From 31c78a5ed7429a9c0e5146c9c8f4c502a29ef20e Mon Sep 17 00:00:00 2001 From: lihua <531456470@qq.com> Date: Fri, 9 Aug 2019 08:44:14 +0800 Subject: [PATCH] init --- .gitignore | 2 +- App.vue | 21 + api/device.js | 84 + api/login.js | 20 + common/auth.js | 26 + common/deviceData.js | 22 + common/icon.css | 1226 ++ common/iconfont.css | 74 + common/main.css | 3912 +++++ common/mqtt.js | 14633 ++++++++++++++++ common/mqttClient.js | 40 + common/qiun.css | 114 + common/request.js | 42 + common/uni.css | 1447 ++ components/mehaotian-search/.DS_Store | Bin 0 -> 6148 bytes .../mehaotian-search/mehaotian-search.vue | 182 + components/refresh/refresh.vue | 174 + components/uni-badge/readme.md | 34 + components/uni-badge/uni-badge.vue | 109 + components/uni-fab/uni-fab.vue | 368 + components/uni-icon/readme.md | 35 + components/uni-icon/uni-icon.vue | 421 + components/uni-list-item/uni-list-item.vue | 196 + components/uni-list/readme.md | 88 + components/uni-list/uni-list.vue | 45 + components/uni-nav-bar/uni-nav-bar.vue | 209 + .../uni-segmented-control.vue | 134 + components/uni-status-bar/uni-status-bar.vue | 30 + components/wuc-tab/wuc-tab.vue | 133 + js_sdk/luch-request/index.js | 57 + js_sdk/luch-request/readme.md | 148 + js_sdk/luch-request/request.js | 111 + js_sdk/u-charts/u-charts/component.vue | 165 + js_sdk/u-charts/u-charts/u-charts.js | 4383 +++++ js_sdk/u-charts/u-charts/u-charts.min.js | 1 + main.js | 14 + manifest.json | 76 + pages.json | 79 + pages/device/detail/device-info.vue | 50 + pages/device/detail/index.vue | 78 + pages/device/detail/real-data.vue | 35 + pages/device/device.vue | 180 + pages/home/home.vue | 229 + pages/location/location.vue | 38 + pages/login/login.vue | 177 + pages/user/user.vue | 208 + static/banner1.png | Bin 0 -> 143948 bytes static/banner2.png | Bin 0 -> 111673 bytes static/device.png | Bin 0 -> 3841 bytes static/device_active.png | Bin 0 -> 3887 bytes static/dtu.png | Bin 0 -> 5847 bytes static/gateway.png | Bin 0 -> 2418 bytes static/head.png | Bin 0 -> 2749 bytes static/home.png | Bin 0 -> 2461 bytes static/home_active.png | Bin 0 -> 2423 bytes static/humiture.png | Bin 0 -> 1873 bytes static/icon_del.png | Bin 0 -> 975 bytes static/icon_pwd.png | Bin 0 -> 635 bytes static/icon_pwd_switch.png | Bin 0 -> 842 bytes static/icon_user.png | Bin 0 -> 1512 bytes static/location.png | Bin 0 -> 3872 bytes static/location_active.png | Bin 0 -> 3860 bytes static/logo.png | Bin 0 -> 4023 bytes static/user.png | Bin 0 -> 2590 bytes static/user_active.png | Bin 0 -> 2621 bytes store/getters.js | 7 + store/index.js | 15 + store/user.js | 87 + uni.scss | 106 + 69 files changed, 30064 insertions(+), 1 deletion(-) create mode 100644 App.vue create mode 100644 api/device.js create mode 100644 api/login.js create mode 100644 common/auth.js create mode 100644 common/deviceData.js create mode 100644 common/icon.css create mode 100644 common/iconfont.css create mode 100644 common/main.css create mode 100644 common/mqtt.js create mode 100644 common/mqttClient.js create mode 100644 common/qiun.css create mode 100644 common/request.js create mode 100644 common/uni.css create mode 100644 components/mehaotian-search/.DS_Store create mode 100644 components/mehaotian-search/mehaotian-search.vue create mode 100644 components/refresh/refresh.vue create mode 100644 components/uni-badge/readme.md create mode 100644 components/uni-badge/uni-badge.vue create mode 100644 components/uni-fab/uni-fab.vue create mode 100644 components/uni-icon/readme.md create mode 100644 components/uni-icon/uni-icon.vue create mode 100644 components/uni-list-item/uni-list-item.vue create mode 100644 components/uni-list/readme.md create mode 100644 components/uni-list/uni-list.vue create mode 100644 components/uni-nav-bar/uni-nav-bar.vue create mode 100644 components/uni-segmented-control/uni-segmented-control.vue create mode 100644 components/uni-status-bar/uni-status-bar.vue create mode 100644 components/wuc-tab/wuc-tab.vue create mode 100644 js_sdk/luch-request/index.js create mode 100644 js_sdk/luch-request/readme.md create mode 100644 js_sdk/luch-request/request.js create mode 100644 js_sdk/u-charts/u-charts/component.vue create mode 100644 js_sdk/u-charts/u-charts/u-charts.js create mode 100644 js_sdk/u-charts/u-charts/u-charts.min.js create mode 100644 main.js create mode 100644 manifest.json create mode 100644 pages.json create mode 100644 pages/device/detail/device-info.vue create mode 100644 pages/device/detail/index.vue create mode 100644 pages/device/detail/real-data.vue create mode 100644 pages/device/device.vue create mode 100644 pages/home/home.vue create mode 100644 pages/location/location.vue create mode 100644 pages/login/login.vue create mode 100644 pages/user/user.vue create mode 100644 static/banner1.png create mode 100644 static/banner2.png create mode 100644 static/device.png create mode 100644 static/device_active.png create mode 100644 static/dtu.png create mode 100644 static/gateway.png create mode 100644 static/head.png create mode 100644 static/home.png create mode 100644 static/home_active.png create mode 100644 static/humiture.png create mode 100644 static/icon_del.png create mode 100644 static/icon_pwd.png create mode 100644 static/icon_pwd_switch.png create mode 100644 static/icon_user.png create mode 100644 static/location.png create mode 100644 static/location_active.png create mode 100644 static/logo.png create mode 100644 static/user.png create mode 100644 static/user_active.png create mode 100644 store/getters.js create mode 100644 store/index.js create mode 100644 store/user.js create mode 100644 uni.scss diff --git a/.gitignore b/.gitignore index 144585f..fefbeb9 100644 --- a/.gitignore +++ b/.gitignore @@ -75,4 +75,4 @@ typings/ # FuseBox cache .fusebox/ - +unpackage diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..e617aa9 --- /dev/null +++ b/App.vue @@ -0,0 +1,21 @@ + + + diff --git a/api/device.js b/api/device.js new file mode 100644 index 0000000..8784a24 --- /dev/null +++ b/api/device.js @@ -0,0 +1,84 @@ +import http from '@/common/request' +import deviceData from '@/common/deviceData' + +export function getDeviceList(productId) { + let data = {} + if(productId){ + data.productId = productId + } + return http.get('/device/list',data) +} + +export function getDeviceInfo(productId, deviceName) { + return http.get(`/device/find/${productId}/${deviceName}`) +} +export function controlDeviceCmd(productId, deviceName, cmd) { + return deviceCmd({ + url: '/device/cmd/simple', + method: 'post', + params: { + productId: productId, + deviceName: deviceName + }, + data: cmd + }) +} + +export function getDeviceLatestUpMessage(productId, deviceName) { + return deviceData.get(`/device/message/find/one/up/${productId}/${deviceName}`) +} + +export function getDeviceAllUpMessage(productId, deviceName, pageNum, pageSize) { + let data = {}; + if(deviceName){ + data.deviceName = deviceName + } + if(pageNum){ + data.pageNum = pageNum + } + if(pageSize){ + data.pageSize = pageSize + } + return deviceData.get(`/device/message/find/all/up/${productId}`,data) +} + +export function getDeviceAllDownMessage(productId, deviceName, pageNum, pageSize) { + return deviceData({ + url: `/device/message/find/all/down/${productId}`, + params: { + deviceName: deviceName, + pageNum: pageNum, + pageSize: pageSize + }, + method: 'get' + }) +} + +export function statisticsDevice(productId) { + let data = {} + if(productId){ + data.productId = productId + } + return http.get('/device/statistics',data) +} + +export function getSubDeviceList(devicePid) { + return request({ + url: `/device/list/sub/${devicePid}`, + method: 'get' + }) +} + +export function addSubDevice(deviceId, devicePid) { + return request({ + url: `/device/add/sub/${deviceId}/${devicePid}`, + method: 'post' + }) +} + +export function deleteSubDevice(deviceId, devicePid) { + return request({ + url: `/device/delete/sub/${deviceId}/${devicePid}`, + method: 'delete' + }) +} diff --git a/api/login.js b/api/login.js new file mode 100644 index 0000000..e54ee46 --- /dev/null +++ b/api/login.js @@ -0,0 +1,20 @@ +import http from '@/common/request' + +export function login(username, password) { + return http.post('/user/login', {name: username, password: password} ) +} + +export function getInfo(token) { + return request({ + url: '/user/info', + method: 'get', + params: { token } + }) +} + +export function logout() { + return request({ + url: '/user/logout', + method: 'post' + }) +} diff --git a/common/auth.js b/common/auth.js new file mode 100644 index 0000000..45d8cae --- /dev/null +++ b/common/auth.js @@ -0,0 +1,26 @@ +const TokenKey = 'iotx_token' + +export function getToken() { + try { + return uni.getStorageSync(TokenKey); + } catch (e) { + console.error('getToken failed '); + } + return null; +} + +export function setToken(token) { + try { + uni.setStorageSync(TokenKey, token); + } catch (e) { + console.error('setToken failed '+token); + } +} + +export function removeToken() { + try { + uni.removeStorageSync(TokenKey); + } catch (e) { + console.error('removeToken failed '); + } +} diff --git a/common/deviceData.js b/common/deviceData.js new file mode 100644 index 0000000..bdc5559 --- /dev/null +++ b/common/deviceData.js @@ -0,0 +1,22 @@ +import Request from '@/js_sdk/luch-request/request' +const http = new Request(); + +http.setConfig((config) => { /* 设置全局配置 */ + config.baseUrl = 'http://39.98.253.192/data'; /* 根域名不同 */ + return config; +}) + +http.interceptor.request((config, cancel) => { + return config; +}) + +http.interceptor.response((response) => { /* 请求之后拦截器 */ + const res = response.data + if (res.code !== 0) { + uni.showToast({title: res.msg, duration:2000}) + return Promise.reject('error') + } else { + return res + } +}) +export default http; \ No newline at end of file diff --git a/common/icon.css b/common/icon.css new file mode 100644 index 0000000..16ed121 --- /dev/null +++ b/common/icon.css @@ -0,0 +1,1226 @@ +@keyframes cuIcon-spin { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +.cuIconfont-spin { + -webkit-animation: cuIcon-spin 2s infinite linear; + animation: cuIcon-spin 2s infinite linear; + display: inline-block; +} + +.cuIconfont-pulse { + -webkit-animation: cuIcon-spin 1s infinite steps(8); + animation: cuIcon-spin 1s infinite steps(8); + display: inline-block; +} + +[class*="cuIcon-"] { + font-family: "cuIcon"; + font-size: inherit; + font-style: normal; +} + +@font-face { + font-family: "cuIcon"; + src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831'); + /* IE9*/ + src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831#iefix') format('embedded-opentype'), + /* IE6-IE8 */ + url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), + url('//at.alicdn.com/t/font_533566_yfq2d9wdij.ttf?t=1545239985831') format('truetype'), + /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('//at.alicdn.com/t/font_533566_yfq2d9wdij.svg?t=1545239985831#cuIconfont') format('svg'); + /* iOS 4.1- */ +} + +.cuIcon-appreciate:before { + content: "\e644"; +} + +.cuIcon-check:before { + content: "\e645"; +} + +.cuIcon-close:before { + content: "\e646"; +} + +.cuIcon-edit:before { + content: "\e649"; +} + +.cuIcon-emoji:before { + content: "\e64a"; +} + +.cuIcon-favorfill:before { + content: "\e64b"; +} + +.cuIcon-favor:before { + content: "\e64c"; +} + +.cuIcon-loading:before { + content: "\e64f"; +} + +.cuIcon-locationfill:before { + content: "\e650"; +} + +.cuIcon-location:before { + content: "\e651"; +} + +.cuIcon-phone:before { + content: "\e652"; +} + +.cuIcon-roundcheckfill:before { + content: "\e656"; +} + +.cuIcon-roundcheck:before { + content: "\e657"; +} + +.cuIcon-roundclosefill:before { + content: "\e658"; +} + +.cuIcon-roundclose:before { + content: "\e659"; +} + +.cuIcon-roundrightfill:before { + content: "\e65a"; +} + +.cuIcon-roundright:before { + content: "\e65b"; +} + +.cuIcon-search:before { + content: "\e65c"; +} + +.cuIcon-taxi:before { + content: "\e65d"; +} + +.cuIcon-timefill:before { + content: "\e65e"; +} + +.cuIcon-time:before { + content: "\e65f"; +} + +.cuIcon-unfold:before { + content: "\e661"; +} + +.cuIcon-warnfill:before { + content: "\e662"; +} + +.cuIcon-warn:before { + content: "\e663"; +} + +.cuIcon-camerafill:before { + content: "\e664"; +} + +.cuIcon-camera:before { + content: "\e665"; +} + +.cuIcon-commentfill:before { + content: "\e666"; +} + +.cuIcon-comment:before { + content: "\e667"; +} + +.cuIcon-likefill:before { + content: "\e668"; +} + +.cuIcon-like:before { + content: "\e669"; +} + +.cuIcon-notificationfill:before { + content: "\e66a"; +} + +.cuIcon-notification:before { + content: "\e66b"; +} + +.cuIcon-order:before { + content: "\e66c"; +} + +.cuIcon-samefill:before { + content: "\e66d"; +} + +.cuIcon-same:before { + content: "\e66e"; +} + +.cuIcon-deliver:before { + content: "\e671"; +} + +.cuIcon-evaluate:before { + content: "\e672"; +} + +.cuIcon-pay:before { + content: "\e673"; +} + +.cuIcon-send:before { + content: "\e675"; +} + +.cuIcon-shop:before { + content: "\e676"; +} + +.cuIcon-ticket:before { + content: "\e677"; +} + +.cuIcon-back:before { + content: "\e679"; +} + +.cuIcon-cascades:before { + content: "\e67c"; +} + +.cuIcon-discover:before { + content: "\e67e"; +} + +.cuIcon-list:before { + content: "\e682"; +} + +.cuIcon-more:before { + content: "\e684"; +} + +.cuIcon-scan:before { + content: "\e689"; +} + +.cuIcon-settings:before { + content: "\e68a"; +} + +.cuIcon-questionfill:before { + content: "\e690"; +} + +.cuIcon-question:before { + content: "\e691"; +} + +.cuIcon-shopfill:before { + content: "\e697"; +} + +.cuIcon-form:before { + content: "\e699"; +} + +.cuIcon-pic:before { + content: "\e69b"; +} + +.cuIcon-filter:before { + content: "\e69c"; +} + +.cuIcon-footprint:before { + content: "\e69d"; +} + +.cuIcon-top:before { + content: "\e69e"; +} + +.cuIcon-pulldown:before { + content: "\e69f"; +} + +.cuIcon-pullup:before { + content: "\e6a0"; +} + +.cuIcon-right:before { + content: "\e6a3"; +} + +.cuIcon-refresh:before { + content: "\e6a4"; +} + +.cuIcon-moreandroid:before { + content: "\e6a5"; +} + +.cuIcon-deletefill:before { + content: "\e6a6"; +} + +.cuIcon-refund:before { + content: "\e6ac"; +} + +.cuIcon-cart:before { + content: "\e6af"; +} + +.cuIcon-qrcode:before { + content: "\e6b0"; +} + +.cuIcon-remind:before { + content: "\e6b2"; +} + +.cuIcon-delete:before { + content: "\e6b4"; +} + +.cuIcon-profile:before { + content: "\e6b7"; +} + +.cuIcon-home:before { + content: "\e6b8"; +} + +.cuIcon-cartfill:before { + content: "\e6b9"; +} + +.cuIcon-discoverfill:before { + content: "\e6ba"; +} + +.cuIcon-homefill:before { + content: "\e6bb"; +} + +.cuIcon-message:before { + content: "\e6bc"; +} + +.cuIcon-addressbook:before { + content: "\e6bd"; +} + +.cuIcon-link:before { + content: "\e6bf"; +} + +.cuIcon-lock:before { + content: "\e6c0"; +} + +.cuIcon-unlock:before { + content: "\e6c2"; +} + +.cuIcon-vip:before { + content: "\e6c3"; +} + +.cuIcon-weibo:before { + content: "\e6c4"; +} + +.cuIcon-activity:before { + content: "\e6c5"; +} + +.cuIcon-friendaddfill:before { + content: "\e6c9"; +} + +.cuIcon-friendadd:before { + content: "\e6ca"; +} + +.cuIcon-friendfamous:before { + content: "\e6cb"; +} + +.cuIcon-friend:before { + content: "\e6cc"; +} + +.cuIcon-goods:before { + content: "\e6cd"; +} + +.cuIcon-selection:before { + content: "\e6ce"; +} + +.cuIcon-explore:before { + content: "\e6d2"; +} + +.cuIcon-present:before { + content: "\e6d3"; +} + +.cuIcon-squarecheckfill:before { + content: "\e6d4"; +} + +.cuIcon-square:before { + content: "\e6d5"; +} + +.cuIcon-squarecheck:before { + content: "\e6d6"; +} + +.cuIcon-round:before { + content: "\e6d7"; +} + +.cuIcon-roundaddfill:before { + content: "\e6d8"; +} + +.cuIcon-roundadd:before { + content: "\e6d9"; +} + +.cuIcon-add:before { + content: "\e6da"; +} + +.cuIcon-notificationforbidfill:before { + content: "\e6db"; +} + +.cuIcon-explorefill:before { + content: "\e6dd"; +} + +.cuIcon-fold:before { + content: "\e6de"; +} + +.cuIcon-game:before { + content: "\e6df"; +} + +.cuIcon-redpacket:before { + content: "\e6e0"; +} + +.cuIcon-selectionfill:before { + content: "\e6e1"; +} + +.cuIcon-similar:before { + content: "\e6e2"; +} + +.cuIcon-appreciatefill:before { + content: "\e6e3"; +} + +.cuIcon-infofill:before { + content: "\e6e4"; +} + +.cuIcon-info:before { + content: "\e6e5"; +} + +.cuIcon-forwardfill:before { + content: "\e6ea"; +} + +.cuIcon-forward:before { + content: "\e6eb"; +} + +.cuIcon-rechargefill:before { + content: "\e6ec"; +} + +.cuIcon-recharge:before { + content: "\e6ed"; +} + +.cuIcon-vipcard:before { + content: "\e6ee"; +} + +.cuIcon-voice:before { + content: "\e6ef"; +} + +.cuIcon-voicefill:before { + content: "\e6f0"; +} + +.cuIcon-friendfavor:before { + content: "\e6f1"; +} + +.cuIcon-wifi:before { + content: "\e6f2"; +} + +.cuIcon-share:before { + content: "\e6f3"; +} + +.cuIcon-wefill:before { + content: "\e6f4"; +} + +.cuIcon-we:before { + content: "\e6f5"; +} + +.cuIcon-lightauto:before { + content: "\e6f6"; +} + +.cuIcon-lightforbid:before { + content: "\e6f7"; +} + +.cuIcon-lightfill:before { + content: "\e6f8"; +} + +.cuIcon-camerarotate:before { + content: "\e6f9"; +} + +.cuIcon-light:before { + content: "\e6fa"; +} + +.cuIcon-barcode:before { + content: "\e6fb"; +} + +.cuIcon-flashlightclose:before { + content: "\e6fc"; +} + +.cuIcon-flashlightopen:before { + content: "\e6fd"; +} + +.cuIcon-searchlist:before { + content: "\e6fe"; +} + +.cuIcon-service:before { + content: "\e6ff"; +} + +.cuIcon-sort:before { + content: "\e700"; +} + +.cuIcon-down:before { + content: "\e703"; +} + +.cuIcon-mobile:before { + content: "\e704"; +} + +.cuIcon-mobilefill:before { + content: "\e705"; +} + +.cuIcon-copy:before { + content: "\e706"; +} + +.cuIcon-countdownfill:before { + content: "\e707"; +} + +.cuIcon-countdown:before { + content: "\e708"; +} + +.cuIcon-noticefill:before { + content: "\e709"; +} + +.cuIcon-notice:before { + content: "\e70a"; +} + +.cuIcon-upstagefill:before { + content: "\e70e"; +} + +.cuIcon-upstage:before { + content: "\e70f"; +} + +.cuIcon-babyfill:before { + content: "\e710"; +} + +.cuIcon-baby:before { + content: "\e711"; +} + +.cuIcon-brandfill:before { + content: "\e712"; +} + +.cuIcon-brand:before { + content: "\e713"; +} + +.cuIcon-choicenessfill:before { + content: "\e714"; +} + +.cuIcon-choiceness:before { + content: "\e715"; +} + +.cuIcon-clothesfill:before { + content: "\e716"; +} + +.cuIcon-clothes:before { + content: "\e717"; +} + +.cuIcon-creativefill:before { + content: "\e718"; +} + +.cuIcon-creative:before { + content: "\e719"; +} + +.cuIcon-female:before { + content: "\e71a"; +} + +.cuIcon-keyboard:before { + content: "\e71b"; +} + +.cuIcon-male:before { + content: "\e71c"; +} + +.cuIcon-newfill:before { + content: "\e71d"; +} + +.cuIcon-new:before { + content: "\e71e"; +} + +.cuIcon-pullleft:before { + content: "\e71f"; +} + +.cuIcon-pullright:before { + content: "\e720"; +} + +.cuIcon-rankfill:before { + content: "\e721"; +} + +.cuIcon-rank:before { + content: "\e722"; +} + +.cuIcon-bad:before { + content: "\e723"; +} + +.cuIcon-cameraadd:before { + content: "\e724"; +} + +.cuIcon-focus:before { + content: "\e725"; +} + +.cuIcon-friendfill:before { + content: "\e726"; +} + +.cuIcon-cameraaddfill:before { + content: "\e727"; +} + +.cuIcon-apps:before { + content: "\e729"; +} + +.cuIcon-paintfill:before { + content: "\e72a"; +} + +.cuIcon-paint:before { + content: "\e72b"; +} + +.cuIcon-picfill:before { + content: "\e72c"; +} + +.cuIcon-refresharrow:before { + content: "\e72d"; +} + +.cuIcon-colorlens:before { + content: "\e6e6"; +} + +.cuIcon-markfill:before { + content: "\e730"; +} + +.cuIcon-mark:before { + content: "\e731"; +} + +.cuIcon-presentfill:before { + content: "\e732"; +} + +.cuIcon-repeal:before { + content: "\e733"; +} + +.cuIcon-album:before { + content: "\e734"; +} + +.cuIcon-peoplefill:before { + content: "\e735"; +} + +.cuIcon-people:before { + content: "\e736"; +} + +.cuIcon-servicefill:before { + content: "\e737"; +} + +.cuIcon-repair:before { + content: "\e738"; +} + +.cuIcon-file:before { + content: "\e739"; +} + +.cuIcon-repairfill:before { + content: "\e73a"; +} + +.cuIcon-taoxiaopu:before { + content: "\e73b"; +} + +.cuIcon-weixin:before { + content: "\e612"; +} + +.cuIcon-attentionfill:before { + content: "\e73c"; +} + +.cuIcon-attention:before { + content: "\e73d"; +} + +.cuIcon-commandfill:before { + content: "\e73e"; +} + +.cuIcon-command:before { + content: "\e73f"; +} + +.cuIcon-communityfill:before { + content: "\e740"; +} + +.cuIcon-community:before { + content: "\e741"; +} + +.cuIcon-read:before { + content: "\e742"; +} + +.cuIcon-calendar:before { + content: "\e74a"; +} + +.cuIcon-cut:before { + content: "\e74b"; +} + +.cuIcon-magic:before { + content: "\e74c"; +} + +.cuIcon-backwardfill:before { + content: "\e74d"; +} + +.cuIcon-playfill:before { + content: "\e74f"; +} + +.cuIcon-stop:before { + content: "\e750"; +} + +.cuIcon-tagfill:before { + content: "\e751"; +} + +.cuIcon-tag:before { + content: "\e752"; +} + +.cuIcon-group:before { + content: "\e753"; +} + +.cuIcon-all:before { + content: "\e755"; +} + +.cuIcon-backdelete:before { + content: "\e756"; +} + +.cuIcon-hotfill:before { + content: "\e757"; +} + +.cuIcon-hot:before { + content: "\e758"; +} + +.cuIcon-post:before { + content: "\e759"; +} + +.cuIcon-radiobox:before { + content: "\e75b"; +} + +.cuIcon-rounddown:before { + content: "\e75c"; +} + +.cuIcon-upload:before { + content: "\e75d"; +} + +.cuIcon-writefill:before { + content: "\e760"; +} + +.cuIcon-write:before { + content: "\e761"; +} + +.cuIcon-radioboxfill:before { + content: "\e763"; +} + +.cuIcon-punch:before { + content: "\e764"; +} + +.cuIcon-shake:before { + content: "\e765"; +} + +.cuIcon-move:before { + content: "\e768"; +} + +.cuIcon-safe:before { + content: "\e769"; +} + +.cuIcon-activityfill:before { + content: "\e775"; +} + +.cuIcon-crownfill:before { + content: "\e776"; +} + +.cuIcon-crown:before { + content: "\e777"; +} + +.cuIcon-goodsfill:before { + content: "\e778"; +} + +.cuIcon-messagefill:before { + content: "\e779"; +} + +.cuIcon-profilefill:before { + content: "\e77a"; +} + +.cuIcon-sound:before { + content: "\e77b"; +} + +.cuIcon-sponsorfill:before { + content: "\e77c"; +} + +.cuIcon-sponsor:before { + content: "\e77d"; +} + +.cuIcon-upblock:before { + content: "\e77e"; +} + +.cuIcon-weblock:before { + content: "\e77f"; +} + +.cuIcon-weunblock:before { + content: "\e780"; +} + +.cuIcon-my:before { + content: "\e78b"; +} + +.cuIcon-myfill:before { + content: "\e78c"; +} + +.cuIcon-emojifill:before { + content: "\e78d"; +} + +.cuIcon-emojiflashfill:before { + content: "\e78e"; +} + +.cuIcon-flashbuyfill:before { + content: "\e78f"; +} + +.cuIcon-text:before { + content: "\e791"; +} + +.cuIcon-goodsfavor:before { + content: "\e794"; +} + +.cuIcon-musicfill:before { + content: "\e795"; +} + +.cuIcon-musicforbidfill:before { + content: "\e796"; +} + +.cuIcon-card:before { + content: "\e624"; +} + +.cuIcon-triangledownfill:before { + content: "\e79b"; +} + +.cuIcon-triangleupfill:before { + content: "\e79c"; +} + +.cuIcon-roundleftfill-copy:before { + content: "\e79e"; +} + +.cuIcon-font:before { + content: "\e76a"; +} + +.cuIcon-title:before { + content: "\e82f"; +} + +.cuIcon-recordfill:before { + content: "\e7a4"; +} + +.cuIcon-record:before { + content: "\e7a6"; +} + +.cuIcon-cardboardfill:before { + content: "\e7a9"; +} + +.cuIcon-cardboard:before { + content: "\e7aa"; +} + +.cuIcon-formfill:before { + content: "\e7ab"; +} + +.cuIcon-coin:before { + content: "\e7ac"; +} + +.cuIcon-cardboardforbid:before { + content: "\e7af"; +} + +.cuIcon-circlefill:before { + content: "\e7b0"; +} + +.cuIcon-circle:before { + content: "\e7b1"; +} + +.cuIcon-attentionforbid:before { + content: "\e7b2"; +} + +.cuIcon-attentionforbidfill:before { + content: "\e7b3"; +} + +.cuIcon-attentionfavorfill:before { + content: "\e7b4"; +} + +.cuIcon-attentionfavor:before { + content: "\e7b5"; +} + +.cuIcon-titles:before { + content: "\e701"; +} + +.cuIcon-icloading:before { + content: "\e67a"; +} + +.cuIcon-full:before { + content: "\e7bc"; +} + +.cuIcon-mail:before { + content: "\e7bd"; +} + +.cuIcon-peoplelist:before { + content: "\e7be"; +} + +.cuIcon-goodsnewfill:before { + content: "\e7bf"; +} + +.cuIcon-goodsnew:before { + content: "\e7c0"; +} + +.cuIcon-medalfill:before { + content: "\e7c1"; +} + +.cuIcon-medal:before { + content: "\e7c2"; +} + +.cuIcon-newsfill:before { + content: "\e7c3"; +} + +.cuIcon-newshotfill:before { + content: "\e7c4"; +} + +.cuIcon-newshot:before { + content: "\e7c5"; +} + +.cuIcon-news:before { + content: "\e7c6"; +} + +.cuIcon-videofill:before { + content: "\e7c7"; +} + +.cuIcon-video:before { + content: "\e7c8"; +} + +.cuIcon-exit:before { + content: "\e7cb"; +} + +.cuIcon-skinfill:before { + content: "\e7cc"; +} + +.cuIcon-skin:before { + content: "\e7cd"; +} + +.cuIcon-moneybagfill:before { + content: "\e7ce"; +} + +.cuIcon-usefullfill:before { + content: "\e7cf"; +} + +.cuIcon-usefull:before { + content: "\e7d0"; +} + +.cuIcon-moneybag:before { + content: "\e7d1"; +} + +.cuIcon-redpacket_fill:before { + content: "\e7d3"; +} + +.cuIcon-subscription:before { + content: "\e7d4"; +} + +.cuIcon-loading1:before { + content: "\e633"; +} + +.cuIcon-github:before { + content: "\e692"; +} + +.cuIcon-global:before { + content: "\e7eb"; +} + +.cuIcon-settingsfill:before { + content: "\e6ab"; +} + +.cuIcon-back_android:before { + content: "\e7ed"; +} + +.cuIcon-expressman:before { + content: "\e7ef"; +} + +.cuIcon-evaluate_fill:before { + content: "\e7f0"; +} + +.cuIcon-group_fill:before { + content: "\e7f5"; +} + +.cuIcon-play_forward_fill:before { + content: "\e7f6"; +} + +.cuIcon-deliver_fill:before { + content: "\e7f7"; +} + +.cuIcon-notice_forbid_fill:before { + content: "\e7f8"; +} + +.cuIcon-fork:before { + content: "\e60c"; +} + +.cuIcon-pick:before { + content: "\e7fa"; +} + +.cuIcon-wenzi:before { + content: "\e6a7"; +} + +.cuIcon-ellipse:before { + content: "\e600"; +} + +.cuIcon-qr_code:before { + content: "\e61b"; +} + +.cuIcon-dianhua:before { + content: "\e64d"; +} + +.cuIcon-cuIcon:before { + content: "\e602"; +} + +.cuIcon-loading2:before { + content: "\e7f1"; +} + +.cuIcon-btn:before { + content: "\e601"; +} diff --git a/common/iconfont.css b/common/iconfont.css new file mode 100644 index 0000000..a78ab59 --- /dev/null +++ b/common/iconfont.css @@ -0,0 +1,74 @@ +@font-face { + font-family: "iconfont"; + src: url('//at.alicdn.com/t/font_1339011_fnx8kfgj0pj.eot?t=1565167418581'); /* IE9 */ + src: url('//at.alicdn.com/t/font_1339011_fnx8kfgj0pj.eot?t=1565167418581#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAwMAAsAAAAAFfAAAAu8AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCEbgqbYJZBATYCJAM8CyAABCAFhG0HgX4bZxIjkjBWFtlfHRh619RhnXa6spLe6UhyxCeuqPiLkn5hO5Iv6kd6n4Mnfq29+XYq8dC4iWqWRKOINbInSJEkljJtDgmdDYBLnYZgbrtqLZnGbOUNcH9LLzDoffLLTvLz/Db/3FfAeyCohIpidGBsbeMacxH12Br+b0LnyuhVBLGKQNgGMq3sQjHw09qvKhpFow7eCIWUKWne/4uMILPoYL4fca+ERCak3Y/ZgJ9oEg3R6sUL6UK6Eq/EC7mfhW3GbGqCBfOg1tdxN0OANA0iZGRsfJ4kDpkKeh3sbq+S9OXiUvyEZFaIOdUhD3iS5s6cAe7NHy9/dMkGDN4i32p6a3SDAeVv2bIxu2D/4KY6CVzOAgtEgAN5ii15tDaJTJaOG+i4hDpFVhnUqfZrqGmLDuucbjY//+b+luNYoamUlIU6jf/Ag4AnTZYcQh5HggwWQ5IUSEBmWfJ8ac6DoiUigIrAgxsI0uAWgiy4gyAHHkApwmuwV8dbQBHjwxAkwOcgyIBvIhEWmp+JMPA3J0iafBnFpJBZgZ/SAIbAXYD/ApkbZokjLLa0eEUGkiQtAhXfebY8mkZ8Pz8Rj89PcHDgohJUIlGElA8Q27vwCb49IQ915/H4Mhniu5I9rp+DvZ23c4gdn768maNb9joX02hZp19F6w4nom6nf2VblxxnymrX+Izasg9xNLbRug62Xdup6So9avGkNSs7t9HIYimhNdZLVnqoneVhie2xyvqo1PxgtNXKjzYXs5ZEg0lmMkp3WVGTLa/AEaw5Qa+XGAyMQXba1j8ZimoAYWmzqbzlrLkXwftSVmuZZp92D7BrfcGgk6G29cXGxm2dqJ9pflDcHJl2Bwu8r9L8YAiyWUut5uJWessF1xNmiyUHHbNabckyWf1+f53EV77ZlnPUAsB05TWsNmfTwBy3eTdac8vqbXkmA4BebDwToadprTGvvsv/G8WK9e3iY3R1+lapxsSokEZK6zMKWssp7ZawDEM3orViMEgYkwwZadooRSYZo4MvQppBBgmwEkYnKUb04kRXiU2gmGGKg5pDdKUDlwBsnQ40ljWb2z8Qr9+90xnbaimZNGLuobSp8OkxtVlKGF1drZgGxmAko7UIudcC8yOTpPjwjjhi9sDEF8wlFovKZpsJh+VhYNfjCS49ZvXCU6829zNA7QntKReN7MgJpzqLziZfdkqFa/br9rph3ckKwgjVDjOQEkC1VSEdB93GEYrXrDocPH7OdKl+Zp3OIBhyIFvXomurR0v4iDNRf7uyWoAVe2OF2/e7I80YQYndeDskHMUArdKKZ/K1E3SJZVJjOwCrp/nadieo6/AVrkRYmflq7cxnMxalzzCh8CaDe3OkvkNiapOtsuksboYWialrVRF1QPsWG1p0YKUiG4byN+swWitFGmOrfiZtNRsdjEDX1Q2ocYxRY9IZWD1jUfoMSwNv0n8irPR1jM4kW3Ved9Zt1XbQ1UsbrepAao3BBp3p7zBMYQ4CVW9/8OtQRkQ+Go6qJnQdw5HtsT+glofqCh9hl1VstaYtn9mpDajS13a0yGQYu9eXQfVdbT+9A4Bp249wQ1vXMunQc1ZVZ6XF3It3ZNtpkbYTbRHIZC0pwdg1tKi1E+EqU74jjAjX1LfpWuoAY8UCH6lfCCtnjB2lFUfoDYywvz9NlJEubm5nO3yZti5Npx/tvgdu05TcI6oIEl7WHxEni46pyvdLVkr2qY+FFJwm4qSQTB5STlny9ct9UVxu9PPddl6uysuhS+8WFgqCJR/ODpYsqEQLF2CVEX6uypxsuR/8ngtx1cPjKiFhvo64Sv023UF9aob2AcKkhvrERKseZx4uFqdmVwXlBiqKS+7c0V62IiQopyIrReYzCc/H6Zji7YUzsKYmbAYUFi7u5pN1uESckp3hlTsFemAj//1nhJ6BkQUa2T1v2rvMVKlvjt8okedXtBjyyRnNTXEy15qkGlenLUMPCT2Ex6o2K+k3jnKli1LuCB442zHN7SdounaaEAgIPeP0GZDO3myYAwXdS8fmifKEc1Lds/o7j2OnVCapRZOKeja54so0gTq8z8UH4b2bLjh+mblj5+jYF697DMn0lDtkKO3ttSoHrpw7XjkKBV7BXYsoLqLndo9onEtmvGnwFxMcImZC8fUcDyXBJTMvZw0KvQw8tp0ed1bKpaZRsoMsld+QT6WS+YsoqidJBeRzFlNUitTOjsoPoEjFkf9/PsmJ60gKyPwUikxxmeASlzEBGXIuwikakC/P51PTKb5pEwuNPZ5cVrQwn2QdqYVUeEEBlSCpAg7+EABsV3RGt2q6T7ykKrzobQU1dTFVMTsia0kQDBr71wDZAMemniFFAcU+G3JTkyBvYHkekQeV/cm8WP7RIxuinaI3bNnKPyvyt27ZEN33aMSwlOiY4LI5poLI7Ax7e+0lRRaYDnj+rcj1ylmQ2VPY037gRHC/P2I+tn0NPs9xsXimZ6ZiqqPO7b97zezjF/L7usrhc+GAj9xVIWCxmCDPDjhLko7O67HQaf7bVaVQh1VwW795zsjUwjetRNa9u3ocDuWI3JSnIstiUNHo0UVYIcYPQ0Uxkard596nE/K+fTc2QEFOpL+XpubAgIEoh9f77zO1tRI23yTkDBzo4hg+KH6Qapbo+36P/d9FLvYx9pA8vgFWesfrnQ47fUA3RTc8bqIPDl13raqGBetzbny4sTS/QKYN+pEQ87bCi5xKjhe8O3gnSjjB2cFLeob8RZ7JX5nPmhbct7N3VUShgBE50/WZQXkh88JV4TWeBzUldkqF9M0GQdByZYJabb88SLDhjVQB85qSoQcOCOX8ij/nViEFc2ybyYWuPgrhjA2r5mCECZNQ+OzEdv/kFYXiip5BsnXkFVfp2ctLPG4hb23kS7qIy7v0Jlu0Q6TlPhKZ1s7N9E3xDfEZ8dkU+uwJLH1k+Pll0uG8G+KbayZH9Ej9x+UAwzvJGcfNcVLLTnL5B1xWd08ltLzTXF5u9cDuSMEckxn3tPgczZTNnTgAEaZ/nimjzy2Qkvt9NQCHA0e6F/B3EMYTJ4w4plaePIEbvThoyksEfFZL8ywMzcQM7HyxQC/nFKQilMot+LgBDZw+YwDqhcYOccjrnIWpe8K0WE0DeEeHF8ZlLZ7YwY870F69QFF34dI14qykUnJTcu3KgQ4Fe+pArKADNEufRS4Vd5d2m6zqBQrm2C4Sd4+MsFgQ1HwN+5cPfFcNW9jzqiCmvClStHpMkqa77I1siPqXU7ekeWNW20cQZIPgSE/nAVsEDSRx/fyoeJ1/Hd5ArionfbaJy8iHZB6R60vV34QpPlOgRsSHiL6JanxqRA4v1hbHHEPtoO8v+C0bJ8fB/7CN//h4ORl6JT7y0qFtOV4NrArfhx2D8XM+jptb5v3C56TF+d1RhavD9x3GleGWLjy4hX2Izz4a7gb95v9OWRamfOQy/yDrr55sSGLjmncAFzCQSxHAsU8S1G8ULuqdBiL8UEixm7Op2SuKFMJzGO2oAdd5cOSrcIBbzWVKhLXDbabERRhwwA3hwAUfV8IzBJHAQAyigAvpiIZgyDubAUeYADggggcAQbBQQghEsB5hYAf7EQ4iOOtKeN5EJEjhJaJAhHBEQylyVGTAL0vc7ikgMCpRnoST5LVawDur9zea2EDwpplh/xh6Vy/yJAu2vqHHUMUR/WAKZi10oFa8SrfDpiHRBapQcmKZu0Oa6rgjE0ntZMdwQGAeVwnKU1InyevNeRf6/t9oYgMhZdJX0n8Mvdu+ICchE3B9Y15o0q4M7AdTwCS10IxArZ35yiQ2ShMJuvidKpScYAsY3YGUFtOiLGk+s13vjNU3pfwIBQmp6YYyLdtxPX/MX5W/OrdYols0FGD//vA7gjcmgl+O6FVcKMdx43TrrVNxLWZRXNYRnLSoRMqPzmdfxlVUQb4tmpsvja+6OGHrwN9L6k66s2uDAf3Zkjc5dVJe52MsHdDZRs8Uc0C0M7M2wDjCaTIBAAAA') format('woff2'), + url('//at.alicdn.com/t/font_1339011_fnx8kfgj0pj.woff?t=1565167418581') format('woff'), + url('//at.alicdn.com/t/font_1339011_fnx8kfgj0pj.ttf?t=1565167418581') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ + url('//at.alicdn.com/t/font_1339011_fnx8kfgj0pj.svg?t=1565167418581#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family: "iconfont"; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-shebei:before { + content: "\e606"; +} + +.icon-lora:before { + content: "\e7bd"; +} + +.icon-NATwangguan:before { + content: "\e665"; +} + +.icon-wendu:before { + content: "\e61f"; +} + +.icon-ditu:before { + content: "\e601"; +} + +.icon-wenshidu:before { + content: "\e600"; +} + +.icon-shebei2:before { + content: "\e643"; +} + +.icon-kuaicheduanxinwangguan:before { + content: "\eb53"; +} + +.icon-kuaicheduanxinwangguan1:before { + content: "\eb5f"; +} + +.icon-wenshidu1:before { + content: "\e602"; +} + +.icon-shidu:before { + content: "\e653"; +} + +.icon-yemian-copy-copy-copy:before { + content: "\e603"; +} + +.icon-gerenzhongxinwoderenwubiaozhuntoumianxing:before { + content: "\e604"; +} + +.icon-gateway:before { + content: "\e615"; +} + diff --git a/common/main.css b/common/main.css new file mode 100644 index 0000000..fade3b2 --- /dev/null +++ b/common/main.css @@ -0,0 +1,3912 @@ +/* + ColorUi for uniApp v2.1.6 | by 文晓港 2019-05-31 10:44:24 + 仅供学习交流,如作它用所承受的法律责任一概与作者无关 + + *使用ColorUi开发扩展与插件时,请注明基于ColorUi开发 + + (QQ交流群:240787041) +*/ + +/* ================== + 初始化 + ==================== */ +body { + background-color: #f1f1f1; + font-size: 28upx; + color: #333333; + font-family: Helvetica Neue, Helvetica, sans-serif; +} + +view, +scroll-view, +swiper, +button, +input, +textarea, +label, +navigator, +image { + box-sizing: border-box; +} + +.round { + border-radius: 5000upx; +} + +.radius { + border-radius: 6upx; +} + +/* ================== + 图片 + ==================== */ + +image { + max-width: 100%; + display: inline-block; + position: relative; + z-index: 0; +} + +image.loading::before { + content: ""; + background-color: #f5f5f5; + display: block; + position: absolute; + width: 100%; + height: 100%; + z-index: -2; +} + +image.loading::after { + content: "\e7f1"; + font-family: "cuIcon"; + position: absolute; + top: 0; + left: 0; + width: 32upx; + height: 32upx; + line-height: 32upx; + right: 0; + bottom: 0; + z-index: -1; + font-size: 32upx; + margin: auto; + color: #ccc; + -webkit-animation: cuIcon-spin 2s infinite linear; + animation: cuIcon-spin 2s infinite linear; + display: block; +} + +.response { + width: 100%; +} + +/* ================== + 开关 + ==================== */ + +switch, +checkbox, +radio { + position: relative; +} + +switch::after, +switch::before { + font-family: "cuIcon"; + content: "\e645"; + position: absolute; + color: #ffffff !important; + top: 0%; + left: 0upx; + font-size: 26upx; + line-height: 26px; + width: 50%; + text-align: center; + pointer-events: none; + transform: scale(0, 0); + transition: all 0.3s ease-in-out 0s; + z-index: 9; + bottom: 0; + height: 26px; + margin: auto; +} + +switch::before { + content: "\e646"; + right: 0; + transform: scale(1, 1); + left: auto; +} + +switch[checked]::after, +switch.checked::after { + transform: scale(1, 1); +} + +switch[checked]::before, +switch.checked::before { + transform: scale(0, 0); +} + +/* #ifndef MP-ALIPAY */ +radio::before, +checkbox::before { + font-family: "cuIcon"; + content: "\e645"; + position: absolute; + color: #ffffff !important; + top: 50%; + margin-top: -8px; + right: 5px; + font-size: 32upx; + line-height: 16px; + pointer-events: none; + transform: scale(1, 1); + transition: all 0.3s ease-in-out 0s; + z-index: 9; +} + +radio .wx-radio-input, +checkbox .wx-checkbox-input, +radio .uni-radio-input, +checkbox .uni-checkbox-input { + margin: 0; + width: 24px; + height: 24px; +} + +checkbox.round .wx-checkbox-input, +checkbox.round .uni-checkbox-input { + border-radius: 100upx; +} + +/* #endif */ + +switch[checked]::before { + transform: scale(0, 0); +} + +switch .wx-switch-input, +switch .uni-switch-input { + border: none; + padding: 0 24px; + width: 48px; + height: 26px; + margin: 0; + border-radius: 100upx; +} + +switch .wx-switch-input:not([class*="bg-"]), +switch .uni-switch-input:not([class*="bg-"]) { + background: #8799a3 !important; +} + +switch .wx-switch-input::after, +switch .uni-switch-input::after { + margin: auto; + width: 26px; + height: 26px; + border-radius: 100upx; + left: 0upx; + top: 0upx; + bottom: 0upx; + position: absolute; + transform: scale(0.9, 0.9); + transition: all 0.1s ease-in-out 0s; +} + +switch .wx-switch-input.wx-switch-input-checked::after, +switch .uni-switch-input.uni-switch-input-checked::after { + margin: auto; + left: 22px; + box-shadow: none; + transform: scale(0.9, 0.9); +} + +radio-group { + display: inline-block; +} + + + +switch.radius .wx-switch-input::after, +switch.radius .wx-switch-input, +switch.radius .wx-switch-input::before, +switch.radius .uni-switch-input::after, +switch.radius .uni-switch-input, +switch.radius .uni-switch-input::before { + border-radius: 10upx; +} + +switch .wx-switch-input::before, +radio.radio::before, +checkbox .wx-checkbox-input::before, +radio .wx-radio-input::before, +switch .uni-switch-input::before, +radio.radio::before, +checkbox .uni-checkbox-input::before, +radio .uni-radio-input::before { + display: none; +} + +radio.radio[checked]::after, +radio.radio .uni-radio-input-checked::after { + content: ""; + background-color: transparent; + display: block; + position: absolute; + width: 8px; + height: 8px; + z-index: 999; + top: 0upx; + left: 0upx; + right: 0; + bottom: 0; + margin: auto; + border-radius: 200upx; + /* #ifndef MP */ + border: 7px solid #ffffff !important; + /* #endif */ + + /* #ifdef MP */ + border: 8px solid #ffffff !important; + /* #endif */ +} + +.switch-sex::after { + content: "\e71c"; +} + +.switch-sex::before { + content: "\e71a"; +} + +.switch-sex .wx-switch-input, +.switch-sex .uni-switch-input { + background: #e54d42 !important; + border-color: #e54d42 !important; +} + +.switch-sex[checked] .wx-switch-input, +.switch-sex.checked .uni-switch-input { + background: #0081ff !important; + border-color: #0081ff !important; +} + +switch.red[checked] .wx-switch-input.wx-switch-input-checked, +checkbox.red[checked] .wx-checkbox-input, +radio.red[checked] .wx-radio-input, +switch.red.checked .uni-switch-input.uni-switch-input-checked, +checkbox.red.checked .uni-checkbox-input, +radio.red.checked .uni-radio-input { + background-color: #e54d42 !important; + border-color: #e54d42 !important; + color: #ffffff !important; +} + +switch.orange[checked] .wx-switch-input, +checkbox.orange[checked] .wx-checkbox-input, +radio.orange[checked] .wx-radio-input, +switch.orange.checked .uni-switch-input, +checkbox.orange.checked .uni-checkbox-input, +radio.orange.checked .uni-radio-input { + background-color: #f37b1d !important; + border-color: #f37b1d !important; + color: #ffffff !important; +} + +switch.yellow[checked] .wx-switch-input, +checkbox.yellow[checked] .wx-checkbox-input, +radio.yellow[checked] .wx-radio-input, +switch.yellow.checked .uni-switch-input, +checkbox.yellow.checked .uni-checkbox-input, +radio.yellow.checked .uni-radio-input { + background-color: #fbbd08 !important; + border-color: #fbbd08 !important; + color: #333333 !important; +} + +switch.olive[checked] .wx-switch-input, +checkbox.olive[checked] .wx-checkbox-input, +radio.olive[checked] .wx-radio-input, +switch.olive.checked .uni-switch-input, +checkbox.olive.checked .uni-checkbox-input, +radio.olive.checked .uni-radio-input { + background-color: #8dc63f !important; + border-color: #8dc63f !important; + color: #ffffff !important; +} + +switch.green[checked] .wx-switch-input, +switch[checked] .wx-switch-input, +checkbox.green[checked] .wx-checkbox-input, +checkbox[checked] .wx-checkbox-input, +radio.green[checked] .wx-radio-input, +radio[checked] .wx-radio-input, +switch.green.checked .uni-switch-input, +switch.checked .uni-switch-input, +checkbox.green.checked .uni-checkbox-input, +checkbox.checked .uni-checkbox-input, +radio.green.checked .uni-radio-input, +radio.checked .uni-radio-input { + background-color: #39b54a !important; + border-color: #39b54a !important; + color: #ffffff !important; + border-color: #39B54A !important; +} + +switch.cyan[checked] .wx-switch-input, +checkbox.cyan[checked] .wx-checkbox-input, +radio.cyan[checked] .wx-radio-input, +switch.cyan.checked .uni-switch-input, +checkbox.cyan.checked .uni-checkbox-input, +radio.cyan.checked .uni-radio-input { + background-color: #1cbbb4 !important; + border-color: #1cbbb4 !important; + color: #ffffff !important; +} + +switch.blue[checked] .wx-switch-input, +checkbox.blue[checked] .wx-checkbox-input, +radio.blue[checked] .wx-radio-input, +switch.blue.checked .uni-switch-input, +checkbox.blue.checked .uni-checkbox-input, +radio.blue.checked .uni-radio-input { + background-color: #0081ff !important; + border-color: #0081ff !important; + color: #ffffff !important; +} + +switch.purple[checked] .wx-switch-input, +checkbox.purple[checked] .wx-checkbox-input, +radio.purple[checked] .wx-radio-input, +switch.purple.checked .uni-switch-input, +checkbox.purple.checked .uni-checkbox-input, +radio.purple.checked .uni-radio-input { + background-color: #6739b6 !important; + border-color: #6739b6 !important; + color: #ffffff !important; +} + +switch.mauve[checked] .wx-switch-input, +checkbox.mauve[checked] .wx-checkbox-input, +radio.mauve[checked] .wx-radio-input, +switch.mauve.checked .uni-switch-input, +checkbox.mauve.checked .uni-checkbox-input, +radio.mauve.checked .uni-radio-input { + background-color: #9c26b0 !important; + border-color: #9c26b0 !important; + color: #ffffff !important; +} + +switch.pink[checked] .wx-switch-input, +checkbox.pink[checked] .wx-checkbox-input, +radio.pink[checked] .wx-radio-input, +switch.pink.checked .uni-switch-input, +checkbox.pink.checked .uni-checkbox-input, +radio.pink.checked .uni-radio-input { + background-color: #e03997 !important; + border-color: #e03997 !important; + color: #ffffff !important; +} + +switch.brown[checked] .wx-switch-input, +checkbox.brown[checked] .wx-checkbox-input, +radio.brown[checked] .wx-radio-input, +switch.brown.checked .uni-switch-input, +checkbox.brown.checked .uni-checkbox-input, +radio.brown.checked .uni-radio-input { + background-color: #a5673f !important; + border-color: #a5673f !important; + color: #ffffff !important; +} + +switch.grey[checked] .wx-switch-input, +checkbox.grey[checked] .wx-checkbox-input, +radio.grey[checked] .wx-radio-input, +switch.grey.checked .uni-switch-input, +checkbox.grey.checked .uni-checkbox-input, +radio.grey.checked .uni-radio-input { + background-color: #8799a3 !important; + border-color: #8799a3 !important; + color: #ffffff !important; +} + +switch.gray[checked] .wx-switch-input, +checkbox.gray[checked] .wx-checkbox-input, +radio.gray[checked] .wx-radio-input, +switch.gray.checked .uni-switch-input, +checkbox.gray.checked .uni-checkbox-input, +radio.gray.checked .uni-radio-input { + background-color: #f0f0f0 !important; + border-color: #f0f0f0 !important; + color: #333333 !important; +} + +switch.black[checked] .wx-switch-input, +checkbox.black[checked] .wx-checkbox-input, +radio.black[checked] .wx-radio-input, +switch.black.checked .uni-switch-input, +checkbox.black.checked .uni-checkbox-input, +radio.black.checked .uni-radio-input { + background-color: #333333 !important; + border-color: #333333 !important; + color: #ffffff !important; +} + +switch.white[checked] .wx-switch-input, +checkbox.white[checked] .wx-checkbox-input, +radio.white[checked] .wx-radio-input, +switch.white.checked .uni-switch-input, +checkbox.white.checked .uni-checkbox-input, +radio.white.checked .uni-radio-input { + background-color: #ffffff !important; + border-color: #ffffff !important; + color: #333333 !important; +} + +/* ================== + 边框 + ==================== */ + +/* -- 实线 -- */ + +.solid, +.solid-top, +.solid-right, +.solid-bottom, +.solid-left, +.solids, +.solids-top, +.solids-right, +.solids-bottom, +.solids-left, +.dashed, +.dashed-top, +.dashed-right, +.dashed-bottom, +.dashed-left { + position: relative; +} + +.solid::after, +.solid-top::after, +.solid-right::after, +.solid-bottom::after, +.solid-left::after, +.solids::after, +.solids-top::after, +.solids-right::after, +.solids-bottom::after, +.solids-left::after, +.dashed::after, +.dashed-top::after, +.dashed-right::after, +.dashed-bottom::after, +.dashed-left::after { + content: " "; + width: 200%; + height: 200%; + position: absolute; + top: 0; + left: 0; + border-radius: inherit; + transform: scale(0.5); + transform-origin: 0 0; + pointer-events: none; + box-sizing: border-box; +} + +.solid::after { + border: 1upx solid rgba(0, 0, 0, 0.1); +} + +.solid-top::after { + border-top: 1upx solid rgba(0, 0, 0, 0.1); +} + +.solid-right::after { + border-right: 1upx solid rgba(0, 0, 0, 0.1); +} + +.solid-bottom::after { + border-bottom: 1upx solid rgba(0, 0, 0, 0.1); +} + +.solid-left::after { + border-left: 1upx solid rgba(0, 0, 0, 0.1); +} + +.solids::after { + border: 8upx solid #eee; +} + +.solids-top::after { + border-top: 8upx solid #eee; +} + +.solids-right::after { + border-right: 8upx solid #eee; +} + +.solids-bottom::after { + border-bottom: 8upx solid #eee; +} + +.solids-left::after { + border-left: 8upx solid #eee; +} + +/* -- 虚线 -- */ + +.dashed::after { + border: 1upx dashed #ddd; +} + +.dashed-top::after { + border-top: 1upx dashed #ddd; +} + +.dashed-right::after { + border-right: 1upx dashed #ddd; +} + +.dashed-bottom::after { + border-bottom: 1upx dashed #ddd; +} + +.dashed-left::after { + border-left: 1upx dashed #ddd; +} + +/* -- 阴影 -- */ + +.shadow[class*='white'] { + --ShadowSize: 0 1upx 6upx; +} + +.shadow-lg { + --ShadowSize: 0upx 40upx 100upx 0upx; +} + +.shadow-warp { + position: relative; + box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1); +} + +.shadow-warp:before, +.shadow-warp:after { + position: absolute; + content: ""; + top: 20upx; + bottom: 30upx; + left: 20upx; + width: 50%; + box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2); + transform: rotate(-3deg); + z-index: -1; +} + +.shadow-warp:after { + right: 20upx; + left: auto; + transform: rotate(3deg); +} + +.shadow-blur { + position: relative; +} + +.shadow-blur::before { + content: ""; + display: block; + background: inherit; + filter: blur(10upx); + position: absolute; + width: 100%; + height: 100%; + top: 10upx; + left: 10upx; + z-index: -1; + opacity: 0.4; + transform-origin: 0 0; + border-radius: inherit; + transform: scale(1, 1); +} + +/* ================== + 按钮 + ==================== */ + +.cu-btn { + position: relative; + border: 0upx; + display: inline-flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + padding: 0 30upx; + font-size: 28upx; + height: 64upx; + line-height: 1; + text-align: center; + text-decoration: none; + overflow: visible; + margin-left: initial; + transform: translate(0upx, 0upx); + margin-right: initial; +} + +.cu-btn::after { + display: none; +} + +.cu-btn:not([class*="bg-"]) { + background-color: #f0f0f0; +} + +.cu-btn[class*="line"] { + background-color: transparent; +} + +.cu-btn[class*="line"]::after { + content: " "; + display: block; + width: 200%; + height: 200%; + position: absolute; + top: 0; + left: 0; + border: 1upx solid currentColor; + transform: scale(0.5); + transform-origin: 0 0; + box-sizing: border-box; + border-radius: 12upx; + z-index: 1; + pointer-events: none; +} + +.cu-btn.round[class*="line"]::after { + border-radius: 1000upx; +} + +.cu-btn[class*="lines"]::after { + border: 6upx solid currentColor; +} + +.cu-btn[class*="bg-"]::after { + display: none; +} + +.cu-btn.sm { + padding: 0 20upx; + font-size: 20upx; + height: 48upx; +} + +.cu-btn.lg { + padding: 0 40upx; + font-size: 32upx; + height: 80upx; +} + +.cu-btn.cuIcon.sm { + width: 48upx; + height: 48upx; +} + +.cu-btn.cuIcon { + width: 64upx; + height: 64upx; + border-radius: 500upx; + padding: 0; +} + +button.cuIcon.lg { + width: 80upx; + height: 80upx; +} + +.cu-btn.shadow-blur::before { + top: 4upx; + left: 4upx; + filter: blur(6upx); + opacity: 0.6; +} + +.cu-btn.button-hover { + transform: translate(1upx, 1upx); +} + +.block { + display: block; +} + +.cu-btn.block { + display: flex; +} + +.cu-btn[disabled] { + opacity: 0.6; + color: #ffffff; +} + +/* ================== + 徽章 + ==================== */ + +.cu-tag { + font-size: 24upx; + vertical-align: middle; + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + padding: 0upx 16upx; + height: 48upx; + font-family: Helvetica Neue, Helvetica, sans-serif; + white-space: nowrap; +} + +.cu-tag:not([class*="bg"]):not([class*="line"]) { + background-color: #f1f1f1; +} + +.cu-tag[class*="line-"]::after { + content: " "; + width: 200%; + height: 200%; + position: absolute; + top: 0; + left: 0; + border: 1upx solid currentColor; + transform: scale(0.5); + transform-origin: 0 0; + box-sizing: border-box; + border-radius: inherit; + z-index: 1; + pointer-events: none; +} + +.cu-tag.radius[class*="line"]::after { + border-radius: 12upx; +} + +.cu-tag.round[class*="line"]::after { + border-radius: 1000upx; +} + +.cu-tag[class*="line-"]::after { + border-radius: 0; +} + +.cu-tag+.cu-tag { + margin-left: 10upx; +} + +.cu-tag.sm { + font-size: 20upx; + padding: 0upx 12upx; + height: 32upx; +} + +.cu-capsule { + display: inline-flex; + vertical-align: middle; +} + +.cu-capsule+.cu-capsule { + margin-left: 10upx; +} + +.cu-capsule .cu-tag { + margin: 0; +} + +.cu-capsule .cu-tag[class*="line-"]:last-child::after { + border-left: 0upx solid transparent; +} + +.cu-capsule .cu-tag[class*="line-"]:first-child::after { + border-right: 0upx solid transparent; +} + +.cu-capsule.radius .cu-tag:first-child { + border-top-left-radius: 6upx; + border-bottom-left-radius: 6upx; +} + +.cu-capsule.radius .cu-tag:last-child::after, +.cu-capsule.radius .cu-tag[class*="line-"] { + border-top-right-radius: 12upx; + border-bottom-right-radius: 12upx; +} + +.cu-capsule.round .cu-tag:first-child { + border-top-left-radius: 200upx; + border-bottom-left-radius: 200upx; + text-indent: 4upx; +} + +.cu-capsule.round .cu-tag:last-child::after, +.cu-capsule.round .cu-tag:last-child { + border-top-right-radius: 200upx; + border-bottom-right-radius: 200upx; + text-indent: -4upx; +} + +.cu-tag.badge { + border-radius: 200upx; + position: absolute; + top: -10upx; + right: -10upx; + font-size: 20upx; + padding: 0upx 10upx; + height: 28upx; + color: #ffffff; +} + +.cu-tag.badge:not([class*="bg-"]) { + background-color: #dd514c; +} + +.cu-tag:empty:not([class*="cuIcon-"]) { + padding: 0upx; + width: 16upx; + height: 16upx; + top: -4upx; + right: -4upx; +} + +.cu-tag[class*="cuIcon-"] { + width: 32upx; + height: 32upx; + top: -4upx; + right: -4upx; +} + +/* ================== + 头像 + ==================== */ + +.cu-avatar { + font-variant: small-caps; + margin: 0; + padding: 0; + display: inline-flex; + text-align: center; + justify-content: center; + align-items: center; + background-color: #ccc; + color: #ffffff; + white-space: nowrap; + position: relative; + width: 64upx; + height: 64upx; + background-size: cover; + background-position: center; + vertical-align: middle; + font-size: 1.5em; +} + +.cu-avatar.sm { + width: 48upx; + height: 48upx; + font-size: 1em; +} + +.cu-avatar.lg { + width: 96upx; + height: 96upx; + font-size: 2em; +} + +.cu-avatar.xl { + width: 128upx; + height: 128upx; + font-size: 2.5em; +} + +.cu-avatar .avatar-text { + font-size: 0.4em; +} + +.cu-avatar-group { + direction: rtl; + unicode-bidi: bidi-override; + padding: 0 10upx 0 40upx; + display: inline-block; +} + +.cu-avatar-group .cu-avatar { + margin-left: -30upx; + border: 4upx solid #f1f1f1; + vertical-align: middle; +} + +.cu-avatar-group .cu-avatar.sm { + margin-left: -20upx; + border: 1upx solid #f1f1f1; +} + +/* ================== + 进度条 + ==================== */ + +.cu-progress { + overflow: hidden; + height: 28upx; + background-color: #ebeef5; + display: inline-flex; + align-items: center; + width: 100%; +} + +.cu-progress+view, +.cu-progress+text { + line-height: 1; +} + +.cu-progress.xs { + height: 10upx; +} + +.cu-progress.sm { + height: 20upx; +} + +.cu-progress view { + width: 0; + height: 100%; + align-items: center; + display: flex; + justify-items: flex-end; + justify-content: space-around; + font-size: 20upx; + color: #ffffff; + transition: width 0.6s ease; +} + +.cu-progress text { + align-items: center; + display: flex; + font-size: 20upx; + color: #333333; + text-indent: 10upx; +} + +.cu-progress.text-progress { + padding-right: 60upx; +} + +.cu-progress.striped view { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 72upx 72upx; +} + +.cu-progress.active view { + animation: progress-stripes 2s linear infinite; +} + +@keyframes progress-stripes { + from { + background-position: 72upx 0; + } + + to { + background-position: 0 0; + } +} + +/* ================== + 加载 + ==================== */ + +.cu-load { + display: block; + line-height: 3em; + text-align: center; +} + +.cu-load::before { + font-family: "cuIcon"; + display: inline-block; + margin-right: 6upx; +} + +.cu-load.loading::before { + content: "\e67a"; + animation: cuIcon-spin 2s infinite linear; +} + +.cu-load.loading::after { + content: "加载中..."; +} + +.cu-load.over::before { + content: "\e64a"; +} + +.cu-load.over::after { + content: "没有更多了"; +} + +.cu-load.erro::before { + content: "\e658"; +} + +.cu-load.erro::after { + content: "加载失败"; +} + +.cu-load.load-cuIcon::before { + font-size: 32upx; +} + +.cu-load.load-cuIcon::after { + display: none; +} + +.cu-load.load-cuIcon.over { + display: none; +} + +.cu-load.load-modal { + position: fixed; + top: 0; + right: 0; + bottom: 140upx; + left: 0; + margin: auto; + width: 260upx; + height: 260upx; + background-color: #ffffff; + border-radius: 10upx; + box-shadow: 0 0 0upx 2000upx rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + font-size: 28upx; + z-index: 9999; + line-height: 2.4em; +} + +.cu-load.load-modal [class*="cuIcon-"] { + font-size: 60upx; +} + +.cu-load.load-modal image { + width: 70upx; + height: 70upx; +} + +.cu-load.load-modal::after { + content: ""; + position: absolute; + background-color: #ffffff; + border-radius: 50%; + width: 200upx; + height: 200upx; + font-size: 10px; + border-top: 6upx solid rgba(0, 0, 0, 0.05); + border-right: 6upx solid rgba(0, 0, 0, 0.05); + border-bottom: 6upx solid rgba(0, 0, 0, 0.05); + border-left: 6upx solid #f37b1d; + animation: cuIcon-spin 1s infinite linear; + z-index: -1; +} + +.load-progress { + pointer-events: none; + top: 0; + position: fixed; + width: 100%; + left: 0; + z-index: 2000; +} + +.load-progress.hide { + display: none; +} + +.load-progress .load-progress-bar { + position: relative; + width: 100%; + height: 4upx; + overflow: hidden; + transition: all 200ms ease 0s; +} + +.load-progress .load-progress-spinner { + position: absolute; + top: 10upx; + right: 10upx; + z-index: 2000; + display: block; +} + +.load-progress .load-progress-spinner::after { + content: ""; + display: block; + width: 24upx; + height: 24upx; + -webkit-box-sizing: border-box; + box-sizing: border-box; + border: solid 4upx transparent; + border-top-color: inherit; + border-left-color: inherit; + border-radius: 50%; + -webkit-animation: load-progress-spinner 0.4s linear infinite; + animation: load-progress-spinner 0.4s linear infinite; +} + +@-webkit-keyframes load-progress-spinner { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes load-progress-spinner { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +/* ================== + 列表 + ==================== */ +.grayscale { + filter: grayscale(1); +} + +.cu-list+.cu-list { + margin-top: 30upx +} + +.cu-list>.cu-item { + transition: all .6s ease-in-out 0s; + transform: translateX(0upx) +} + +.cu-list>.cu-item.move-cur { + transform: translateX(-260upx) +} + +.cu-list>.cu-item .move { + position: absolute; + right: 0; + display: flex; + width: 260upx; + height: 100%; + transform: translateX(100%) +} + +.cu-list>.cu-item .move view { + display: flex; + flex: 1; + justify-content: center; + align-items: center +} + +.cu-list.menu-avatar { + overflow: hidden; +} + +.cu-list.menu-avatar>.cu-item { + position: relative; + display: flex; + padding-right: 10upx; + height: 140upx; + background-color: #ffffff; + justify-content: flex-end; + align-items: center +} + +.cu-list.menu-avatar>.cu-item>.cu-avatar { + position: absolute; + left: 30upx +} + +.cu-list.menu-avatar>.cu-item .flex .text-cut { + max-width: 510upx +} + +.cu-list.menu-avatar>.cu-item .content { + position: absolute; + left: 146upx; + width: calc(100% - 96upx - 60upx - 120upx - 20upx); + line-height: 1.6em; +} + +.cu-list.menu-avatar>.cu-item .content.flex-sub { + width: calc(100% - 96upx - 60upx - 20upx); +} + +.cu-list.menu-avatar>.cu-item .content>view:first-child { + font-size: 30upx; + display: flex; + align-items: center +} + +.cu-list.menu-avatar>.cu-item .content .cu-tag.sm { + display: inline-block; + margin-left: 10upx; + height: 28upx; + font-size: 16upx; + line-height: 32upx +} + +.cu-list.menu-avatar>.cu-item .action { + width: 100upx; + text-align: center +} + +.cu-list.menu-avatar>.cu-item .action view+view { + margin-top: 10upx +} + +.cu-list.menu-avatar.comment>.cu-item .content { + position: relative; + left: 0; + width: auto; + flex: 1; +} + +.cu-list.menu-avatar.comment>.cu-item { + padding: 30upx 30upx 30upx 120upx; + height: auto +} + +.cu-list.menu-avatar.comment .cu-avatar { + align-self: flex-start +} + +.cu-list.menu>.cu-item { + position: relative; + display: flex; + padding: 0 30upx; + min-height: 100upx; + background-color: #ffffff; + justify-content: space-between; + align-items: center +} + +.cu-list.menu>.cu-item:last-child:after { + border: none +} + +.cu-list.menu-avatar>.cu-item:after, +.cu-list.menu>.cu-item:after { + position: absolute; + top: 0; + left: 0; + box-sizing: border-box; + width: 200%; + height: 200%; + border-bottom: 1upx solid #ddd; + border-radius: inherit; + content: " "; + transform: scale(.5); + transform-origin: 0 0; + pointer-events: none +} + +.cu-list.menu>.cu-item.grayscale { + background-color: #f5f5f5 +} + +.cu-list.menu>.cu-item.cur { + background-color: #fcf7e9 +} + +.cu-list.menu>.cu-item.arrow { + padding-right: 90upx +} + +.cu-list.menu>.cu-item.arrow:before { + position: absolute; + top: 0; + right: 30upx; + bottom: 0; + display: block; + margin: auto; + width: 30upx; + height: 30upx; + color: #8799a3; + content: "\e6a3"; + text-align: center; + font-size: 34upx; + font-family: cuIcon; + line-height: 30upx +} + +.cu-list.menu>.cu-item button.content { + padding: 0; + background-color: transparent; + justify-content: flex-start +} + +.cu-list.menu>.cu-item button.content:after { + display: none +} + +.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar { + border-color: #ffffff +} + +.cu-list.menu>.cu-item .content>view:first-child { + display: flex; + align-items: center +} + +.cu-list.menu>.cu-item .content>text[class*=cuIcon] { + display: inline-block; + margin-right: 10upx; + width: 1.6em; + text-align: center +} + +.cu-list.menu>.cu-item .content>image { + display: inline-block; + margin-right: 10upx; + width: 1.6em; + height: 1.6em; + vertical-align: middle +} + +.cu-list.menu>.cu-item .content { + font-size: 30upx; + line-height: 1.6em; + flex: 1 +} + +.cu-list.menu>.cu-item .content .cu-tag.sm { + display: inline-block; + margin-left: 10upx; + height: 28upx; + font-size: 16upx; + line-height: 32upx +} + +.cu-list.menu>.cu-item .action .cu-tag:empty { + right: 10upx +} + +.cu-list.menu { + display: block; + overflow: hidden +} + +.cu-list.menu.sm-border>.cu-item:after { + left: 30upx; + width: calc(200% - 120upx) +} + +.cu-list.grid>.cu-item { + position: relative; + display: flex; + padding: 20upx 0 30upx; + transition-duration: 0s; + flex-direction: column +} + +.cu-list.grid>.cu-item:after { + position: absolute; + top: 0; + left: 0; + box-sizing: border-box; + width: 200%; + height: 200%; + border-right: 1px solid rgba(0, 0, 0, .1); + border-bottom: 1px solid rgba(0, 0, 0, .1); + border-radius: inherit; + content: " "; + transform: scale(.5); + transform-origin: 0 0; + pointer-events: none +} + +.cu-list.grid>.cu-item text { + display: block; + margin-top: 10upx; + color: #888; + font-size: 26upx; + line-height: 40upx +} + +.cu-list.grid>.cu-item [class*=cuIcon] { + position: relative; + display: block; + margin-top: 20upx; + width: 100%; + font-size: 48upx +} + +.cu-list.grid>.cu-item .cu-tag { + right: auto; + left: 50%; + margin-left: 20upx +} + +.cu-list.grid { + background-color: #ffffff; + text-align: center +} + +.cu-list.grid.no-border>.cu-item { + padding-top: 10upx; + padding-bottom: 20upx +} + +.cu-list.grid.no-border>.cu-item:after { + border: none +} + +.cu-list.grid.no-border { + padding: 20upx 10upx +} + +.cu-list.grid.col-3>.cu-item:nth-child(3n):after, +.cu-list.grid.col-4>.cu-item:nth-child(4n):after, +.cu-list.grid.col-5>.cu-item:nth-child(5n):after { + border-right-width: 0 +} + +.cu-list.card-menu { + overflow: hidden; + margin-right: 30upx; + margin-left: 30upx; + border-radius: 20upx +} + + +/* ================== + 操作条 + ==================== */ + +.cu-bar { + display: flex; + position: relative; + align-items: center; + min-height: 100upx; + justify-content: space-between; +} + +.cu-bar .action { + display: flex; + align-items: center; + height: 100%; + justify-content: center; + max-width: 100%; +} + +.cu-bar .action.border-title { + position: relative; + top: -10upx; +} + +.cu-bar .action.border-title text[class*="bg-"]:last-child { + position: absolute; + bottom: -0.5rem; + min-width: 2rem; + height: 6upx; + left: 0; +} + +.cu-bar .action.sub-title { + position: relative; + top: -0.2rem; +} + +.cu-bar .action.sub-title text { + position: relative; + z-index: 1; +} + +.cu-bar .action.sub-title text[class*="bg-"]:last-child { + position: absolute; + display: inline-block; + bottom: -0.2rem; + border-radius: 6upx; + width: 100%; + height: 0.6rem; + left: 0.6rem; + opacity: 0.3; + z-index: 0; +} + +.cu-bar .action.sub-title text[class*="text-"]:last-child { + position: absolute; + display: inline-block; + bottom: -0.7rem; + left: 0.5rem; + opacity: 0.2; + z-index: 0; + text-align: right; + font-weight: 900; + font-size: 36upx; +} + +.cu-bar.justify-center .action.border-title text:last-child, +.cu-bar.justify-center .action.sub-title text:last-child { + left: 0; + right: 0; + margin: auto; + text-align: center; +} + +.cu-bar .action:first-child { + margin-left: 30upx; + font-size: 30upx; +} + +.cu-bar .action text.text-cut { + text-align: left; + width: 100%; +} + +.cu-bar .cu-avatar:first-child { + margin-left: 20upx; +} + +.cu-bar .action:first-child>text[class*="cuIcon-"] { + margin-left: -0.3em; + margin-right: 0.3em; +} + +.cu-bar .action:last-child { + margin-right: 30upx; +} + +.cu-bar .action>text[class*="cuIcon-"], +.cu-bar .action>view[class*="cuIcon-"] { + font-size: 36upx; +} + +.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] { + margin-left: 0.5em; +} + +.cu-bar .content { + position: absolute; + text-align: center; + width: calc(100% - 340upx); + left: 0; + right: 0; + bottom: 0; + top: 0; + margin: auto; + height: 60upx; + font-size: 32upx; + line-height: 60upx; + cursor: none; + pointer-events: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.cu-bar.ios .content { + bottom: 7px; + height: 30px; + font-size: 32upx; + line-height: 30px; +} + +.cu-bar.btn-group { + justify-content: space-around; +} + +.cu-bar.btn-group button { + padding: 20upx 32upx; +} + +.cu-bar.btn-group button { + flex: 1; + margin: 0 20upx; + max-width: 50%; +} + +.cu-bar .search-form { + background-color: #f5f5f5; + line-height: 64upx; + height: 64upx; + font-size: 24upx; + color: #333333; + flex: 1; + display: flex; + align-items: center; + margin: 0 30upx; +} + +.cu-bar .search-form+.action { + margin-right: 30upx; +} + +.cu-bar .search-form input { + flex: 1; + padding-right: 30upx; + height: 64upx; + line-height: 64upx; + font-size: 26upx; + background-color: transparent; +} + +.cu-bar .search-form [class*="cuIcon-"] { + margin: 0 0.5em 0 0.8em; +} + +.cu-bar .search-form [class*="cuIcon-"]::before { + top: 0upx; +} + +.cu-bar.fixed, +.nav.fixed { + position: fixed; + width: 100%; + top: 0; + z-index: 1024; + box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1); +} + +.cu-bar.foot { + position: fixed; + width: 100%; + bottom: 0; + z-index: 1024; + box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1); +} + +.cu-bar.tabbar { + padding: 0; + height: calc(100upx + env(safe-area-inset-bottom) / 2); + padding-bottom: calc(env(safe-area-inset-bottom) / 2); +} + +.cu-tabbar-height { + min-height: 100upx; + height: calc(100upx + env(safe-area-inset-bottom) / 2); +} + +.cu-bar.tabbar.shadow { + box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1); +} + +.cu-bar.tabbar .action { + font-size: 22upx; + position: relative; + flex: 1; + text-align: center; + padding: 0; + display: block; + height: auto; + line-height: 1; + margin: 0; + background-color: inherit; + overflow: initial; +} + +.cu-bar.tabbar.shop .action { + width: 140upx; + flex: initial; +} + +.cu-bar.tabbar .action.add-action { + position: relative; + z-index: 2; + padding-top: 50upx; +} + +.cu-bar.tabbar .action.add-action [class*="cuIcon-"] { + position: absolute; + width: 70upx; + z-index: 2; + height: 70upx; + border-radius: 50%; + line-height: 70upx; + font-size: 50upx; + top: -35upx; + left: 0; + right: 0; + margin: auto; + padding: 0; +} + +.cu-bar.tabbar .action.add-action::after { + content: ""; + position: absolute; + width: 100upx; + height: 100upx; + top: -50upx; + left: 0; + right: 0; + margin: auto; + box-shadow: 0 -3upx 8upx rgba(0, 0, 0, 0.08); + border-radius: 50upx; + background-color: inherit; + z-index: 0; +} + +.cu-bar.tabbar .action.add-action::before { + content: ""; + position: absolute; + width: 100upx; + height: 30upx; + bottom: 30upx; + left: 0; + right: 0; + margin: auto; + background-color: inherit; + z-index: 1; +} + +.cu-bar.tabbar .btn-group { + flex: 1; + display: flex; + justify-content: space-around; + align-items: center; + padding: 0 10upx; +} + +.cu-bar.tabbar button.action::after { + border: 0; +} + +.cu-bar.tabbar .action [class*="cuIcon-"] { + width: 100upx; + position: relative; + display: block; + height: auto; + margin: 0 auto 10upx; + text-align: center; + font-size: 40upx; +} + +.cu-bar.tabbar .action .cuIcon-cu-image { + margin: 0 auto; +} + +.cu-bar.tabbar .action .cuIcon-cu-image image { + width: 50upx; + height: 50upx; + display: inline-block; +} + +.cu-bar.tabbar .submit { + align-items: center; + display: flex; + justify-content: center; + text-align: center; + position: relative; + flex: 2; + align-self: stretch; +} + +.cu-bar.tabbar .submit:last-child { + flex: 2.6; +} + +.cu-bar.tabbar .submit+.submit { + flex: 2; +} + +.cu-bar.tabbar.border .action::before { + content: " "; + width: 200%; + height: 200%; + position: absolute; + top: 0; + left: 0; + transform: scale(0.5); + transform-origin: 0 0; + border-right: 1upx solid rgba(0, 0, 0, 0.1); + z-index: 3; +} + +.cu-bar.tabbar.border .action:last-child:before { + display: none; +} + +.cu-bar.input { + padding-right: 20upx; + background-color: #ffffff; +} + +.cu-bar.input input { + overflow: initial; + line-height: 64upx; + height: 64upx; + min-height: 64upx; + flex: 1; + font-size: 30upx; + margin: 0 20upx; +} + +.cu-bar.input .action { + margin-left: 20upx; +} + +.cu-bar.input .action [class*="cuIcon-"] { + font-size: 48upx; +} + +.cu-bar.input input+.action { + margin-right: 20upx; + margin-left: 0upx; +} + +.cu-bar.input .action:first-child [class*="cuIcon-"] { + margin-left: 0upx; +} + +.cu-custom { + display: block; + position: relative; +} + +.cu-custom .cu-bar .content { + width: calc(100% - 440upx); +} + +/* #ifdef MP-ALIPAY */ +.cu-custom .cu-bar .action .cuIcon-back { + opacity: 0; +} + +/* #endif */ + +.cu-custom .cu-bar .content image { + height: 60upx; + width: 240upx; +} + +.cu-custom .cu-bar { + min-height: 0px; + /* #ifdef MP-WEIXIN */ + padding-right: 220upx; + /* #endif */ + /* #ifdef MP-ALIPAY */ + padding-right: 150upx; + /* #endif */ + box-shadow: 0upx 0upx 0upx; + z-index: 9999; +} + +.cu-custom .cu-bar .border-custom { + position: relative; + background: rgba(0, 0, 0, 0.15); + border-radius: 1000upx; + height: 30px; +} + +.cu-custom .cu-bar .border-custom::after { + content: " "; + width: 200%; + height: 200%; + position: absolute; + top: 0; + left: 0; + border-radius: inherit; + transform: scale(0.5); + transform-origin: 0 0; + pointer-events: none; + box-sizing: border-box; + border: 1upx solid #ffffff; + opacity: 0.5; +} + +.cu-custom .cu-bar .border-custom::before { + content: " "; + width: 1upx; + height: 110%; + position: absolute; + top: 22.5%; + left: 0; + right: 0; + margin: auto; + transform: scale(0.5); + transform-origin: 0 0; + pointer-events: none; + box-sizing: border-box; + opacity: 0.6; + background-color: #ffffff; +} + +.cu-custom .cu-bar .border-custom text { + display: block; + flex: 1; + margin: auto !important; + text-align: center; + font-size: 34upx; +} + +/* ================== + 导航栏 + ==================== */ + +.nav { + white-space: nowrap; +} + +::-webkit-scrollbar { + display: none; +} + +.nav .cu-item { + height: 90upx; + display: inline-block; + line-height: 90upx; + margin: 0 10upx; + padding: 0 20upx; +} + +.nav .cu-item.cur { + border-bottom: 4upx solid; +} + +/* ================== + 时间轴 + ==================== */ + +.cu-timeline { + display: block; + background-color: #ffffff; +} + +.cu-timeline .cu-time { + width: 120upx; + text-align: center; + padding: 20upx 0; + font-size: 26upx; + color: #888; + display: block; +} + +.cu-timeline>.cu-item { + padding: 30upx 30upx 30upx 120upx; + position: relative; + display: block; + z-index: 0; +} + +.cu-timeline>.cu-item:not([class*="text-"]) { + color: #ccc; +} + +.cu-timeline>.cu-item::after { + content: ""; + display: block; + position: absolute; + width: 1upx; + background-color: #ddd; + left: 60upx; + height: 100%; + top: 0; + z-index: 8; +} + +.cu-timeline>.cu-item::before { + font-family: "cuIcon"; + display: block; + position: absolute; + top: 36upx; + z-index: 9; + background-color: #ffffff; + width: 50upx; + height: 50upx; + text-align: center; + border: none; + line-height: 50upx; + left: 36upx; +} + +.cu-timeline>.cu-item:not([class*="cuIcon-"])::before { + content: "\e763"; +} + +.cu-timeline>.cu-item[class*="cuIcon-"]::before { + background-color: #ffffff; + width: 50upx; + height: 50upx; + text-align: center; + border: none; + line-height: 50upx; + left: 36upx; +} + +.cu-timeline>.cu-item>.content { + padding: 30upx; + border-radius: 6upx; + display: block; + line-height: 1.6; +} + +.cu-timeline>.cu-item>.content:not([class*="bg-"]) { + background-color: #f1f1f1; + color: #333333; +} + +.cu-timeline>.cu-item>.content+.content { + margin-top: 20upx; +} + +/* ================== + 聊天 + ==================== */ + +.cu-chat { + display: flex; + flex-direction: column; +} + +.cu-chat .cu-item { + display: flex; + padding: 30upx 30upx 70upx; + position: relative; +} + +.cu-chat .cu-item>.cu-avatar { + width: 80upx; + height: 80upx; +} + +.cu-chat .cu-item>.main { + max-width: calc(100% - 260upx); + margin: 0 40upx; + display: flex; + align-items: center; +} + +.cu-chat .cu-item>image { + height: 320upx; +} + +.cu-chat .cu-item>.main .content { + padding: 20upx; + border-radius: 6upx; + display: inline-flex; + max-width: 100%; + align-items: center; + font-size: 30upx; + position: relative; + min-height: 80upx; + line-height: 40upx; + text-align: left; +} + +.cu-chat .cu-item>.main .content:not([class*="bg-"]) { + background-color: #ffffff; + color: #333333; +} + +.cu-chat .cu-item .date { + position: absolute; + font-size: 24upx; + color: #8799a3; + width: calc(100% - 320upx); + bottom: 20upx; + left: 160upx; +} + +.cu-chat .cu-item .action { + padding: 0 30upx; + display: flex; + align-items: center; +} + +.cu-chat .cu-item>.main .content::after { + content: ""; + top: 27upx; + transform: rotate(45deg); + position: absolute; + z-index: 100; + display: inline-block; + overflow: hidden; + width: 24upx; + height: 24upx; + left: -12upx; + right: initial; + background-color: inherit; +} + +.cu-chat .cu-item.self>.main .content::after { + left: auto; + right: -12upx; +} + +.cu-chat .cu-item>.main .content::before { + content: ""; + top: 30upx; + transform: rotate(45deg); + position: absolute; + z-index: -1; + display: inline-block; + overflow: hidden; + width: 24upx; + height: 24upx; + left: -12upx; + right: initial; + background-color: inherit; + filter: blur(5upx); + opacity: 0.3; +} + +.cu-chat .cu-item>.main .content:not([class*="bg-"])::before { + background-color: #333333; + opacity: 0.1; +} + +.cu-chat .cu-item.self>.main .content::before { + left: auto; + right: -12upx; +} + +.cu-chat .cu-item.self { + justify-content: flex-end; + text-align: right; +} + +.cu-chat .cu-info { + display: inline-block; + margin: 20upx auto; + font-size: 24upx; + padding: 8upx 12upx; + background-color: rgba(0, 0, 0, 0.2); + border-radius: 6upx; + color: #ffffff; + max-width: 400upx; + line-height: 1.4; +} + +/* ================== + 卡片 + ==================== */ + +.cu-card { + display: block; + overflow: hidden; +} + +.cu-card>.cu-item { + display: block; + background-color: #ffffff; + overflow: hidden; + border-radius: 10upx; + margin: 30upx; +} + +.cu-card>.cu-item.shadow-blur { + overflow: initial; +} + +.cu-card.no-card>.cu-item { + margin: 0upx; + border-radius: 0upx; +} + +.cu-card .grid.grid-square { + margin-bottom: -20upx; +} + +.cu-card.case .image { + position: relative; +} + +.cu-card.case .image image { + width: 100%; +} + +.cu-card.case .image .cu-tag { + position: absolute; + right: 0; + top: 0; +} + +.cu-card.case .image .cu-bar { + position: absolute; + bottom: 0; + width: 100%; + background-color: transparent; + padding: 0upx 30upx; +} + +.cu-card.case.no-card .image { + margin: 30upx 30upx 0; + overflow: hidden; + border-radius: 10upx; +} + +.cu-card.dynamic { + display: block; +} + +.cu-card.dynamic>.cu-item { + display: block; + background-color: #ffffff; + overflow: hidden; +} + +.cu-card.dynamic>.cu-item>.text-content { + padding: 0 30upx 0; + max-height: 6.4em; + overflow: hidden; + font-size: 30upx; + margin-bottom: 20upx; +} + +.cu-card.dynamic>.cu-item .square-img { + width: 100%; + height: 200upx; + border-radius: 6upx; +} + +.cu-card.dynamic>.cu-item .only-img { + width: 100%; + height: 320upx; + border-radius: 6upx; +} + +/* card.dynamic>.cu-item .comment { + padding: 20upx; + background-color: #f1f1f1; + margin: 0 30upx 30upx; + border-radius: 6upx; +} */ + +.cu-card.article { + display: block; +} + +.cu-card.article>.cu-item { + padding-bottom: 30upx; +} + +.cu-card.article>.cu-item .title { + font-size: 30upx; + font-weight: 900; + color: #333333; + line-height: 100upx; + padding: 0 30upx; +} + +.cu-card.article>.cu-item .content { + display: flex; + padding: 0 30upx; +} + +.cu-card.article>.cu-item .content>image { + width: 240upx; + height: 6.4em; + margin-right: 20upx; + border-radius: 6upx; +} + +.cu-card.article>.cu-item .content .desc { + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.cu-card.article>.cu-item .content .text-content { + font-size: 28upx; + color: #888; + height: 4.8em; + overflow: hidden; +} + +/* ================== + 表单 + ==================== */ + +.cu-form-group { + background-color: #ffffff; + padding: 1upx 30upx; + display: flex; + align-items: center; + min-height: 100upx; + justify-content: space-between; +} + +.cu-form-group+.cu-form-group { + border-top: 1upx solid #eee; +} + +.cu-form-group .title { + text-align: justify; + padding-right: 30upx; + font-size: 30upx; + position: relative; + height: 60upx; + line-height: 60upx; +} + +.cu-form-group input { + flex: 1; + font-size: 30upx; + color: #555; + padding-right: 20upx; +} + +.cu-form-group>text[class*="cuIcon-"] { + font-size: 36upx; + padding: 0; + box-sizing: border-box; +} + +.cu-form-group textarea { + margin: 32upx 0 30upx; + height: 4.6em; + width: 100%; + line-height: 1.2em; + flex: 1; + font-size: 28upx; + padding: 0; +} + +.cu-form-group.align-start .title { + height: 1em; + margin-top: 32upx; + line-height: 1em; +} + +.cu-form-group picker { + flex: 1; + padding-right: 40upx; + overflow: hidden; + position: relative; +} + +.cu-form-group picker .picker { + line-height: 100upx; + font-size: 28upx; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + text-align: right; +} + +.cu-form-group picker::after { + font-family: cuIcon; + display: block; + content: "\e6a3"; + position: absolute; + font-size: 34upx; + color: #8799a3; + line-height: 100upx; + width: 60upx; + text-align: center; + top: 0; + bottom: 0; + right: -20upx; + margin: auto; +} + +.cu-form-group textarea[disabled], +.cu-form-group textarea[disabled] .placeholder { + color: transparent; +} + +/* ================== + 模态窗口 + ==================== */ + +.cu-modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1110; + opacity: 0; + outline: 0; + text-align: center; + -ms-transform: scale(1.185); + transform: scale(1.185); + backface-visibility: hidden; + perspective: 2000upx; + background: rgba(0, 0, 0, 0.6); + transition: all 0.3s ease-in-out 0s; + pointer-events: none; +} + +.cu-modal::before { + content: "\200B"; + display: inline-block; + height: 100%; + vertical-align: middle; +} + +.cu-modal.show { + opacity: 1; + transition-duration: 0.3s; + -ms-transform: scale(1); + transform: scale(1); + overflow-x: hidden; + overflow-y: auto; + pointer-events: auto; +} + +.cu-dialog { + position: relative; + display: inline-block; + vertical-align: middle; + margin-left: auto; + margin-right: auto; + width: 680upx; + max-width: 100%; + background-color: #f8f8f8; + border-radius: 10upx; + overflow: hidden; +} + +.cu-modal.bottom-modal::before { + vertical-align: bottom; +} + +.cu-modal.bottom-modal .cu-dialog { + width: 100%; + border-radius: 0; +} + +.cu-modal.bottom-modal { + margin-bottom: -1000upx; +} + +.cu-modal.bottom-modal.show { + margin-bottom: 0; +} + +.cu-modal.drawer-modal { + transform: scale(1); + display: flex; +} + +.cu-modal.drawer-modal .cu-dialog { + height: 100%; + min-width: 200upx; + border-radius: 0; + margin: initial; + transition-duration: 0.3s; +} + +.cu-modal.drawer-modal.justify-start .cu-dialog { + transform: translateX(-100%); +} + +.cu-modal.drawer-modal.justify-end .cu-dialog { + transform: translateX(100%); +} + +.cu-modal.drawer-modal.show .cu-dialog { + transform: translateX(0%); +} +.cu-modal .cu-dialog>.cu-bar:first-child .action{ + min-width: 100rpx; + margin-right: 0; + min-height: 100rpx; +} +/* ================== + 轮播 + ==================== */ +swiper .a-swiper-dot { + display: inline-block; + width: 16upx; + height: 16upx; + background: rgba(0, 0, 0, .3); + border-radius: 50%; + vertical-align: middle; +} + +swiper[class*="-dot"] .wx-swiper-dots, +swiper[class*="-dot"] .a-swiper-dots, +swiper[class*="-dot"] .uni-swiper-dots { + display: flex; + align-items: center; + width: 100%; + justify-content: center; +} + +swiper.square-dot .wx-swiper-dot, +swiper.square-dot .a-swiper-dot, +swiper.square-dot .uni-swiper-dot { + background-color: #ffffff; + opacity: 0.4; + width: 10upx; + height: 10upx; + border-radius: 20upx; + margin: 0 8upx !important; +} + +swiper.square-dot .wx-swiper-dot.wx-swiper-dot-active, +swiper.square-dot .a-swiper-dot.a-swiper-dot-active, +swiper.square-dot .uni-swiper-dot.uni-swiper-dot-active { + opacity: 1; + width: 30upx; +} + +swiper.round-dot .wx-swiper-dot, +swiper.round-dot .a-swiper-dot, +swiper.round-dot .uni-swiper-dot { + width: 10upx; + height: 10upx; + position: relative; + margin: 4upx 8upx !important; +} + +swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active::after, +swiper.round-dot .a-swiper-dot.a-swiper-dot-active::after, +swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active::after { + content: ""; + position: absolute; + width: 10upx; + height: 10upx; + top: 0upx; + left: 0upx; + right: 0; + bottom: 0; + margin: auto; + background-color: #ffffff; + border-radius: 20upx; +} + +swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active, +swiper.round-dot .a-swiper-dot.a-swiper-dot-active, +swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active { + width: 18upx; + height: 18upx; +} + +.screen-swiper { + min-height: 375upx; +} + +.screen-swiper image, +.screen-swiper video, +.swiper-item image, +.swiper-item video { + width: 100%; + display: block; + height: 100%; + margin: 0; + pointer-events: none; +} + +.card-swiper { + height: 420upx !important; +} + +.card-swiper swiper-item { + width: 610upx !important; + left: 70upx; + box-sizing: border-box; + padding: 40upx 0upx 70upx; + overflow: initial; +} + +.card-swiper swiper-item .swiper-item { + width: 100%; + display: block; + height: 100%; + border-radius: 10upx; + transform: scale(0.9); + transition: all 0.2s ease-in 0s; + overflow: hidden; +} + +.card-swiper swiper-item.cur .swiper-item { + transform: none; + transition: all 0.2s ease-in 0s; +} + + +.tower-swiper { + height: 420upx; + position: relative; + max-width: 750upx; + overflow: hidden; +} + +.tower-swiper .tower-item { + position: absolute; + width: 300upx; + height: 380upx; + top: 0; + bottom: 0; + left: 50%; + margin: auto; + transition: all 0.2s ease-in 0s; + opacity: 1; +} + +.tower-swiper .tower-item.none { + opacity: 0; +} + +.tower-swiper .tower-item .swiper-item { + width: 100%; + height: 100%; + border-radius: 6upx; + overflow: hidden; +} + +/* ================== + 步骤条 + ==================== */ + +.cu-steps { + display: flex; +} + +scroll-view.cu-steps { + display: block; + white-space: nowrap; +} + +scroll-view.cu-steps .cu-item { + display: inline-block; +} + +.cu-steps .cu-item { + flex: 1; + text-align: center; + position: relative; + min-width: 100upx; +} + +.cu-steps .cu-item:not([class*="text-"]) { + color: #8799a3; +} + +.cu-steps .cu-item [class*="cuIcon-"], +.cu-steps .cu-item .num { + display: block; + font-size: 40upx; + line-height: 80upx; +} + +.cu-steps .cu-item::before, +.cu-steps .cu-item::after, +.cu-steps.steps-arrow .cu-item::before, +.cu-steps.steps-arrow .cu-item::after { + content: ""; + display: block; + position: absolute; + height: 0px; + width: calc(100% - 80upx); + border-bottom: 1px solid #ccc; + left: calc(0px - (100% - 80upx) / 2); + top: 40upx; + z-index: 0; +} + +.cu-steps.steps-arrow .cu-item::before, +.cu-steps.steps-arrow .cu-item::after { + content: "\e6a3"; + font-family: 'cuIcon'; + height: 30upx; + border-bottom-width: 0px; + line-height: 30upx; + top: 0; + bottom: 0; + margin: auto; + color: #ccc; +} + +.cu-steps.steps-bottom .cu-item::before, +.cu-steps.steps-bottom .cu-item::after { + bottom: 40upx; + top: initial; +} + +.cu-steps .cu-item::after { + border-bottom: 1px solid currentColor; + width: 0px; + transition: all 0.3s ease-in-out 0s; +} + +.cu-steps .cu-item[class*="text-"]::after { + width: calc(100% - 80upx); + color: currentColor; +} + +.cu-steps .cu-item:first-child::before, +.cu-steps .cu-item:first-child::after { + display: none; +} + +.cu-steps .cu-item .num { + width: 40upx; + height: 40upx; + border-radius: 50%; + line-height: 40upx; + margin: 20upx auto; + font-size: 24upx; + border: 1px solid currentColor; + position: relative; + overflow: hidden; +} + +.cu-steps .cu-item[class*="text-"] .num { + background-color: currentColor; +} + +.cu-steps .cu-item .num::before, +.cu-steps .cu-item .num::after { + content: attr(data-index); + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; + transition: all 0.3s ease-in-out 0s; + transform: translateY(0upx); +} + +.cu-steps .cu-item[class*="text-"] .num::before { + transform: translateY(-40upx); + color: #ffffff; +} + +.cu-steps .cu-item .num::after { + transform: translateY(40upx); + color: #ffffff; + transition: all 0.3s ease-in-out 0s; +} + +.cu-steps .cu-item[class*="text-"] .num::after { + content: "\e645"; + font-family: 'cuIcon'; + color: #ffffff; + transform: translateY(0upx); +} + +.cu-steps .cu-item[class*="text-"] .num.err::after { + content: "\e646"; +} + +/* ================== + 布局 + ==================== */ + +/* -- flex弹性布局 -- */ + +.flex { + display: flex; +} + +.basis-xs { + flex-basis: 20%; +} + +.basis-sm { + flex-basis: 40%; +} + +.basis-df { + flex-basis: 50%; +} + +.basis-lg { + flex-basis: 60%; +} + +.basis-xl { + flex-basis: 80%; +} + +.flex-sub { + flex: 1; +} + +.flex-twice { + flex: 2; +} + +.flex-treble { + flex: 3; +} + +.flex-direction { + flex-direction: column; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.align-start { + align-items: flex-start; +} + +.align-end { + align-items: flex-end; +} + +.align-center { + align-items: center; +} + +.align-stretch { + align-items: stretch; +} + +.self-start { + align-self: flex-start; +} + +.self-center { + align-self: flex-center; +} + +.self-end { + align-self: flex-end; +} + +.self-stretch { + align-self: stretch; +} + +.align-stretch { + align-items: stretch; +} + +.justify-start { + justify-content: flex-start; +} + +.justify-end { + justify-content: flex-end; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.justify-around { + justify-content: space-around; +} + +/* grid布局 */ + +.grid { + display: flex; + flex-wrap: wrap; +} + +.grid.grid-square { + overflow: hidden; +} + +.grid.grid-square .cu-tag { + position: absolute; + right: 0; + top: 0; + border-bottom-left-radius: 6upx; + padding: 6upx 12upx; + height: auto; + background-color: rgba(0, 0, 0, 0.5); +} + +.grid.grid-square>view>text[class*="cuIcon-"] { + font-size: 52upx; + position: absolute; + color: #8799a3; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.grid.grid-square>view { + margin-right: 20upx; + margin-bottom: 20upx; + border-radius: 6upx; + position: relative; + overflow: hidden; +} +.grid.grid-square>view.bg-img image { + width: 100%; + height: 100%; + position: absolute; +} +.grid.col-1.grid-square>view { + padding-bottom: 100%; + height: 0; + margin-right: 0; +} + +.grid.col-2.grid-square>view { + padding-bottom: calc((100% - 20upx)/2); + height: 0; + width: calc((100% - 20upx)/2); +} + +.grid.col-3.grid-square>view { + padding-bottom: calc((100% - 40upx)/3); + height: 0; + width: calc((100% - 40upx)/3); +} + +.grid.col-4.grid-square>view { + padding-bottom: calc((100% - 60upx)/4); + height: 0; + width: calc((100% - 60upx)/4); +} + +.grid.col-5.grid-square>view { + padding-bottom: calc((100% - 80upx)/5); + height: 0; + width: calc((100% - 80upx)/5); +} + +.grid.col-2.grid-square>view:nth-child(2n), +.grid.col-3.grid-square>view:nth-child(3n), +.grid.col-4.grid-square>view:nth-child(4n), +.grid.col-5.grid-square>view:nth-child(5n) { + margin-right: 0; +} + +.grid.col-1>view { + width: 100%; +} + +.grid.col-2>view { + width: 50%; +} + +.grid.col-3>view { + width: 33.33%; +} + +.grid.col-4>view { + width: 25%; +} + +.grid.col-5>view { + width: 20%; +} + +/* -- 内外边距 -- */ + +.margin-0 { + margin: 0; +} + +.margin-xs { + margin: 10upx; +} + +.margin-sm { + margin: 20upx; +} + +.margin { + margin: 30upx; +} + +.margin-lg { + margin: 40upx; +} + +.margin-xl { + margin: 50upx; +} + +.margin-top-xs { + margin-top: 10upx; +} + +.margin-top-sm { + margin-top: 20upx; +} + +.margin-top { + margin-top: 30upx; +} + +.margin-top-lg { + margin-top: 40upx; +} + +.margin-top-xl { + margin-top: 50upx; +} + +.margin-right-xs { + margin-right: 10upx; +} + +.margin-right-sm { + margin-right: 20upx; +} + +.margin-right { + margin-right: 30upx; +} + +.margin-right-lg { + margin-right: 40upx; +} + +.margin-right-xl { + margin-right: 50upx; +} + +.margin-bottom-xs { + margin-bottom: 10upx; +} + +.margin-bottom-sm { + margin-bottom: 20upx; +} + +.margin-bottom { + margin-bottom: 30upx; +} + +.margin-bottom-lg { + margin-bottom: 40upx; +} + +.margin-bottom-xl { + margin-bottom: 50upx; +} + +.margin-left-xs { + margin-left: 10upx; +} + +.margin-left-sm { + margin-left: 20upx; +} + +.margin-left { + margin-left: 30upx; +} + +.margin-left-lg { + margin-left: 40upx; +} + +.margin-left-xl { + margin-left: 50upx; +} + +.margin-lr-xs { + margin-left: 10upx; + margin-right: 10upx; +} + +.margin-lr-sm { + margin-left: 20upx; + margin-right: 20upx; +} + +.margin-lr { + margin-left: 30upx; + margin-right: 30upx; +} + +.margin-lr-lg { + margin-left: 40upx; + margin-right: 40upx; +} + +.margin-lr-xl { + margin-left: 50upx; + margin-right: 50upx; +} + +.margin-tb-xs { + margin-top: 10upx; + margin-bottom: 10upx; +} + +.margin-tb-sm { + margin-top: 20upx; + margin-bottom: 20upx; +} + +.margin-tb { + margin-top: 30upx; + margin-bottom: 30upx; +} + +.margin-tb-lg { + margin-top: 40upx; + margin-bottom: 40upx; +} + +.margin-tb-xl { + margin-top: 50upx; + margin-bottom: 50upx; +} + +.padding-0 { + padding: 0; +} + +.padding-xs { + padding: 10upx; +} + +.padding-sm { + padding: 20upx; +} + +.padding { + padding: 30upx; +} + +.padding-lg { + padding: 40upx; +} + +.padding-xl { + padding: 50upx; +} + +.padding-top-xs { + padding-top: 10upx; +} + +.padding-top-sm { + padding-top: 20upx; +} + +.padding-top { + padding-top: 30upx; +} + +.padding-top-lg { + padding-top: 40upx; +} + +.padding-top-xl { + padding-top: 50upx; +} + +.padding-right-xs { + padding-right: 10upx; +} + +.padding-right-sm { + padding-right: 20upx; +} + +.padding-right { + padding-right: 30upx; +} + +.padding-right-lg { + padding-right: 40upx; +} + +.padding-right-xl { + padding-right: 50upx; +} + +.padding-bottom-xs { + padding-bottom: 10upx; +} + +.padding-bottom-sm { + padding-bottom: 20upx; +} + +.padding-bottom { + padding-bottom: 30upx; +} + +.padding-bottom-lg { + padding-bottom: 40upx; +} + +.padding-bottom-xl { + padding-bottom: 50upx; +} + +.padding-left-xs { + padding-left: 10upx; +} + +.padding-left-sm { + padding-left: 20upx; +} + +.padding-left { + padding-left: 30upx; +} + +.padding-left-lg { + padding-left: 40upx; +} + +.padding-left-xl { + padding-left: 50upx; +} + +.padding-lr-xs { + padding-left: 10upx; + padding-right: 10upx; +} + +.padding-lr-sm { + padding-left: 20upx; + padding-right: 20upx; +} + +.padding-lr { + padding-left: 30upx; + padding-right: 30upx; +} + +.padding-lr-lg { + padding-left: 40upx; + padding-right: 40upx; +} + +.padding-lr-xl { + padding-left: 50upx; + padding-right: 50upx; +} + +.padding-tb-xs { + padding-top: 10upx; + padding-bottom: 10upx; +} + +.padding-tb-sm { + padding-top: 20upx; + padding-bottom: 20upx; +} + +.padding-tb { + padding-top: 30upx; + padding-bottom: 30upx; +} + +.padding-tb-lg { + padding-top: 40upx; + padding-bottom: 40upx; +} + +.padding-tb-xl { + padding-top: 50upx; + padding-bottom: 50upx; +} + +/* -- 浮动 -- */ + +.cf::after, +.cf::before { + content: " "; + display: table; +} + +.cf::after { + clear: both; +} + +.fl { + float: left; +} + +.fr { + float: right; +} + +/* ================== + 背景 + ==================== */ + +.line-red::after, +.lines-red::after { + border-color: #e54d42; +} + +.line-orange::after, +.lines-orange::after { + border-color: #f37b1d; +} + +.line-yellow::after, +.lines-yellow::after { + border-color: #fbbd08; +} + +.line-olive::after, +.lines-olive::after { + border-color: #8dc63f; +} + +.line-green::after, +.lines-green::after { + border-color: #39b54a; +} + +.line-cyan::after, +.lines-cyan::after { + border-color: #1cbbb4; +} + +.line-blue::after, +.lines-blue::after { + border-color: #0081ff; +} + +.line-purple::after, +.lines-purple::after { + border-color: #6739b6; +} + +.line-mauve::after, +.lines-mauve::after { + border-color: #9c26b0; +} + +.line-pink::after, +.lines-pink::after { + border-color: #e03997; +} + +.line-brown::after, +.lines-brown::after { + border-color: #a5673f; +} + +.line-grey::after, +.lines-grey::after { + border-color: #8799a3; +} + +.line-gray::after, +.lines-gray::after { + border-color: #aaaaaa; +} + +.line-black::after, +.lines-black::after { + border-color: #333333; +} + +.line-white::after, +.lines-white::after { + border-color: #ffffff; +} + +.bg-red { + background-color: #e54d42; + color: #ffffff; +} + +.bg-orange { + background-color: #f37b1d; + color: #ffffff; +} + +.bg-yellow { + background-color: #fbbd08; + color: #333333; +} + +.bg-olive { + background-color: #8dc63f; + color: #ffffff; +} + +.bg-green { + background-color: #39b54a; + color: #ffffff; +} + +.bg-cyan { + background-color: #1cbbb4; + color: #ffffff; +} + +.bg-blue { + background-color: #0081ff; + color: #ffffff; +} + +.bg-purple { + background-color: #6739b6; + color: #ffffff; +} + +.bg-mauve { + background-color: #9c26b0; + color: #ffffff; +} + +.bg-pink { + background-color: #e03997; + color: #ffffff; +} + +.bg-brown { + background-color: #a5673f; + color: #ffffff; +} + +.bg-grey { + background-color: #8799a3; + color: #ffffff; +} + +.bg-gray { + background-color: #f0f0f0; + color: #333333; +} + +.bg-black { + background-color: #333333; + color: #ffffff; +} + +.bg-white { + background-color: #ffffff; + color: #666666; +} + +.bg-shadeTop { + background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01)); + color: #ffffff; +} + +.bg-shadeBottom { + background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1)); + color: #ffffff; +} + +.bg-red.light { + color: #e54d42; + background-color: #fadbd9; +} + +.bg-orange.light { + color: #f37b1d; + background-color: #fde6d2; +} + +.bg-yellow.light { + color: #fbbd08; + background-color: #fef2ced2; +} + +.bg-olive.light { + color: #8dc63f; + background-color: #e8f4d9; +} + +.bg-green.light { + color: #39b54a; + background-color: #d7f0dbff; +} + +.bg-cyan.light { + color: #1cbbb4; + background-color: #d2f1f0; +} + +.bg-blue.light { + color: #0081ff; + background-color: #cce6ff; +} + +.bg-purple.light { + color: #6739b6; + background-color: #e1d7f0; +} + +.bg-mauve.light { + color: #9c26b0; + background-color: #ebd4ef; +} + +.bg-pink.light { + color: #e03997; + background-color: #f9d7ea; +} + +.bg-brown.light { + color: #a5673f; + background-color: #ede1d9; +} + +.bg-grey.light { + color: #8799a3; + background-color: #e7ebed; +} + +.bg-gradual-red { + background-image: linear-gradient(45deg, #f43f3b, #ec008c); + color: #ffffff; +} + +.bg-gradual-orange { + background-image: linear-gradient(45deg, #ff9700, #ed1c24); + color: #ffffff; +} + +.bg-gradual-green { + background-image: linear-gradient(45deg, #39b54a, #8dc63f); + color: #ffffff; +} + +.bg-gradual-purple { + background-image: linear-gradient(45deg, #9000ff, #5e00ff); + color: #ffffff; +} + +.bg-gradual-pink { + background-image: linear-gradient(45deg, #ec008c, #6739b6); + color: #ffffff; +} + +.bg-gradual-blue { + background-image: linear-gradient(45deg, #0081ff, #1cbbb4); + color: #ffffff; +} + +.shadow[class*="-red"] { + box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2); +} + +.shadow[class*="-orange"] { + box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2); +} + +.shadow[class*="-yellow"] { + box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2); +} + +.shadow[class*="-olive"] { + box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2); +} + +.shadow[class*="-green"] { + box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2); +} + +.shadow[class*="-cyan"] { + box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2); +} + +.shadow[class*="-blue"] { + box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2); +} + +.shadow[class*="-purple"] { + box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2); +} + +.shadow[class*="-mauve"] { + box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2); +} + +.shadow[class*="-pink"] { + box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2); +} + +.shadow[class*="-brown"] { + box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2); +} + +.shadow[class*="-grey"] { + box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2); +} + +.shadow[class*="-gray"] { + box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2); +} + +.shadow[class*="-black"] { + box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2); +} + +.shadow[class*="-white"] { + box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2); +} + +.text-shadow[class*="-red"] { + text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2); +} + +.text-shadow[class*="-orange"] { + text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2); +} + +.text-shadow[class*="-yellow"] { + text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2); +} + +.text-shadow[class*="-olive"] { + text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2); +} + +.text-shadow[class*="-green"] { + text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2); +} + +.text-shadow[class*="-cyan"] { + text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2); +} + +.text-shadow[class*="-blue"] { + text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2); +} + +.text-shadow[class*="-purple"] { + text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2); +} + +.text-shadow[class*="-mauve"] { + text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2); +} + +.text-shadow[class*="-pink"] { + text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2); +} + +.text-shadow[class*="-brown"] { + text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2); +} + +.text-shadow[class*="-grey"] { + text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2); +} + +.text-shadow[class*="-gray"] { + text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2); +} + +.text-shadow[class*="-black"] { + text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2); +} + +.bg-img { + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.bg-mask { + background-color: #333333; + position: relative; +} + +.bg-mask::after { + content: ""; + border-radius: inherit; + width: 100%; + height: 100%; + display: block; + background-color: rgba(0, 0, 0, 0.4); + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; +} + +.bg-mask view, +.bg-mask cover-view { + z-index: 5; + position: relative; +} + +.bg-video { + position: relative; +} + +.bg-video video { + display: block; + height: 100%; + width: 100%; + -o-object-fit: cover; + object-fit: cover; + position: absolute; + top: 0; + z-index: 0; + pointer-events: none; +} + +/* ================== + 文本 + ==================== */ + +.text-xs { + font-size: 20upx; +} + +.text-sm { + font-size: 24upx; +} + +.text-df { + font-size: 28upx; +} + +.text-lg { + font-size: 32upx; +} + +.text-xl { + font-size: 36upx; +} + +.text-xxl { + font-size: 44upx; +} + +.text-sl { + font-size: 80upx; +} + +.text-xsl { + font-size: 120upx; +} + +.text-Abc { + text-transform: Capitalize; +} + +.text-ABC { + text-transform: Uppercase; +} + +.text-abc { + text-transform: Lowercase; +} + +.text-price::before { + content: "¥"; + font-size: 80%; + margin-right: 4upx; +} + +.text-cut { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.text-bold { + font-weight: bold; +} + +.text-center { + text-align: center; +} + +.text-content { + line-height: 1.6; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-red, +.line-red, +.lines-red { + color: #e54d42; +} + +.text-orange, +.line-orange, +.lines-orange { + color: #f37b1d; +} + +.text-yellow, +.line-yellow, +.lines-yellow { + color: #fbbd08; +} + +.text-olive, +.line-olive, +.lines-olive { + color: #8dc63f; +} + +.text-green, +.line-green, +.lines-green { + color: #39b54a; +} + +.text-cyan, +.line-cyan, +.lines-cyan { + color: #1cbbb4; +} + +.text-blue, +.line-blue, +.lines-blue { + color: #0081ff; +} + +.text-purple, +.line-purple, +.lines-purple { + color: #6739b6; +} + +.text-mauve, +.line-mauve, +.lines-mauve { + color: #9c26b0; +} + +.text-pink, +.line-pink, +.lines-pink { + color: #e03997; +} + +.text-brown, +.line-brown, +.lines-brown { + color: #a5673f; +} + +.text-grey, +.line-grey, +.lines-grey { + color: #8799a3; +} + +.text-gray, +.line-gray, +.lines-gray { + color: #aaaaaa; +} + +.text-black, +.line-black, +.lines-black { + color: #333333; +} + +.text-white, +.line-white, +.lines-white { + color: #ffffff; +} diff --git a/common/mqtt.js b/common/mqtt.js new file mode 100644 index 0000000..79ceffb --- /dev/null +++ b/common/mqtt.js @@ -0,0 +1,14633 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.mqtt = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i to + * + * @param {String} topic - topic to publish to + * @param {String, Buffer} message - message to publish + * @param {Object} [opts] - publish options, includes: + * {Number} qos - qos level to publish on + * {Boolean} retain - whether or not to retain the message + * {Boolean} dup - whether or not mark a message as duplicate + * {Function} cbStorePut - function(){} called when message is put into `outgoingStore` + * @param {Function} [callback] - function(err){} + * called when publish succeeds or fails + * @returns {MqttClient} this - for chaining + * @api public + * + * @example client.publish('topic', 'message'); + * @example + * client.publish('topic', 'message', {qos: 1, retain: true, dup: true}); + * @example client.publish('topic', 'message', console.log); + */ +MqttClient.prototype.publish = function (topic, message, opts, callback) { + var packet + var options = this.options + + // .publish(topic, payload, cb); + if (typeof opts === 'function') { + callback = opts + opts = null + } + + // default opts + var defaultOpts = {qos: 0, retain: false, dup: false} + opts = xtend(defaultOpts, opts) + + if (this._checkDisconnecting(callback)) { + return this + } + + packet = { + cmd: 'publish', + topic: topic, + payload: message, + qos: opts.qos, + retain: opts.retain, + messageId: this._nextId(), + dup: opts.dup + } + + if (options.protocolVersion === 5) { + packet.properties = opts.properties + if ((!options.properties && packet.properties && packet.properties.topicAlias) || ((opts.properties && options.properties) && + ((opts.properties.topicAlias && options.properties.topicAliasMaximum && opts.properties.topicAlias > options.properties.topicAliasMaximum) || + (!options.properties.topicAliasMaximum && opts.properties.topicAlias)))) { + /* + if we are don`t setup topic alias or + topic alias maximum less than topic alias or + server don`t give topic alias maximum, + we are removing topic alias from packet + */ + delete packet.properties.topicAlias + } + } + + switch (opts.qos) { + case 1: + case 2: + // Add to callbacks + this.outgoing[packet.messageId] = { + volatile: false, + cb: callback || nop + } + if (this._storeProcessing) { + this._packetIdsDuringStoreProcessing[packet.messageId] = false + this._storePacket(packet, undefined, opts.cbStorePut) + } else { + this._sendPacket(packet, undefined, opts.cbStorePut) + } + break + default: + if (this._storeProcessing) { + this._storePacket(packet, callback, opts.cbStorePut) + } else { + this._sendPacket(packet, callback, opts.cbStorePut) + } + break + } + + return this +} + +/** + * subscribe - subscribe to + * + * @param {String, Array, Object} topic - topic(s) to subscribe to, supports objects in the form {'topic': qos} + * @param {Object} [opts] - optional subscription options, includes: + * {Number} qos - subscribe qos level + * @param {Function} [callback] - function(err, granted){} where: + * {Error} err - subscription error (none at the moment!) + * {Array} granted - array of {topic: 't', qos: 0} + * @returns {MqttClient} this - for chaining + * @api public + * @example client.subscribe('topic'); + * @example client.subscribe('topic', {qos: 1}); + * @example client.subscribe({'topic': {qos: 0}, 'topic2': {qos: 1}}, console.log); + * @example client.subscribe('topic', console.log); + */ +MqttClient.prototype.subscribe = function () { + var packet + var args = new Array(arguments.length) + for (var i = 0; i < arguments.length; i++) { + args[i] = arguments[i] + } + var subs = [] + var obj = args.shift() + var resubscribe = obj.resubscribe + var callback = args.pop() || nop + var opts = args.pop() + var invalidTopic + var that = this + var version = this.options.protocolVersion + + delete obj.resubscribe + + if (typeof obj === 'string') { + obj = [obj] + } + + if (typeof callback !== 'function') { + opts = callback + callback = nop + } + + invalidTopic = validations.validateTopics(obj) + if (invalidTopic !== null) { + setImmediate(callback, new Error('Invalid topic ' + invalidTopic)) + return this + } + + if (this._checkDisconnecting(callback)) { + return this + } + + var defaultOpts = { + qos: 0 + } + if (version === 5) { + defaultOpts.nl = false + defaultOpts.rap = false + defaultOpts.rh = 0 + } + opts = xtend(defaultOpts, opts) + + if (Array.isArray(obj)) { + obj.forEach(function (topic) { + if (!that._resubscribeTopics.hasOwnProperty(topic) || + that._resubscribeTopics[topic].qos < opts.qos || + resubscribe) { + var currentOpts = { + topic: topic, + qos: opts.qos + } + if (version === 5) { + currentOpts.nl = opts.nl + currentOpts.rap = opts.rap + currentOpts.rh = opts.rh + currentOpts.properties = opts.properties + } + subs.push(currentOpts) + } + }) + } else { + Object + .keys(obj) + .forEach(function (k) { + if (!that._resubscribeTopics.hasOwnProperty(k) || + that._resubscribeTopics[k].qos < obj[k].qos || + resubscribe) { + var currentOpts = { + topic: k, + qos: obj[k].qos + } + if (version === 5) { + currentOpts.nl = obj[k].nl + currentOpts.rap = obj[k].rap + currentOpts.rh = obj[k].rh + currentOpts.properties = opts.properties + } + subs.push(currentOpts) + } + }) + } + + packet = { + cmd: 'subscribe', + subscriptions: subs, + qos: 1, + retain: false, + dup: false, + messageId: this._nextId() + } + + if (opts.properties) { + packet.properties = opts.properties + } + + if (!subs.length) { + callback(null, []) + return + } + + // subscriptions to resubscribe to in case of disconnect + if (this.options.resubscribe) { + var topics = [] + subs.forEach(function (sub) { + if (that.options.reconnectPeriod > 0) { + var topic = { qos: sub.qos } + if (version === 5) { + topic.nl = sub.nl || false + topic.rap = sub.rap || false + topic.rh = sub.rh || 0 + topic.properties = sub.properties + } + that._resubscribeTopics[sub.topic] = topic + topics.push(sub.topic) + } + }) + that.messageIdToTopic[packet.messageId] = topics + } + + this.outgoing[packet.messageId] = { + volatile: true, + cb: function (err, packet) { + if (!err) { + var granted = packet.granted + for (var i = 0; i < granted.length; i += 1) { + subs[i].qos = granted[i] + } + } + + callback(err, subs) + } + } + + this._sendPacket(packet) + + return this +} + +/** + * unsubscribe - unsubscribe from topic(s) + * + * @param {String, Array} topic - topics to unsubscribe from + * @param {Object} [opts] - optional subscription options, includes: + * {Object} properties - properties of unsubscribe packet + * @param {Function} [callback] - callback fired on unsuback + * @returns {MqttClient} this - for chaining + * @api public + * @example client.unsubscribe('topic'); + * @example client.unsubscribe('topic', console.log); + */ +MqttClient.prototype.unsubscribe = function () { + var packet = { + cmd: 'unsubscribe', + qos: 1, + messageId: this._nextId() + } + var that = this + var args = new Array(arguments.length) + for (var i = 0; i < arguments.length; i++) { + args[i] = arguments[i] + } + var topic = args.shift() + var callback = args.pop() || nop + var opts = args.pop() + + if (typeof topic === 'string') { + topic = [topic] + } + + if (typeof callback !== 'function') { + opts = callback + callback = nop + } + + if (this._checkDisconnecting(callback)) { + return this + } + + if (typeof topic === 'string') { + packet.unsubscriptions = [topic] + } else if (typeof topic === 'object' && topic.length) { + packet.unsubscriptions = topic + } + + if (this.options.resubscribe) { + packet.unsubscriptions.forEach(function (topic) { + delete that._resubscribeTopics[topic] + }) + } + + if (typeof opts === 'object' && opts.properties) { + packet.properties = opts.properties + } + + this.outgoing[packet.messageId] = { + volatile: true, + cb: callback + } + + this._sendPacket(packet) + + return this +} + +/** + * end - close connection + * + * @returns {MqttClient} this - for chaining + * @param {Boolean} force - do not wait for all in-flight messages to be acked + * @param {Function} cb - called when the client has been closed + * + * @api public + */ +MqttClient.prototype.end = function () { + var that = this + + var force = arguments[0] + var opts = arguments[1] + var cb = arguments[2] + + if (force == null || typeof force !== 'boolean') { + cb = opts || nop + opts = force + force = false + if (typeof opts !== 'object') { + cb = opts + opts = null + if (typeof cb !== 'function') { + cb = nop + } + } + } + + if (typeof opts !== 'object') { + cb = opts + opts = null + } + + cb = cb || nop + + function closeStores () { + that.disconnected = true + that.incomingStore.close(function () { + that.outgoingStore.close(function () { + if (cb) { + cb.apply(null, arguments) + } + that.emit('end') + }) + }) + if (that._deferredReconnect) { + that._deferredReconnect() + } + } + + function finish () { + // defer closesStores of an I/O cycle, + // just to make sure things are + // ok for websockets + that._cleanUp(force, setImmediate.bind(null, closeStores), opts) + } + + if (this.disconnecting) { + return this + } + + this._clearReconnect() + + this.disconnecting = true + + if (!force && Object.keys(this.outgoing).length > 0) { + // wait 10ms, just to be sure we received all of it + this.once('outgoingEmpty', setTimeout.bind(null, finish, 10)) + } else { + finish() + } + + return this +} + +/** + * removeOutgoingMessage - remove a message in outgoing store + * the outgoing callback will be called withe Error('Message removed') if the message is removed + * + * @param {Number} mid - messageId to remove message + * @returns {MqttClient} this - for chaining + * @api public + * + * @example client.removeOutgoingMessage(client.getLastMessageId()); + */ +MqttClient.prototype.removeOutgoingMessage = function (mid) { + var cb = this.outgoing[mid] ? this.outgoing[mid].cb : null + delete this.outgoing[mid] + this.outgoingStore.del({messageId: mid}, function () { + cb(new Error('Message removed')) + }) + return this +} + +/** + * reconnect - connect again using the same options as connect() + * + * @param {Object} [opts] - optional reconnect options, includes: + * {Store} incomingStore - a store for the incoming packets + * {Store} outgoingStore - a store for the outgoing packets + * if opts is not given, current stores are used + * @returns {MqttClient} this - for chaining + * + * @api public + */ +MqttClient.prototype.reconnect = function (opts) { + var that = this + var f = function () { + if (opts) { + that.options.incomingStore = opts.incomingStore + that.options.outgoingStore = opts.outgoingStore + } else { + that.options.incomingStore = null + that.options.outgoingStore = null + } + that.incomingStore = that.options.incomingStore || new Store() + that.outgoingStore = that.options.outgoingStore || new Store() + that.disconnecting = false + that.disconnected = false + that._deferredReconnect = null + that._reconnect() + } + + if (this.disconnecting && !this.disconnected) { + this._deferredReconnect = f + } else { + f() + } + return this +} + +/** + * _reconnect - implement reconnection + * @api privateish + */ +MqttClient.prototype._reconnect = function () { + this.emit('reconnect') + this._setupStream() +} + +/** + * _setupReconnect - setup reconnect timer + */ +MqttClient.prototype._setupReconnect = function () { + var that = this + + if (!that.disconnecting && !that.reconnectTimer && (that.options.reconnectPeriod > 0)) { + if (!this.reconnecting) { + this.emit('offline') + this.reconnecting = true + } + that.reconnectTimer = setInterval(function () { + that._reconnect() + }, that.options.reconnectPeriod) + } +} + +/** + * _clearReconnect - clear the reconnect timer + */ +MqttClient.prototype._clearReconnect = function () { + if (this.reconnectTimer) { + clearInterval(this.reconnectTimer) + this.reconnectTimer = null + } +} + +/** + * _cleanUp - clean up on connection end + * @api private + */ +MqttClient.prototype._cleanUp = function (forced, done) { + var opts = arguments[2] + if (done) { + this.stream.on('close', done) + } + + if (forced) { + if ((this.options.reconnectPeriod === 0) && this.options.clean) { + flush(this.outgoing) + } + this.stream.destroy() + } else { + var packet = xtend({ cmd: 'disconnect' }, opts) + this._sendPacket( + packet, + setImmediate.bind( + null, + this.stream.end.bind(this.stream) + ) + ) + } + + if (!this.disconnecting) { + this._clearReconnect() + this._setupReconnect() + } + + if (this.pingTimer !== null) { + this.pingTimer.clear() + this.pingTimer = null + } + + if (done && !this.connected) { + this.stream.removeListener('close', done) + done() + } +} + +/** + * _sendPacket - send or queue a packet + * @param {String} type - packet type (see `protocol`) + * @param {Object} packet - packet options + * @param {Function} cb - callback when the packet is sent + * @param {Function} cbStorePut - called when message is put into outgoingStore + * @api private + */ +MqttClient.prototype._sendPacket = function (packet, cb, cbStorePut) { + cbStorePut = cbStorePut || nop + + if (!this.connected) { + this._storePacket(packet, cb, cbStorePut) + return + } + + // When sending a packet, reschedule the ping timer + this._shiftPingInterval() + + switch (packet.cmd) { + case 'publish': + break + case 'pubrel': + storeAndSend(this, packet, cb, cbStorePut) + return + default: + sendPacket(this, packet, cb) + return + } + + switch (packet.qos) { + case 2: + case 1: + storeAndSend(this, packet, cb, cbStorePut) + break + /** + * no need of case here since it will be caught by default + * and jshint comply that before default it must be a break + * anyway it will result in -1 evaluation + */ + case 0: + /* falls through */ + default: + sendPacket(this, packet, cb) + break + } +} + +/** + * _storePacket - queue a packet + * @param {String} type - packet type (see `protocol`) + * @param {Object} packet - packet options + * @param {Function} cb - callback when the packet is sent + * @param {Function} cbStorePut - called when message is put into outgoingStore + * @api private + */ +MqttClient.prototype._storePacket = function (packet, cb, cbStorePut) { + cbStorePut = cbStorePut || nop + + if (((packet.qos || 0) === 0 && this.queueQoSZero) || packet.cmd !== 'publish') { + this.queue.push({ packet: packet, cb: cb }) + } else if (packet.qos > 0) { + cb = this.outgoing[packet.messageId] ? this.outgoing[packet.messageId].cb : null + this.outgoingStore.put(packet, function (err) { + if (err) { + return cb && cb(err) + } + cbStorePut() + }) + } else if (cb) { + cb(new Error('No connection to broker')) + } +} + +/** + * _setupPingTimer - setup the ping timer + * + * @api private + */ +MqttClient.prototype._setupPingTimer = function () { + var that = this + + if (!this.pingTimer && this.options.keepalive) { + this.pingResp = true + this.pingTimer = reInterval(function () { + that._checkPing() + }, this.options.keepalive * 1000) + } +} + +/** + * _shiftPingInterval - reschedule the ping interval + * + * @api private + */ +MqttClient.prototype._shiftPingInterval = function () { + if (this.pingTimer && this.options.keepalive && this.options.reschedulePings) { + this.pingTimer.reschedule(this.options.keepalive * 1000) + } +} +/** + * _checkPing - check if a pingresp has come back, and ping the server again + * + * @api private + */ +MqttClient.prototype._checkPing = function () { + if (this.pingResp) { + this.pingResp = false + this._sendPacket({ cmd: 'pingreq' }) + } else { + // do a forced cleanup since socket will be in bad shape + this._cleanUp(true) + } +} + +/** + * _handlePingresp - handle a pingresp + * + * @api private + */ +MqttClient.prototype._handlePingresp = function () { + this.pingResp = true +} + +/** + * _handleConnack + * + * @param {Object} packet + * @api private + */ + +MqttClient.prototype._handleConnack = function (packet) { + var options = this.options + var version = options.protocolVersion + var rc = version === 5 ? packet.reasonCode : packet.returnCode + + clearTimeout(this.connackTimer) + + if (packet.properties) { + if (packet.properties.topicAliasMaximum) { + if (!options.properties) { options.properties = {} } + options.properties.topicAliasMaximum = packet.properties.topicAliasMaximum + } + if (packet.properties.serverKeepAlive && options.keepalive) { + options.keepalive = packet.properties.serverKeepAlive + this._shiftPingInterval() + } + if (packet.properties.maximumPacketSize) { + if (!options.properties) { options.properties = {} } + options.properties.maximumPacketSize = packet.properties.maximumPacketSize + } + } + + if (rc === 0) { + this.reconnecting = false + this._onConnect(packet) + } else if (rc > 0) { + var err = new Error('Connection refused: ' + errors[rc]) + err.code = rc + this.emit('error', err) + } +} + +/** + * _handlePublish + * + * @param {Object} packet + * @api private + */ +/* +those late 2 case should be rewrite to comply with coding style: + +case 1: +case 0: + // do not wait sending a puback + // no callback passed + if (1 === qos) { + this._sendPacket({ + cmd: 'puback', + messageId: mid + }); + } + // emit the message event for both qos 1 and 0 + this.emit('message', topic, message, packet); + this.handleMessage(packet, done); + break; +default: + // do nothing but every switch mus have a default + // log or throw an error about unknown qos + break; + +for now i just suppressed the warnings +*/ +MqttClient.prototype._handlePublish = function (packet, done) { + done = typeof done !== 'undefined' ? done : nop + var topic = packet.topic.toString() + var message = packet.payload + var qos = packet.qos + var mid = packet.messageId + var that = this + var options = this.options + var validReasonCodes = [0, 16, 128, 131, 135, 144, 145, 151, 153] + + switch (qos) { + case 2: { + options.customHandleAcks(topic, message, packet, function (error, code) { + if (!(error instanceof Error)) { + code = error + error = null + } + if (error) { return that.emit('error', error) } + if (validReasonCodes.indexOf(code) === -1) { return that.emit('error', new Error('Wrong reason code for pubrec')) } + if (code) { + that._sendPacket({cmd: 'pubrec', messageId: mid, reasonCode: code}, done) + } else { + that.incomingStore.put(packet, function () { + that._sendPacket({cmd: 'pubrec', messageId: mid}, done) + }) + } + }) + break + } + case 1: { + // emit the message event + options.customHandleAcks(topic, message, packet, function (error, code) { + if (!(error instanceof Error)) { + code = error + error = null + } + if (error) { return that.emit('error', error) } + if (validReasonCodes.indexOf(code) === -1) { return that.emit('error', new Error('Wrong reason code for puback')) } + if (!code) { that.emit('message', topic, message, packet) } + that.handleMessage(packet, function (err) { + if (err) { + return done && done(err) + } + that._sendPacket({cmd: 'puback', messageId: mid, reasonCode: code}, done) + }) + }) + break + } + case 0: + // emit the message event + this.emit('message', topic, message, packet) + this.handleMessage(packet, done) + break + default: + // do nothing + // log or throw an error about unknown qos + break + } +} + +/** + * Handle messages with backpressure support, one at a time. + * Override at will. + * + * @param Packet packet the packet + * @param Function callback call when finished + * @api public + */ +MqttClient.prototype.handleMessage = function (packet, callback) { + callback() +} + +/** + * _handleAck + * + * @param {Object} packet + * @api private + */ + +MqttClient.prototype._handleAck = function (packet) { + /* eslint no-fallthrough: "off" */ + var mid = packet.messageId + var type = packet.cmd + var response = null + var cb = this.outgoing[mid] ? this.outgoing[mid].cb : null + var that = this + var err + + if (!cb) { + // Server sent an ack in error, ignore it. + return + } + + // Process + switch (type) { + case 'pubcomp': + // same thing as puback for QoS 2 + case 'puback': + var pubackRC = packet.reasonCode + // Callback - we're done + if (pubackRC && pubackRC > 0 && pubackRC !== 16) { + err = new Error('Publish error: ' + errors[pubackRC]) + err.code = pubackRC + cb(err, packet) + } + delete this.outgoing[mid] + this.outgoingStore.del(packet, cb) + break + case 'pubrec': + response = { + cmd: 'pubrel', + qos: 2, + messageId: mid + } + var pubrecRC = packet.reasonCode + + if (pubrecRC && pubrecRC > 0 && pubrecRC !== 16) { + err = new Error('Publish error: ' + errors[pubrecRC]) + err.code = pubrecRC + cb(err, packet) + } else { + this._sendPacket(response) + } + break + case 'suback': + delete this.outgoing[mid] + for (var grantedI = 0; grantedI < packet.granted.length; grantedI++) { + if ((packet.granted[grantedI] & 0x80) !== 0) { + // suback with Failure status + var topics = this.messageIdToTopic[mid] + if (topics) { + topics.forEach(function (topic) { + delete that._resubscribeTopics[topic] + }) + } + } + } + cb(null, packet) + break + case 'unsuback': + delete this.outgoing[mid] + cb(null) + break + default: + that.emit('error', new Error('unrecognized packet type')) + } + + if (this.disconnecting && + Object.keys(this.outgoing).length === 0) { + this.emit('outgoingEmpty') + } +} + +/** + * _handlePubrel + * + * @param {Object} packet + * @api private + */ +MqttClient.prototype._handlePubrel = function (packet, callback) { + callback = typeof callback !== 'undefined' ? callback : nop + var mid = packet.messageId + var that = this + + var comp = {cmd: 'pubcomp', messageId: mid} + + that.incomingStore.get(packet, function (err, pub) { + if (!err) { + that.emit('message', pub.topic, pub.payload, pub) + that.handleMessage(pub, function (err) { + if (err) { + return callback(err) + } + that.incomingStore.del(pub, nop) + that._sendPacket(comp, callback) + }) + } else { + that._sendPacket(comp, callback) + } + }) +} + +/** + * _handleDisconnect + * + * @param {Object} packet + * @api private + */ +MqttClient.prototype._handleDisconnect = function (packet) { + this.emit('disconnect', packet) +} + +/** + * _nextId + * @return unsigned int + */ +MqttClient.prototype._nextId = function () { + // id becomes current state of this.nextId and increments afterwards + var id = this.nextId++ + // Ensure 16 bit unsigned int (max 65535, nextId got one higher) + if (this.nextId === 65536) { + this.nextId = 1 + } + return id +} + +/** + * getLastMessageId + * @return unsigned int + */ +MqttClient.prototype.getLastMessageId = function () { + return (this.nextId === 1) ? 65535 : (this.nextId - 1) +} + +/** + * _resubscribe + * @api private + */ +MqttClient.prototype._resubscribe = function (connack) { + var _resubscribeTopicsKeys = Object.keys(this._resubscribeTopics) + if (!this._firstConnection && + (this.options.clean || (this.options.protocolVersion === 5 && !connack.sessionPresent)) && + _resubscribeTopicsKeys.length > 0) { + if (this.options.resubscribe) { + if (this.options.protocolVersion === 5) { + for (var topicI = 0; topicI < _resubscribeTopicsKeys.length; topicI++) { + var resubscribeTopic = {} + resubscribeTopic[_resubscribeTopicsKeys[topicI]] = this._resubscribeTopics[_resubscribeTopicsKeys[topicI]] + resubscribeTopic.resubscribe = true + this.subscribe(resubscribeTopic, {properties: resubscribeTopic[_resubscribeTopicsKeys[topicI]].properties}) + } + } else { + this._resubscribeTopics.resubscribe = true + this.subscribe(this._resubscribeTopics) + } + } else { + this._resubscribeTopics = {} + } + } + + this._firstConnection = false +} + +/** + * _onConnect + * + * @api private + */ +MqttClient.prototype._onConnect = function (packet) { + if (this.disconnected) { + this.emit('connect', packet) + return + } + + var that = this + + this._setupPingTimer() + this._resubscribe(packet) + + this.connected = true + + function startStreamProcess () { + var outStore = that.outgoingStore.createStream() + + function clearStoreProcessing () { + that._storeProcessing = false + that._packetIdsDuringStoreProcessing = {} + } + + that.once('close', remove) + outStore.on('error', function (err) { + clearStoreProcessing() + that.removeListener('close', remove) + that.emit('error', err) + }) + + function remove () { + outStore.destroy() + outStore = null + clearStoreProcessing() + } + + function storeDeliver () { + // edge case, we wrapped this twice + if (!outStore) { + return + } + that._storeProcessing = true + + var packet = outStore.read(1) + + var cb + + if (!packet) { + // read when data is available in the future + outStore.once('readable', storeDeliver) + return + } + + // Skip already processed store packets + if (that._packetIdsDuringStoreProcessing[packet.messageId]) { + storeDeliver() + return + } + + // Avoid unnecessary stream read operations when disconnected + if (!that.disconnecting && !that.reconnectTimer) { + cb = that.outgoing[packet.messageId] ? that.outgoing[packet.messageId].cb : null + that.outgoing[packet.messageId] = { + volatile: false, + cb: function (err, status) { + // Ensure that the original callback passed in to publish gets invoked + if (cb) { + cb(err, status) + } + + storeDeliver() + } + } + that._packetIdsDuringStoreProcessing[packet.messageId] = true + that._sendPacket(packet) + } else if (outStore.destroy) { + outStore.destroy() + } + } + + outStore.on('end', function () { + var allProcessed = true + for (var id in that._packetIdsDuringStoreProcessing) { + if (!that._packetIdsDuringStoreProcessing[id]) { + allProcessed = false + break + } + } + if (allProcessed) { + clearStoreProcessing() + that.removeListener('close', remove) + that.emit('connect', packet) + } else { + startStreamProcess() + } + }) + storeDeliver() + } + // start flowing + startStreamProcess() +} + +module.exports = MqttClient + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./store":7,"./validations":8,"_process":92,"events":13,"inherits":80,"mqtt-packet":84,"readable-stream":108,"reinterval":109,"xtend":121}],2:[function(require,module,exports){ +(function (Buffer){ +'use strict' + +var Transform = require('readable-stream').Transform +var duplexify = require('duplexify') +var base64 = require('base64-js') + +/* global FileReader */ +var my +var proxy +var stream +var isInitialized = false + +function buildProxy () { + var proxy = new Transform() + proxy._write = function (chunk, encoding, next) { + my.sendSocketMessage({ + data: chunk.buffer, + success: function () { + next() + }, + fail: function () { + next(new Error()) + } + }) + } + proxy._flush = function socketEnd (done) { + my.closeSocket({ + success: function () { + done() + } + }) + } + + return proxy +} + +function setDefaultOpts (opts) { + if (!opts.hostname) { + opts.hostname = 'localhost' + } + if (!opts.path) { + opts.path = '/' + } + + if (!opts.wsOptions) { + opts.wsOptions = {} + } +} + +function buildUrl (opts, client) { + var protocol = opts.protocol === 'alis' ? 'wss' : 'ws' + var url = protocol + '://' + opts.hostname + opts.path + if (opts.port && opts.port !== 80 && opts.port !== 443) { + url = protocol + '://' + opts.hostname + ':' + opts.port + opts.path + } + if (typeof (opts.transformWsUrl) === 'function') { + url = opts.transformWsUrl(url, opts, client) + } + return url +} + +function bindEventHandler () { + if (isInitialized) return + + isInitialized = true + + my.onSocketOpen(function () { + stream.setReadable(proxy) + stream.setWritable(proxy) + stream.emit('connect') + }) + + my.onSocketMessage(function (res) { + if (typeof res.data === 'string') { + var array = base64.toByteArray(res.data) + var buffer = Buffer.from(array) + proxy.push(buffer) + } else { + var reader = new FileReader() + reader.addEventListener('load', function () { + var data = reader.result + + if (data instanceof ArrayBuffer) data = Buffer.from(data) + else data = Buffer.from(data, 'utf8') + proxy.push(data) + }) + reader.readAsArrayBuffer(res.data) + } + }) + + my.onSocketClose(function () { + stream.end() + stream.destroy() + }) + + my.onSocketError(function (res) { + stream.destroy(res) + }) +} + +function buildStream (client, opts) { + opts.hostname = opts.hostname || opts.host + + if (!opts.hostname) { + throw new Error('Could not determine host. Specify host manually.') + } + + var websocketSubProtocol = + (opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3) + ? 'mqttv3.1' + : 'mqtt' + + setDefaultOpts(opts) + + var url = buildUrl(opts, client) + my = opts.my + my.connectSocket({ + url: url, + protocols: websocketSubProtocol + }) + + proxy = buildProxy() + stream = duplexify.obj() + + bindEventHandler() + + return stream +} + +module.exports = buildStream + +}).call(this,require("buffer").Buffer) +},{"base64-js":10,"buffer":12,"duplexify":17,"readable-stream":108}],3:[function(require,module,exports){ +'use strict' +var net = require('net') + +/* + variables port and host can be removed since + you have all required information in opts object +*/ +function buildBuilder (client, opts) { + var port, host + opts.port = opts.port || 1883 + opts.hostname = opts.hostname || opts.host || 'localhost' + + port = opts.port + host = opts.hostname + + return net.createConnection(port, host) +} + +module.exports = buildBuilder + +},{"net":11}],4:[function(require,module,exports){ +'use strict' +var tls = require('tls') + +function buildBuilder (mqttClient, opts) { + var connection + opts.port = opts.port || 8883 + opts.host = opts.hostname || opts.host || 'localhost' + + opts.rejectUnauthorized = opts.rejectUnauthorized !== false + + delete opts.path + + connection = tls.connect(opts) + /* eslint no-use-before-define: [2, "nofunc"] */ + connection.on('secureConnect', function () { + if (opts.rejectUnauthorized && !connection.authorized) { + connection.emit('error', new Error('TLS not authorized')) + } else { + connection.removeListener('error', handleTLSerrors) + } + }) + + function handleTLSerrors (err) { + // How can I get verify this error is a tls error? + if (opts.rejectUnauthorized) { + mqttClient.emit('error', err) + } + + // close this connection to match the behaviour of net + // otherwise all we get is an error from the connection + // and close event doesn't fire. This is a work around + // to enable the reconnect code to work the same as with + // net.createConnection + connection.end() + } + + connection.on('error', handleTLSerrors) + return connection +} + +module.exports = buildBuilder + +},{"tls":11}],5:[function(require,module,exports){ +(function (process){ +'use strict' + +var websocket = require('websocket-stream') +var urlModule = require('url') +var WSS_OPTIONS = [ + 'rejectUnauthorized', + 'ca', + 'cert', + 'key', + 'pfx', + 'passphrase' +] +var IS_BROWSER = process.title === 'browser' + +function buildUrl (opts, client) { + var url = opts.protocol + '://' + opts.hostname + ':' + opts.port + opts.path + if (typeof (opts.transformWsUrl) === 'function') { + url = opts.transformWsUrl(url, opts, client) + } + return url +} + +function setDefaultOpts (opts) { + if (!opts.hostname) { + opts.hostname = 'localhost' + } + if (!opts.port) { + if (opts.protocol === 'wss') { + opts.port = 443 + } else { + opts.port = 80 + } + } + if (!opts.path) { + opts.path = '/' + } + + if (!opts.wsOptions) { + opts.wsOptions = {} + } + if (!IS_BROWSER && opts.protocol === 'wss') { + // Add cert/key/ca etc options + WSS_OPTIONS.forEach(function (prop) { + if (opts.hasOwnProperty(prop) && !opts.wsOptions.hasOwnProperty(prop)) { + opts.wsOptions[prop] = opts[prop] + } + }) + } +} + +function createWebSocket (client, opts) { + var websocketSubProtocol = + (opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3) + ? 'mqttv3.1' + : 'mqtt' + + setDefaultOpts(opts) + var url = buildUrl(opts, client) + return websocket(url, [websocketSubProtocol], opts.wsOptions) +} + +function buildBuilder (client, opts) { + return createWebSocket(client, opts) +} + +function buildBuilderBrowser (client, opts) { + if (!opts.hostname) { + opts.hostname = opts.host + } + + if (!opts.hostname) { + // Throwing an error in a Web Worker if no `hostname` is given, because we + // can not determine the `hostname` automatically. If connecting to + // localhost, please supply the `hostname` as an argument. + if (typeof (document) === 'undefined') { + throw new Error('Could not determine host. Specify host manually.') + } + var parsed = urlModule.parse(document.URL) + opts.hostname = parsed.hostname + + if (!opts.port) { + opts.port = parsed.port + } + } + return createWebSocket(client, opts) +} + +if (IS_BROWSER) { + module.exports = buildBuilderBrowser +} else { + module.exports = buildBuilder +} + +}).call(this,require('_process')) +},{"_process":92,"url":113,"websocket-stream":118}],6:[function(require,module,exports){ +(function (process,Buffer){ +'use strict' + +var Transform = require('readable-stream').Transform +var duplexify = require('duplexify') + +/* global wx */ +var socketTask +var proxy +var stream + +function buildProxy () { + var proxy = new Transform() + proxy._write = function (chunk, encoding, next) { + socketTask.send({ + data: chunk.buffer, + success: function () { + next() + }, + fail: function (errMsg) { + next(new Error(errMsg)) + } + }) + } + proxy._flush = function socketEnd (done) { + socketTask.close({ + success: function () { + done() + } + }) + } + + return proxy +} + +function setDefaultOpts (opts) { + if (!opts.hostname) { + opts.hostname = 'localhost' + } + if (!opts.path) { + opts.path = '/' + } + + if (!opts.wsOptions) { + opts.wsOptions = {} + } +} + +function buildUrl (opts, client) { + var protocol = opts.protocol === 'wxs' ? 'wss' : 'ws' + var url = protocol + '://' + opts.hostname + opts.path + if (opts.port && opts.port !== 80 && opts.port !== 443) { + url = protocol + '://' + opts.hostname + ':' + opts.port + opts.path + } + if (typeof (opts.transformWsUrl) === 'function') { + url = opts.transformWsUrl(url, opts, client) + } + return url +} + +function bindEventHandler () { + socketTask.onOpen(function () { + stream.setReadable(proxy) + stream.setWritable(proxy) + stream.emit('connect') + }) + + socketTask.onMessage(function (res) { + var data = res.data + + if (data instanceof ArrayBuffer) data = Buffer.from(data) + else data = Buffer.from(data, 'utf8') + proxy.push(data) + }) + + socketTask.onClose(function () { + stream.end() + stream.destroy() + }) + + socketTask.onError(function (res) { + stream.destroy(new Error(res.errMsg)) + }) +} + +function buildStream (client, opts) { + opts.hostname = opts.hostname || opts.host + + if (!opts.hostname) { + throw new Error('Could not determine host. Specify host manually.') + } + + var websocketSubProtocol = + (opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3) + ? 'mqttv3.1' + : 'mqtt' + + setDefaultOpts(opts) + + var url = buildUrl(opts, client) + socketTask = wx.connectSocket({ + url: url, + protocols: websocketSubProtocol + }) + + proxy = buildProxy() + stream = duplexify.obj() + stream._destroy = function (err, cb) { + socketTask.close({ + success: function () { + cb && cb(err) + } + }) + } + + var destroyRef = stream.destroy + stream.destroy = function () { + stream.destroy = destroyRef + + var self = this + process.nextTick(function () { + socketTask.close({ + fail: function () { + self._destroy(new Error()) + } + }) + }) + }.bind(stream) + + bindEventHandler() + + return stream +} + +module.exports = buildStream + +}).call(this,require('_process'),require("buffer").Buffer) +},{"_process":92,"buffer":12,"duplexify":17,"readable-stream":108}],7:[function(require,module,exports){ +(function (process){ +'use strict' + +/** + * Module dependencies + */ +var xtend = require('xtend') + +var Readable = require('readable-stream').Readable +var streamsOpts = { objectMode: true } +var defaultStoreOptions = { + clean: true +} + +/** + * es6-map can preserve insertion order even if ES version is older. + * + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Description + * It should be noted that a Map which is a map of an object, especially + * a dictionary of dictionaries, will only map to the object's insertion + * order. In ES2015 this is ordered for objects but for older versions of + * ES, this may be random and not ordered. + * + */ +var Map = require('es6-map') + +/** + * In-memory implementation of the message store + * This can actually be saved into files. + * + * @param {Object} [options] - store options + */ +function Store (options) { + if (!(this instanceof Store)) { + return new Store(options) + } + + this.options = options || {} + + // Defaults + this.options = xtend(defaultStoreOptions, options) + + this._inflights = new Map() +} + +/** + * Adds a packet to the store, a packet is + * anything that has a messageId property. + * + */ +Store.prototype.put = function (packet, cb) { + this._inflights.set(packet.messageId, packet) + + if (cb) { + cb() + } + + return this +} + +/** + * Creates a stream with all the packets in the store + * + */ +Store.prototype.createStream = function () { + var stream = new Readable(streamsOpts) + var destroyed = false + var values = [] + var i = 0 + + this._inflights.forEach(function (value, key) { + values.push(value) + }) + + stream._read = function () { + if (!destroyed && i < values.length) { + this.push(values[i++]) + } else { + this.push(null) + } + } + + stream.destroy = function () { + if (destroyed) { + return + } + + var self = this + + destroyed = true + + process.nextTick(function () { + self.emit('close') + }) + } + + return stream +} + +/** + * deletes a packet from the store. + */ +Store.prototype.del = function (packet, cb) { + packet = this._inflights.get(packet.messageId) + if (packet) { + this._inflights.delete(packet.messageId) + cb(null, packet) + } else if (cb) { + cb(new Error('missing packet')) + } + + return this +} + +/** + * get a packet from the store. + */ +Store.prototype.get = function (packet, cb) { + packet = this._inflights.get(packet.messageId) + if (packet) { + cb(null, packet) + } else if (cb) { + cb(new Error('missing packet')) + } + + return this +} + +/** + * Close the store + */ +Store.prototype.close = function (cb) { + if (this.options.clean) { + this._inflights = null + } + if (cb) { + cb() + } +} + +module.exports = Store + +}).call(this,require('_process')) +},{"_process":92,"es6-map":67,"readable-stream":108,"xtend":121}],8:[function(require,module,exports){ +'use strict' + +/** + * Validate a topic to see if it's valid or not. + * A topic is valid if it follow below rules: + * - Rule #1: If any part of the topic is not `+` or `#`, then it must not contain `+` and '#' + * - Rule #2: Part `#` must be located at the end of the mailbox + * + * @param {String} topic - A topic + * @returns {Boolean} If the topic is valid, returns true. Otherwise, returns false. + */ +function validateTopic (topic) { + var parts = topic.split('/') + + for (var i = 0; i < parts.length; i++) { + if (parts[i] === '+') { + continue + } + + if (parts[i] === '#') { + // for Rule #2 + return i === parts.length - 1 + } + + if (parts[i].indexOf('+') !== -1 || parts[i].indexOf('#') !== -1) { + return false + } + } + + return true +} + +/** + * Validate an array of topics to see if any of them is valid or not + * @param {Array} topics - Array of topics + * @returns {String} If the topics is valid, returns null. Otherwise, returns the invalid one + */ +function validateTopics (topics) { + if (topics.length === 0) { + return 'empty_topic_list' + } + for (var i = 0; i < topics.length; i++) { + if (!validateTopic(topics[i])) { + return topics[i] + } + } + return null +} + +module.exports = { + validateTopics: validateTopics +} + +},{}],9:[function(require,module,exports){ +(function (process){ +'use strict' + +var MqttClient = require('../client') +var Store = require('../store') +var url = require('url') +var xtend = require('xtend') +var protocols = {} + +if (process.title !== 'browser') { + protocols.mqtt = require('./tcp') + protocols.tcp = require('./tcp') + protocols.ssl = require('./tls') + protocols.tls = require('./tls') + protocols.mqtts = require('./tls') +} else { + protocols.wx = require('./wx') + protocols.wxs = require('./wx') + + protocols.ali = require('./ali') + protocols.alis = require('./ali') +} + +protocols.ws = require('./ws') +protocols.wss = require('./ws') + +/** + * Parse the auth attribute and merge username and password in the options object. + * + * @param {Object} [opts] option object + */ +function parseAuthOptions (opts) { + var matches + if (opts.auth) { + matches = opts.auth.match(/^(.+):(.+)$/) + if (matches) { + opts.username = matches[1] + opts.password = matches[2] + } else { + opts.username = opts.auth + } + } +} + +/** + * connect - connect to an MQTT broker. + * + * @param {String} [brokerUrl] - url of the broker, optional + * @param {Object} opts - see MqttClient#constructor + */ +function connect (brokerUrl, opts) { + if ((typeof brokerUrl === 'object') && !opts) { + opts = brokerUrl + brokerUrl = null + } + + opts = opts || {} + + if (brokerUrl) { + var parsed = url.parse(brokerUrl, true) + if (parsed.port != null) { + parsed.port = Number(parsed.port) + } + + opts = xtend(parsed, opts) + + if (opts.protocol === null) { + throw new Error('Missing protocol') + } + opts.protocol = opts.protocol.replace(/:$/, '') + } + + // merge in the auth options if supplied + parseAuthOptions(opts) + + // support clientId passed in the query string of the url + if (opts.query && typeof opts.query.clientId === 'string') { + opts.clientId = opts.query.clientId + } + + if (opts.cert && opts.key) { + if (opts.protocol) { + if (['mqtts', 'wss', 'wxs', 'alis'].indexOf(opts.protocol) === -1) { + switch (opts.protocol) { + case 'mqtt': + opts.protocol = 'mqtts' + break + case 'ws': + opts.protocol = 'wss' + break + case 'wx': + opts.protocol = 'wxs' + break + case 'ali': + opts.protocol = 'alis' + break + default: + throw new Error('Unknown protocol for secure connection: "' + opts.protocol + '"!') + } + } + } else { + // don't know what protocol he want to use, mqtts or wss + throw new Error('Missing secure protocol key') + } + } + + if (!protocols[opts.protocol]) { + var isSecure = ['mqtts', 'wss'].indexOf(opts.protocol) !== -1 + opts.protocol = [ + 'mqtt', + 'mqtts', + 'ws', + 'wss', + 'wx', + 'wxs', + 'ali', + 'alis' + ].filter(function (key, index) { + if (isSecure && index % 2 === 0) { + // Skip insecure protocols when requesting a secure one. + return false + } + return (typeof protocols[key] === 'function') + })[0] + } + + if (opts.clean === false && !opts.clientId) { + throw new Error('Missing clientId for unclean clients') + } + + if (opts.protocol) { + opts.defaultProtocol = opts.protocol + } + + function wrapper (client) { + if (opts.servers) { + if (!client._reconnectCount || client._reconnectCount === opts.servers.length) { + client._reconnectCount = 0 + } + + opts.host = opts.servers[client._reconnectCount].host + opts.port = opts.servers[client._reconnectCount].port + opts.protocol = (!opts.servers[client._reconnectCount].protocol ? opts.defaultProtocol : opts.servers[client._reconnectCount].protocol) + opts.hostname = opts.host + + client._reconnectCount++ + } + + return protocols[opts.protocol](client, opts) + } + + return new MqttClient(wrapper, opts) +} + +module.exports = connect +module.exports.connect = connect +module.exports.MqttClient = MqttClient +module.exports.Store = Store + +}).call(this,require('_process')) +},{"../client":1,"../store":7,"./ali":2,"./tcp":3,"./tls":4,"./ws":5,"./wx":6,"_process":92,"url":113,"xtend":121}],10:[function(require,module,exports){ +'use strict' + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + for (var i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + +},{}],11:[function(require,module,exports){ + +},{}],12:[function(require,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1) + arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = Buffer.prototype + return buf +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species != null && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayLike(value) + } + + if (value == null) { + throw TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + var valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + var b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from( + value[Symbol.toPrimitive]('string'), encodingOrOffset, length + ) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) + + var actual = buf.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike (array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + var buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + buf.__proto__ = Buffer.prototype + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (isInstance(buf, Uint8Array)) { + buf = Buffer.from(buf) + } + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + var len = string.length + var mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + var strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = Buffer.prototype + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (var i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + var len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +},{"base64-js":10,"ieee754":79}],13:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var objectCreate = Object.create || objectCreatePolyfill +var objectKeys = Object.keys || objectKeysPolyfill +var bind = Function.prototype.bind || functionBindPolyfill + +function EventEmitter() { + if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) { + this._events = objectCreate(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +var defaultMaxListeners = 10; + +var hasDefineProperty; +try { + var o = {}; + if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 }); + hasDefineProperty = o.x === 0; +} catch (err) { hasDefineProperty = false } +if (hasDefineProperty) { + Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + // check whether the input is a positive number (whose value is zero or + // greater and not a NaN). + if (typeof arg !== 'number' || arg < 0 || arg !== arg) + throw new TypeError('"defaultMaxListeners" must be a positive number'); + defaultMaxListeners = arg; + } + }); +} else { + EventEmitter.defaultMaxListeners = defaultMaxListeners; +} + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || isNaN(n)) + throw new TypeError('"n" argument must be a positive number'); + this._maxListeners = n; + return this; +}; + +function $getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return $getMaxListeners(this); +}; + +// These standalone emit* functions are used to optimize calling of event +// handlers for fast cases because emit() itself often has a variable number of +// arguments and can be deoptimized because of that. These functions always have +// the same number of arguments and thus do not get deoptimized, so the code +// inside them can execute faster. +function emitNone(handler, isFn, self) { + if (isFn) + handler.call(self); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self); + } +} +function emitOne(handler, isFn, self, arg1) { + if (isFn) + handler.call(self, arg1); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1); + } +} +function emitTwo(handler, isFn, self, arg1, arg2) { + if (isFn) + handler.call(self, arg1, arg2); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2); + } +} +function emitThree(handler, isFn, self, arg1, arg2, arg3) { + if (isFn) + handler.call(self, arg1, arg2, arg3); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2, arg3); + } +} + +function emitMany(handler, isFn, self, args) { + if (isFn) + handler.apply(self, args); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].apply(self, args); + } +} + +EventEmitter.prototype.emit = function emit(type) { + var er, handler, len, args, i, events; + var doError = (type === 'error'); + + events = this._events; + if (events) + doError = (doError && events.error == null); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + if (arguments.length > 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],14:[function(require,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) +},{"../../is-buffer/index.js":81}],15:[function(require,module,exports){ +'use strict'; + +var copy = require('es5-ext/object/copy') + , normalizeOptions = require('es5-ext/object/normalize-options') + , ensureCallable = require('es5-ext/object/valid-callable') + , map = require('es5-ext/object/map') + , callable = require('es5-ext/object/valid-callable') + , validValue = require('es5-ext/object/valid-value') + + , bind = Function.prototype.bind, defineProperty = Object.defineProperty + , hasOwnProperty = Object.prototype.hasOwnProperty + , define; + +define = function (name, desc, options) { + var value = validValue(desc) && callable(desc.value), dgs; + dgs = copy(desc); + delete dgs.writable; + delete dgs.value; + dgs.get = function () { + if (!options.overwriteDefinition && hasOwnProperty.call(this, name)) return value; + desc.value = bind.call(value, options.resolveContext ? options.resolveContext(this) : this); + defineProperty(this, name, desc); + return this[name]; + }; + return dgs; +}; + +module.exports = function (props/*, options*/) { + var options = normalizeOptions(arguments[1]); + if (options.resolveContext != null) ensureCallable(options.resolveContext); + return map(props, function (desc, name) { return define(name, desc, options); }); +}; + +},{"es5-ext/object/copy":39,"es5-ext/object/map":48,"es5-ext/object/normalize-options":49,"es5-ext/object/valid-callable":54,"es5-ext/object/valid-value":55}],16:[function(require,module,exports){ +'use strict'; + +var assign = require('es5-ext/object/assign') + , normalizeOpts = require('es5-ext/object/normalize-options') + , isCallable = require('es5-ext/object/is-callable') + , contains = require('es5-ext/string/#/contains') + + , d; + +d = module.exports = function (dscr, value/*, options*/) { + var c, e, w, options, desc; + if ((arguments.length < 2) || (typeof dscr !== 'string')) { + options = value; + value = dscr; + dscr = null; + } else { + options = arguments[2]; + } + if (dscr == null) { + c = w = true; + e = false; + } else { + c = contains.call(dscr, 'c'); + e = contains.call(dscr, 'e'); + w = contains.call(dscr, 'w'); + } + + desc = { value: value, configurable: c, enumerable: e, writable: w }; + return !options ? desc : assign(normalizeOpts(options), desc); +}; + +d.gs = function (dscr, get, set/*, options*/) { + var c, e, options, desc; + if (typeof dscr !== 'string') { + options = set; + set = get; + get = dscr; + dscr = null; + } else { + options = arguments[3]; + } + if (get == null) { + get = undefined; + } else if (!isCallable(get)) { + options = get; + get = set = undefined; + } else if (set == null) { + set = undefined; + } else if (!isCallable(set)) { + options = set; + set = undefined; + } + if (dscr == null) { + c = true; + e = false; + } else { + c = contains.call(dscr, 'c'); + e = contains.call(dscr, 'e'); + } + + desc = { get: get, set: set, configurable: c, enumerable: e }; + return !options ? desc : assign(normalizeOpts(options), desc); +}; + +},{"es5-ext/object/assign":36,"es5-ext/object/is-callable":42,"es5-ext/object/normalize-options":49,"es5-ext/string/#/contains":56}],17:[function(require,module,exports){ +(function (process,Buffer){ +var stream = require('readable-stream') +var eos = require('end-of-stream') +var inherits = require('inherits') +var shift = require('stream-shift') + +var SIGNAL_FLUSH = (Buffer.from && Buffer.from !== Uint8Array.from) + ? Buffer.from([0]) + : new Buffer([0]) + +var onuncork = function(self, fn) { + if (self._corked) self.once('uncork', fn) + else fn() +} + +var autoDestroy = function (self, err) { + if (self._autoDestroy) self.destroy(err) +} + +var destroyer = function(self, end) { + return function(err) { + if (err) autoDestroy(self, err.message === 'premature close' ? null : err) + else if (end && !self._ended) self.end() + } +} + +var end = function(ws, fn) { + if (!ws) return fn() + if (ws._writableState && ws._writableState.finished) return fn() + if (ws._writableState) return ws.end(fn) + ws.end() + fn() +} + +var toStreams2 = function(rs) { + return new (stream.Readable)({objectMode:true, highWaterMark:16}).wrap(rs) +} + +var Duplexify = function(writable, readable, opts) { + if (!(this instanceof Duplexify)) return new Duplexify(writable, readable, opts) + stream.Duplex.call(this, opts) + + this._writable = null + this._readable = null + this._readable2 = null + + this._autoDestroy = !opts || opts.autoDestroy !== false + this._forwardDestroy = !opts || opts.destroy !== false + this._forwardEnd = !opts || opts.end !== false + this._corked = 1 // start corked + this._ondrain = null + this._drained = false + this._forwarding = false + this._unwrite = null + this._unread = null + this._ended = false + + this.destroyed = false + + if (writable) this.setWritable(writable) + if (readable) this.setReadable(readable) +} + +inherits(Duplexify, stream.Duplex) + +Duplexify.obj = function(writable, readable, opts) { + if (!opts) opts = {} + opts.objectMode = true + opts.highWaterMark = 16 + return new Duplexify(writable, readable, opts) +} + +Duplexify.prototype.cork = function() { + if (++this._corked === 1) this.emit('cork') +} + +Duplexify.prototype.uncork = function() { + if (this._corked && --this._corked === 0) this.emit('uncork') +} + +Duplexify.prototype.setWritable = function(writable) { + if (this._unwrite) this._unwrite() + + if (this.destroyed) { + if (writable && writable.destroy) writable.destroy() + return + } + + if (writable === null || writable === false) { + this.end() + return + } + + var self = this + var unend = eos(writable, {writable:true, readable:false}, destroyer(this, this._forwardEnd)) + + var ondrain = function() { + var ondrain = self._ondrain + self._ondrain = null + if (ondrain) ondrain() + } + + var clear = function() { + self._writable.removeListener('drain', ondrain) + unend() + } + + if (this._unwrite) process.nextTick(ondrain) // force a drain on stream reset to avoid livelocks + + this._writable = writable + this._writable.on('drain', ondrain) + this._unwrite = clear + + this.uncork() // always uncork setWritable +} + +Duplexify.prototype.setReadable = function(readable) { + if (this._unread) this._unread() + + if (this.destroyed) { + if (readable && readable.destroy) readable.destroy() + return + } + + if (readable === null || readable === false) { + this.push(null) + this.resume() + return + } + + var self = this + var unend = eos(readable, {writable:false, readable:true}, destroyer(this)) + + var onreadable = function() { + self._forward() + } + + var onend = function() { + self.push(null) + } + + var clear = function() { + self._readable2.removeListener('readable', onreadable) + self._readable2.removeListener('end', onend) + unend() + } + + this._drained = true + this._readable = readable + this._readable2 = readable._readableState ? readable : toStreams2(readable) + this._readable2.on('readable', onreadable) + this._readable2.on('end', onend) + this._unread = clear + + this._forward() +} + +Duplexify.prototype._read = function() { + this._drained = true + this._forward() +} + +Duplexify.prototype._forward = function() { + if (this._forwarding || !this._readable2 || !this._drained) return + this._forwarding = true + + var data + + while (this._drained && (data = shift(this._readable2)) !== null) { + if (this.destroyed) continue + this._drained = this.push(data) + } + + this._forwarding = false +} + +Duplexify.prototype.destroy = function(err) { + if (this.destroyed) return + this.destroyed = true + + var self = this + process.nextTick(function() { + self._destroy(err) + }) +} + +Duplexify.prototype._destroy = function(err) { + if (err) { + var ondrain = this._ondrain + this._ondrain = null + if (ondrain) ondrain(err) + else this.emit('error', err) + } + + if (this._forwardDestroy) { + if (this._readable && this._readable.destroy) this._readable.destroy() + if (this._writable && this._writable.destroy) this._writable.destroy() + } + + this.emit('close') +} + +Duplexify.prototype._write = function(data, enc, cb) { + if (this.destroyed) return cb() + if (this._corked) return onuncork(this, this._write.bind(this, data, enc, cb)) + if (data === SIGNAL_FLUSH) return this._finish(cb) + if (!this._writable) return cb() + + if (this._writable.write(data) === false) this._ondrain = cb + else cb() +} + +Duplexify.prototype._finish = function(cb) { + var self = this + this.emit('preend') + onuncork(this, function() { + end(self._forwardEnd && self._writable, function() { + // haxx to not emit prefinish twice + if (self._writableState.prefinished === false) self._writableState.prefinished = true + self.emit('prefinish') + onuncork(self, cb) + }) + }) +} + +Duplexify.prototype.end = function(data, enc, cb) { + if (typeof data === 'function') return this.end(null, null, data) + if (typeof enc === 'function') return this.end(data, null, enc) + this._ended = true + if (data) this.write(data) + if (!this._writableState.ending) this.write(SIGNAL_FLUSH) + return stream.Writable.prototype.end.call(this, cb) +} + +module.exports = Duplexify + +}).call(this,require('_process'),require("buffer").Buffer) +},{"_process":92,"buffer":12,"end-of-stream":18,"inherits":80,"readable-stream":108,"stream-shift":111}],18:[function(require,module,exports){ +var once = require('once'); + +var noop = function() {}; + +var isRequest = function(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +}; + +var isChildProcess = function(stream) { + return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 +}; + +var eos = function(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + + callback = once(callback || noop); + + var ws = stream._writableState; + var rs = stream._readableState; + var readable = opts.readable || (opts.readable !== false && stream.readable); + var writable = opts.writable || (opts.writable !== false && stream.writable); + + var onlegacyfinish = function() { + if (!stream.writable) onfinish(); + }; + + var onfinish = function() { + writable = false; + if (!readable) callback.call(stream); + }; + + var onend = function() { + readable = false; + if (!writable) callback.call(stream); + }; + + var onexit = function(exitCode) { + callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); + }; + + var onerror = function(err) { + callback.call(stream, err); + }; + + var onclose = function() { + if (readable && !(rs && rs.ended)) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && ws.ended)) return callback.call(stream, new Error('premature close')); + }; + + var onrequest = function() { + stream.req.on('finish', onfinish); + }; + + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest(); + else stream.on('request', onrequest); + } else if (writable && !ws) { // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + + if (isChildProcess(stream)) stream.on('exit', onexit); + + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + + return function() { + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('exit', onexit); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +}; + +module.exports = eos; + +},{"once":90}],19:[function(require,module,exports){ +// Inspired by Google Closure: +// http://closure-library.googlecode.com/svn/docs/ +// closure_goog_array_array.js.html#goog.array.clear + +"use strict"; + +var value = require("../../object/valid-value"); + +module.exports = function () { + value(this).length = 0; + return this; +}; + +},{"../../object/valid-value":55}],20:[function(require,module,exports){ +"use strict"; + +var numberIsNaN = require("../../number/is-nan") + , toPosInt = require("../../number/to-pos-integer") + , value = require("../../object/valid-value") + , indexOf = Array.prototype.indexOf + , objHasOwnProperty = Object.prototype.hasOwnProperty + , abs = Math.abs + , floor = Math.floor; + +module.exports = function (searchElement /*, fromIndex*/) { + var i, length, fromIndex, val; + if (!numberIsNaN(searchElement)) return indexOf.apply(this, arguments); + + length = toPosInt(value(this).length); + fromIndex = arguments[1]; + if (isNaN(fromIndex)) fromIndex = 0; + else if (fromIndex >= 0) fromIndex = floor(fromIndex); + else fromIndex = toPosInt(this.length) - floor(abs(fromIndex)); + + for (i = fromIndex; i < length; ++i) { + if (objHasOwnProperty.call(this, i)) { + val = this[i]; + if (numberIsNaN(val)) return i; // Jslint: ignore + } + } + return -1; +}; + +},{"../../number/is-nan":30,"../../number/to-pos-integer":34,"../../object/valid-value":55}],21:[function(require,module,exports){ +"use strict"; + +module.exports = require("./is-implemented")() + ? Array.from + : require("./shim"); + +},{"./is-implemented":22,"./shim":23}],22:[function(require,module,exports){ +"use strict"; + +module.exports = function () { + var from = Array.from, arr, result; + if (typeof from !== "function") return false; + arr = ["raz", "dwa"]; + result = from(arr); + return Boolean(result && (result !== arr) && (result[1] === "dwa")); +}; + +},{}],23:[function(require,module,exports){ +"use strict"; + +var iteratorSymbol = require("es6-symbol").iterator + , isArguments = require("../../function/is-arguments") + , isFunction = require("../../function/is-function") + , toPosInt = require("../../number/to-pos-integer") + , callable = require("../../object/valid-callable") + , validValue = require("../../object/valid-value") + , isValue = require("../../object/is-value") + , isString = require("../../string/is-string") + , isArray = Array.isArray + , call = Function.prototype.call + , desc = { configurable: true, enumerable: true, writable: true, value: null } + , defineProperty = Object.defineProperty; + +// eslint-disable-next-line complexity +module.exports = function (arrayLike /*, mapFn, thisArg*/) { + var mapFn = arguments[1] + , thisArg = arguments[2] + , Context + , i + , j + , arr + , length + , code + , iterator + , result + , getIterator + , value; + + arrayLike = Object(validValue(arrayLike)); + + if (isValue(mapFn)) callable(mapFn); + if (!this || this === Array || !isFunction(this)) { + // Result: Plain array + if (!mapFn) { + if (isArguments(arrayLike)) { + // Source: Arguments + length = arrayLike.length; + if (length !== 1) return Array.apply(null, arrayLike); + arr = new Array(1); + arr[0] = arrayLike[0]; + return arr; + } + if (isArray(arrayLike)) { + // Source: Array + arr = new Array(length = arrayLike.length); + for (i = 0; i < length; ++i) arr[i] = arrayLike[i]; + return arr; + } + } + arr = []; + } else { + // Result: Non plain array + Context = this; + } + + if (!isArray(arrayLike)) { + if ((getIterator = arrayLike[iteratorSymbol]) !== undefined) { + // Source: Iterator + iterator = callable(getIterator).call(arrayLike); + if (Context) arr = new Context(); + result = iterator.next(); + i = 0; + while (!result.done) { + value = mapFn ? call.call(mapFn, thisArg, result.value, i) : result.value; + if (Context) { + desc.value = value; + defineProperty(arr, i, desc); + } else { + arr[i] = value; + } + result = iterator.next(); + ++i; + } + length = i; + } else if (isString(arrayLike)) { + // Source: String + length = arrayLike.length; + if (Context) arr = new Context(); + for (i = 0, j = 0; i < length; ++i) { + value = arrayLike[i]; + if (i + 1 < length) { + code = value.charCodeAt(0); + // eslint-disable-next-line max-depth + if (code >= 0xd800 && code <= 0xdbff) value += arrayLike[++i]; + } + value = mapFn ? call.call(mapFn, thisArg, value, j) : value; + if (Context) { + desc.value = value; + defineProperty(arr, j, desc); + } else { + arr[j] = value; + } + ++j; + } + length = j; + } + } + if (length === undefined) { + // Source: array or array-like + length = toPosInt(arrayLike.length); + if (Context) arr = new Context(length); + for (i = 0; i < length; ++i) { + value = mapFn ? call.call(mapFn, thisArg, arrayLike[i], i) : arrayLike[i]; + if (Context) { + desc.value = value; + defineProperty(arr, i, desc); + } else { + arr[i] = value; + } + } + } + if (Context) { + desc.value = null; + arr.length = length; + } + return arr; +}; + +},{"../../function/is-arguments":24,"../../function/is-function":25,"../../number/to-pos-integer":34,"../../object/is-value":44,"../../object/valid-callable":54,"../../object/valid-value":55,"../../string/is-string":59,"es6-symbol":73}],24:[function(require,module,exports){ +"use strict"; + +var objToString = Object.prototype.toString + , id = objToString.call( + (function () { + return arguments; + })() +); + +module.exports = function (value) { + return objToString.call(value) === id; +}; + +},{}],25:[function(require,module,exports){ +"use strict"; + +var objToString = Object.prototype.toString, id = objToString.call(require("./noop")); + +module.exports = function (value) { + return typeof value === "function" && objToString.call(value) === id; +}; + +},{"./noop":26}],26:[function(require,module,exports){ +"use strict"; + +// eslint-disable-next-line no-empty-function +module.exports = function () {}; + +},{}],27:[function(require,module,exports){ +"use strict"; + +module.exports = require("./is-implemented")() + ? Math.sign + : require("./shim"); + +},{"./is-implemented":28,"./shim":29}],28:[function(require,module,exports){ +"use strict"; + +module.exports = function () { + var sign = Math.sign; + if (typeof sign !== "function") return false; + return (sign(10) === 1) && (sign(-20) === -1); +}; + +},{}],29:[function(require,module,exports){ +"use strict"; + +module.exports = function (value) { + value = Number(value); + if (isNaN(value) || (value === 0)) return value; + return value > 0 ? 1 : -1; +}; + +},{}],30:[function(require,module,exports){ +"use strict"; + +module.exports = require("./is-implemented")() + ? Number.isNaN + : require("./shim"); + +},{"./is-implemented":31,"./shim":32}],31:[function(require,module,exports){ +"use strict"; + +module.exports = function () { + var numberIsNaN = Number.isNaN; + if (typeof numberIsNaN !== "function") return false; + return !numberIsNaN({}) && numberIsNaN(NaN) && !numberIsNaN(34); +}; + +},{}],32:[function(require,module,exports){ +"use strict"; + +module.exports = function (value) { + // eslint-disable-next-line no-self-compare + return value !== value; +}; + +},{}],33:[function(require,module,exports){ +"use strict"; + +var sign = require("../math/sign") + + , abs = Math.abs, floor = Math.floor; + +module.exports = function (value) { + if (isNaN(value)) return 0; + value = Number(value); + if ((value === 0) || !isFinite(value)) return value; + return sign(value) * floor(abs(value)); +}; + +},{"../math/sign":27}],34:[function(require,module,exports){ +"use strict"; + +var toInteger = require("./to-integer") + + , max = Math.max; + +module.exports = function (value) { + return max(0, toInteger(value)); +}; + +},{"./to-integer":33}],35:[function(require,module,exports){ +// Internal method, used by iteration functions. +// Calls a function for each key-value pair found in object +// Optionally takes compareFn to iterate object in specific order + +"use strict"; + +var callable = require("./valid-callable") + , value = require("./valid-value") + , bind = Function.prototype.bind + , call = Function.prototype.call + , keys = Object.keys + , objPropertyIsEnumerable = Object.prototype.propertyIsEnumerable; + +module.exports = function (method, defVal) { + return function (obj, cb /*, thisArg, compareFn*/) { + var list, thisArg = arguments[2], compareFn = arguments[3]; + obj = Object(value(obj)); + callable(cb); + + list = keys(obj); + if (compareFn) { + list.sort(typeof compareFn === "function" ? bind.call(compareFn, obj) : undefined); + } + if (typeof method !== "function") method = list[method]; + return call.call(method, list, function (key, index) { + if (!objPropertyIsEnumerable.call(obj, key)) return defVal; + return call.call(cb, thisArg, obj[key], key, obj, index); + }); + }; +}; + +},{"./valid-callable":54,"./valid-value":55}],36:[function(require,module,exports){ +"use strict"; + +module.exports = require("./is-implemented")() + ? Object.assign + : require("./shim"); + +},{"./is-implemented":37,"./shim":38}],37:[function(require,module,exports){ +"use strict"; + +module.exports = function () { + var assign = Object.assign, obj; + if (typeof assign !== "function") return false; + obj = { foo: "raz" }; + assign(obj, { bar: "dwa" }, { trzy: "trzy" }); + return (obj.foo + obj.bar + obj.trzy) === "razdwatrzy"; +}; + +},{}],38:[function(require,module,exports){ +"use strict"; + +var keys = require("../keys") + , value = require("../valid-value") + , max = Math.max; + +module.exports = function (dest, src /*, …srcn*/) { + var error, i, length = max(arguments.length, 2), assign; + dest = Object(value(dest)); + assign = function (key) { + try { + dest[key] = src[key]; + } catch (e) { + if (!error) error = e; + } + }; + for (i = 1; i < length; ++i) { + src = arguments[i]; + keys(src).forEach(assign); + } + if (error !== undefined) throw error; + return dest; +}; + +},{"../keys":45,"../valid-value":55}],39:[function(require,module,exports){ +"use strict"; + +var aFrom = require("../array/from") + , assign = require("./assign") + , value = require("./valid-value"); + +module.exports = function (obj/*, propertyNames, options*/) { + var copy = Object(value(obj)), propertyNames = arguments[1], options = Object(arguments[2]); + if (copy !== obj && !propertyNames) return copy; + var result = {}; + if (propertyNames) { + aFrom(propertyNames, function (propertyName) { + if (options.ensure || propertyName in obj) result[propertyName] = obj[propertyName]; + }); + } else { + assign(result, obj); + } + return result; +}; + +},{"../array/from":21,"./assign":36,"./valid-value":55}],40:[function(require,module,exports){ +// Workaround for http://code.google.com/p/v8/issues/detail?id=2804 + +"use strict"; + +var create = Object.create, shim; + +if (!require("./set-prototype-of/is-implemented")()) { + shim = require("./set-prototype-of/shim"); +} + +module.exports = (function () { + var nullObject, polyProps, desc; + if (!shim) return create; + if (shim.level !== 1) return create; + + nullObject = {}; + polyProps = {}; + desc = { + configurable: false, + enumerable: false, + writable: true, + value: undefined + }; + Object.getOwnPropertyNames(Object.prototype).forEach(function (name) { + if (name === "__proto__") { + polyProps[name] = { + configurable: true, + enumerable: false, + writable: true, + value: undefined + }; + return; + } + polyProps[name] = desc; + }); + Object.defineProperties(nullObject, polyProps); + + Object.defineProperty(shim, "nullPolyfill", { + configurable: false, + enumerable: false, + writable: false, + value: nullObject + }); + + return function (prototype, props) { + return create(prototype === null ? nullObject : prototype, props); + }; +}()); + +},{"./set-prototype-of/is-implemented":52,"./set-prototype-of/shim":53}],41:[function(require,module,exports){ +"use strict"; + +module.exports = require("./_iterate")("forEach"); + +},{"./_iterate":35}],42:[function(require,module,exports){ +// Deprecated + +"use strict"; + +module.exports = function (obj) { + return typeof obj === "function"; +}; + +},{}],43:[function(require,module,exports){ +"use strict"; + +var isValue = require("./is-value"); + +var map = { function: true, object: true }; + +module.exports = function (value) { + return (isValue(value) && map[typeof value]) || false; +}; + +},{"./is-value":44}],44:[function(require,module,exports){ +"use strict"; + +var _undefined = require("../function/noop")(); // Support ES3 engines + +module.exports = function (val) { + return (val !== _undefined) && (val !== null); +}; + +},{"../function/noop":26}],45:[function(require,module,exports){ +"use strict"; + +module.exports = require("./is-implemented")() ? Object.keys : require("./shim"); + +},{"./is-implemented":46,"./shim":47}],46:[function(require,module,exports){ +"use strict"; + +module.exports = function () { + try { + Object.keys("primitive"); + return true; + } catch (e) { + return false; + } +}; + +},{}],47:[function(require,module,exports){ +"use strict"; + +var isValue = require("../is-value"); + +var keys = Object.keys; + +module.exports = function (object) { return keys(isValue(object) ? Object(object) : object); }; + +},{"../is-value":44}],48:[function(require,module,exports){ +"use strict"; + +var callable = require("./valid-callable") + , forEach = require("./for-each") + , call = Function.prototype.call; + +module.exports = function (obj, cb /*, thisArg*/) { + var result = {}, thisArg = arguments[2]; + callable(cb); + forEach(obj, function (value, key, targetObj, index) { + result[key] = call.call(cb, thisArg, value, key, targetObj, index); + }); + return result; +}; + +},{"./for-each":41,"./valid-callable":54}],49:[function(require,module,exports){ +"use strict"; + +var isValue = require("./is-value"); + +var forEach = Array.prototype.forEach, create = Object.create; + +var process = function (src, obj) { + var key; + for (key in src) obj[key] = src[key]; +}; + +// eslint-disable-next-line no-unused-vars +module.exports = function (opts1 /*, …options*/) { + var result = create(null); + forEach.call(arguments, function (options) { + if (!isValue(options)) return; + process(Object(options), result); + }); + return result; +}; + +},{"./is-value":44}],50:[function(require,module,exports){ +"use strict"; + +var forEach = Array.prototype.forEach, create = Object.create; + +// eslint-disable-next-line no-unused-vars +module.exports = function (arg /*, …args*/) { + var set = create(null); + forEach.call(arguments, function (name) { + set[name] = true; + }); + return set; +}; + +},{}],51:[function(require,module,exports){ +"use strict"; + +module.exports = require("./is-implemented")() + ? Object.setPrototypeOf + : require("./shim"); + +},{"./is-implemented":52,"./shim":53}],52:[function(require,module,exports){ +"use strict"; + +var create = Object.create, getPrototypeOf = Object.getPrototypeOf, plainObject = {}; + +module.exports = function (/* CustomCreate*/) { + var setPrototypeOf = Object.setPrototypeOf, customCreate = arguments[0] || create; + if (typeof setPrototypeOf !== "function") return false; + return getPrototypeOf(setPrototypeOf(customCreate(null), plainObject)) === plainObject; +}; + +},{}],53:[function(require,module,exports){ +/* eslint no-proto: "off" */ + +// Big thanks to @WebReflection for sorting this out +// https://gist.github.com/WebReflection/5593554 + +"use strict"; + +var isObject = require("../is-object") + , value = require("../valid-value") + , objIsPrototypeOf = Object.prototype.isPrototypeOf + , defineProperty = Object.defineProperty + , nullDesc = { + configurable: true, + enumerable: false, + writable: true, + value: undefined +} + , validate; + +validate = function (obj, prototype) { + value(obj); + if (prototype === null || isObject(prototype)) return obj; + throw new TypeError("Prototype must be null or an object"); +}; + +module.exports = (function (status) { + var fn, set; + if (!status) return null; + if (status.level === 2) { + if (status.set) { + set = status.set; + fn = function (obj, prototype) { + set.call(validate(obj, prototype), prototype); + return obj; + }; + } else { + fn = function (obj, prototype) { + validate(obj, prototype).__proto__ = prototype; + return obj; + }; + } + } else { + fn = function self(obj, prototype) { + var isNullBase; + validate(obj, prototype); + isNullBase = objIsPrototypeOf.call(self.nullPolyfill, obj); + if (isNullBase) delete self.nullPolyfill.__proto__; + if (prototype === null) prototype = self.nullPolyfill; + obj.__proto__ = prototype; + if (isNullBase) defineProperty(self.nullPolyfill, "__proto__", nullDesc); + return obj; + }; + } + return Object.defineProperty(fn, "level", { + configurable: false, + enumerable: false, + writable: false, + value: status.level + }); +}( + (function () { + var tmpObj1 = Object.create(null) + , tmpObj2 = {} + , set + , desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); + + if (desc) { + try { + set = desc.set; // Opera crashes at this point + set.call(tmpObj1, tmpObj2); + } catch (ignore) {} + if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { set: set, level: 2 }; + } + + tmpObj1.__proto__ = tmpObj2; + if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 2 }; + + tmpObj1 = {}; + tmpObj1.__proto__ = tmpObj2; + if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 1 }; + + return false; + })() +)); + +require("../create"); + +},{"../create":40,"../is-object":43,"../valid-value":55}],54:[function(require,module,exports){ +"use strict"; + +module.exports = function (fn) { + if (typeof fn !== "function") throw new TypeError(fn + " is not a function"); + return fn; +}; + +},{}],55:[function(require,module,exports){ +"use strict"; + +var isValue = require("./is-value"); + +module.exports = function (value) { + if (!isValue(value)) throw new TypeError("Cannot use null or undefined"); + return value; +}; + +},{"./is-value":44}],56:[function(require,module,exports){ +"use strict"; + +module.exports = require("./is-implemented")() + ? String.prototype.contains + : require("./shim"); + +},{"./is-implemented":57,"./shim":58}],57:[function(require,module,exports){ +"use strict"; + +var str = "razdwatrzy"; + +module.exports = function () { + if (typeof str.contains !== "function") return false; + return (str.contains("dwa") === true) && (str.contains("foo") === false); +}; + +},{}],58:[function(require,module,exports){ +"use strict"; + +var indexOf = String.prototype.indexOf; + +module.exports = function (searchString/*, position*/) { + return indexOf.call(this, searchString, arguments[1]) > -1; +}; + +},{}],59:[function(require,module,exports){ +"use strict"; + +var objToString = Object.prototype.toString, id = objToString.call(""); + +module.exports = function (value) { + return ( + typeof value === "string" || + (value && + typeof value === "object" && + (value instanceof String || objToString.call(value) === id)) || + false + ); +}; + +},{}],60:[function(require,module,exports){ +"use strict"; + +var setPrototypeOf = require("es5-ext/object/set-prototype-of") + , contains = require("es5-ext/string/#/contains") + , d = require("d") + , Symbol = require("es6-symbol") + , Iterator = require("./"); + +var defineProperty = Object.defineProperty, ArrayIterator; + +ArrayIterator = module.exports = function (arr, kind) { + if (!(this instanceof ArrayIterator)) throw new TypeError("Constructor requires 'new'"); + Iterator.call(this, arr); + if (!kind) kind = "value"; + else if (contains.call(kind, "key+value")) kind = "key+value"; + else if (contains.call(kind, "key")) kind = "key"; + else kind = "value"; + defineProperty(this, "__kind__", d("", kind)); +}; +if (setPrototypeOf) setPrototypeOf(ArrayIterator, Iterator); + +// Internal %ArrayIteratorPrototype% doesn't expose its constructor +delete ArrayIterator.prototype.constructor; + +ArrayIterator.prototype = Object.create(Iterator.prototype, { + _resolve: d(function (i) { + if (this.__kind__ === "value") return this.__list__[i]; + if (this.__kind__ === "key+value") return [i, this.__list__[i]]; + return i; + }) +}); +defineProperty(ArrayIterator.prototype, Symbol.toStringTag, d("c", "Array Iterator")); + +},{"./":63,"d":16,"es5-ext/object/set-prototype-of":51,"es5-ext/string/#/contains":56,"es6-symbol":73}],61:[function(require,module,exports){ +"use strict"; + +var isArguments = require("es5-ext/function/is-arguments") + , callable = require("es5-ext/object/valid-callable") + , isString = require("es5-ext/string/is-string") + , get = require("./get"); + +var isArray = Array.isArray, call = Function.prototype.call, some = Array.prototype.some; + +module.exports = function (iterable, cb /*, thisArg*/) { + var mode, thisArg = arguments[2], result, doBreak, broken, i, length, char, code; + if (isArray(iterable) || isArguments(iterable)) mode = "array"; + else if (isString(iterable)) mode = "string"; + else iterable = get(iterable); + + callable(cb); + doBreak = function () { + broken = true; + }; + if (mode === "array") { + some.call(iterable, function (value) { + call.call(cb, thisArg, value, doBreak); + return broken; + }); + return; + } + if (mode === "string") { + length = iterable.length; + for (i = 0; i < length; ++i) { + char = iterable[i]; + if (i + 1 < length) { + code = char.charCodeAt(0); + if (code >= 0xd800 && code <= 0xdbff) char += iterable[++i]; + } + call.call(cb, thisArg, char, doBreak); + if (broken) break; + } + return; + } + result = iterable.next(); + + while (!result.done) { + call.call(cb, thisArg, result.value, doBreak); + if (broken) return; + result = iterable.next(); + } +}; + +},{"./get":62,"es5-ext/function/is-arguments":24,"es5-ext/object/valid-callable":54,"es5-ext/string/is-string":59}],62:[function(require,module,exports){ +"use strict"; + +var isArguments = require("es5-ext/function/is-arguments") + , isString = require("es5-ext/string/is-string") + , ArrayIterator = require("./array") + , StringIterator = require("./string") + , iterable = require("./valid-iterable") + , iteratorSymbol = require("es6-symbol").iterator; + +module.exports = function (obj) { + if (typeof iterable(obj)[iteratorSymbol] === "function") return obj[iteratorSymbol](); + if (isArguments(obj)) return new ArrayIterator(obj); + if (isString(obj)) return new StringIterator(obj); + return new ArrayIterator(obj); +}; + +},{"./array":60,"./string":65,"./valid-iterable":66,"es5-ext/function/is-arguments":24,"es5-ext/string/is-string":59,"es6-symbol":73}],63:[function(require,module,exports){ +"use strict"; + +var clear = require("es5-ext/array/#/clear") + , assign = require("es5-ext/object/assign") + , callable = require("es5-ext/object/valid-callable") + , value = require("es5-ext/object/valid-value") + , d = require("d") + , autoBind = require("d/auto-bind") + , Symbol = require("es6-symbol"); + +var defineProperty = Object.defineProperty, defineProperties = Object.defineProperties, Iterator; + +module.exports = Iterator = function (list, context) { + if (!(this instanceof Iterator)) throw new TypeError("Constructor requires 'new'"); + defineProperties(this, { + __list__: d("w", value(list)), + __context__: d("w", context), + __nextIndex__: d("w", 0) + }); + if (!context) return; + callable(context.on); + context.on("_add", this._onAdd); + context.on("_delete", this._onDelete); + context.on("_clear", this._onClear); +}; + +// Internal %IteratorPrototype% doesn't expose its constructor +delete Iterator.prototype.constructor; + +defineProperties( + Iterator.prototype, + assign( + { + _next: d(function () { + var i; + if (!this.__list__) return undefined; + if (this.__redo__) { + i = this.__redo__.shift(); + if (i !== undefined) return i; + } + if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++; + this._unBind(); + return undefined; + }), + next: d(function () { + return this._createResult(this._next()); + }), + _createResult: d(function (i) { + if (i === undefined) return { done: true, value: undefined }; + return { done: false, value: this._resolve(i) }; + }), + _resolve: d(function (i) { + return this.__list__[i]; + }), + _unBind: d(function () { + this.__list__ = null; + delete this.__redo__; + if (!this.__context__) return; + this.__context__.off("_add", this._onAdd); + this.__context__.off("_delete", this._onDelete); + this.__context__.off("_clear", this._onClear); + this.__context__ = null; + }), + toString: d(function () { + return "[object " + (this[Symbol.toStringTag] || "Object") + "]"; + }) + }, + autoBind({ + _onAdd: d(function (index) { + if (index >= this.__nextIndex__) return; + ++this.__nextIndex__; + if (!this.__redo__) { + defineProperty(this, "__redo__", d("c", [index])); + return; + } + this.__redo__.forEach(function (redo, i) { + if (redo >= index) this.__redo__[i] = ++redo; + }, this); + this.__redo__.push(index); + }), + _onDelete: d(function (index) { + var i; + if (index >= this.__nextIndex__) return; + --this.__nextIndex__; + if (!this.__redo__) return; + i = this.__redo__.indexOf(index); + if (i !== -1) this.__redo__.splice(i, 1); + this.__redo__.forEach(function (redo, j) { + if (redo > index) this.__redo__[j] = --redo; + }, this); + }), + _onClear: d(function () { + if (this.__redo__) clear.call(this.__redo__); + this.__nextIndex__ = 0; + }) + }) + ) +); + +defineProperty( + Iterator.prototype, + Symbol.iterator, + d(function () { + return this; + }) +); + +},{"d":16,"d/auto-bind":15,"es5-ext/array/#/clear":19,"es5-ext/object/assign":36,"es5-ext/object/valid-callable":54,"es5-ext/object/valid-value":55,"es6-symbol":73}],64:[function(require,module,exports){ +"use strict"; + +var isArguments = require("es5-ext/function/is-arguments") + , isValue = require("es5-ext/object/is-value") + , isString = require("es5-ext/string/is-string"); + +var iteratorSymbol = require("es6-symbol").iterator + , isArray = Array.isArray; + +module.exports = function (value) { + if (!isValue(value)) return false; + if (isArray(value)) return true; + if (isString(value)) return true; + if (isArguments(value)) return true; + return typeof value[iteratorSymbol] === "function"; +}; + +},{"es5-ext/function/is-arguments":24,"es5-ext/object/is-value":44,"es5-ext/string/is-string":59,"es6-symbol":73}],65:[function(require,module,exports){ +// Thanks @mathiasbynens +// http://mathiasbynens.be/notes/javascript-unicode#iterating-over-symbols + +"use strict"; + +var setPrototypeOf = require("es5-ext/object/set-prototype-of") + , d = require("d") + , Symbol = require("es6-symbol") + , Iterator = require("./"); + +var defineProperty = Object.defineProperty, StringIterator; + +StringIterator = module.exports = function (str) { + if (!(this instanceof StringIterator)) throw new TypeError("Constructor requires 'new'"); + str = String(str); + Iterator.call(this, str); + defineProperty(this, "__length__", d("", str.length)); +}; +if (setPrototypeOf) setPrototypeOf(StringIterator, Iterator); + +// Internal %ArrayIteratorPrototype% doesn't expose its constructor +delete StringIterator.prototype.constructor; + +StringIterator.prototype = Object.create(Iterator.prototype, { + _next: d(function () { + if (!this.__list__) return undefined; + if (this.__nextIndex__ < this.__length__) return this.__nextIndex__++; + this._unBind(); + return undefined; + }), + _resolve: d(function (i) { + var char = this.__list__[i], code; + if (this.__nextIndex__ === this.__length__) return char; + code = char.charCodeAt(0); + if (code >= 0xd800 && code <= 0xdbff) return char + this.__list__[this.__nextIndex__++]; + return char; + }) +}); +defineProperty(StringIterator.prototype, Symbol.toStringTag, d("c", "String Iterator")); + +},{"./":63,"d":16,"es5-ext/object/set-prototype-of":51,"es6-symbol":73}],66:[function(require,module,exports){ +"use strict"; + +var isIterable = require("./is-iterable"); + +module.exports = function (value) { + if (!isIterable(value)) throw new TypeError(value + " is not iterable"); + return value; +}; + +},{"./is-iterable":64}],67:[function(require,module,exports){ +'use strict'; + +module.exports = require('./is-implemented')() ? Map : require('./polyfill'); + +},{"./is-implemented":68,"./polyfill":72}],68:[function(require,module,exports){ +'use strict'; + +module.exports = function () { + var map, iterator, result; + if (typeof Map !== 'function') return false; + try { + // WebKit doesn't support arguments and crashes + map = new Map([['raz', 'one'], ['dwa', 'two'], ['trzy', 'three']]); + } catch (e) { + return false; + } + if (String(map) !== '[object Map]') return false; + if (map.size !== 3) return false; + if (typeof map.clear !== 'function') return false; + if (typeof map.delete !== 'function') return false; + if (typeof map.entries !== 'function') return false; + if (typeof map.forEach !== 'function') return false; + if (typeof map.get !== 'function') return false; + if (typeof map.has !== 'function') return false; + if (typeof map.keys !== 'function') return false; + if (typeof map.set !== 'function') return false; + if (typeof map.values !== 'function') return false; + + iterator = map.entries(); + result = iterator.next(); + if (result.done !== false) return false; + if (!result.value) return false; + if (result.value[0] !== 'raz') return false; + if (result.value[1] !== 'one') return false; + + return true; +}; + +},{}],69:[function(require,module,exports){ +// Exports true if environment provides native `Map` implementation, +// whatever that is. + +'use strict'; + +module.exports = (function () { + if (typeof Map === 'undefined') return false; + return (Object.prototype.toString.call(new Map()) === '[object Map]'); +}()); + +},{}],70:[function(require,module,exports){ +'use strict'; + +module.exports = require('es5-ext/object/primitive-set')('key', + 'value', 'key+value'); + +},{"es5-ext/object/primitive-set":50}],71:[function(require,module,exports){ +'use strict'; + +var setPrototypeOf = require('es5-ext/object/set-prototype-of') + , d = require('d') + , Iterator = require('es6-iterator') + , toStringTagSymbol = require('es6-symbol').toStringTag + , kinds = require('./iterator-kinds') + + , defineProperties = Object.defineProperties + , unBind = Iterator.prototype._unBind + , MapIterator; + +MapIterator = module.exports = function (map, kind) { + if (!(this instanceof MapIterator)) return new MapIterator(map, kind); + Iterator.call(this, map.__mapKeysData__, map); + if (!kind || !kinds[kind]) kind = 'key+value'; + defineProperties(this, { + __kind__: d('', kind), + __values__: d('w', map.__mapValuesData__) + }); +}; +if (setPrototypeOf) setPrototypeOf(MapIterator, Iterator); + +MapIterator.prototype = Object.create(Iterator.prototype, { + constructor: d(MapIterator), + _resolve: d(function (i) { + if (this.__kind__ === 'value') return this.__values__[i]; + if (this.__kind__ === 'key') return this.__list__[i]; + return [this.__list__[i], this.__values__[i]]; + }), + _unBind: d(function () { + this.__values__ = null; + unBind.call(this); + }), + toString: d(function () { return '[object Map Iterator]'; }) +}); +Object.defineProperty(MapIterator.prototype, toStringTagSymbol, + d('c', 'Map Iterator')); + +},{"./iterator-kinds":70,"d":16,"es5-ext/object/set-prototype-of":51,"es6-iterator":63,"es6-symbol":73}],72:[function(require,module,exports){ +'use strict'; + +var clear = require('es5-ext/array/#/clear') + , eIndexOf = require('es5-ext/array/#/e-index-of') + , setPrototypeOf = require('es5-ext/object/set-prototype-of') + , callable = require('es5-ext/object/valid-callable') + , validValue = require('es5-ext/object/valid-value') + , d = require('d') + , ee = require('event-emitter') + , Symbol = require('es6-symbol') + , iterator = require('es6-iterator/valid-iterable') + , forOf = require('es6-iterator/for-of') + , Iterator = require('./lib/iterator') + , isNative = require('./is-native-implemented') + + , call = Function.prototype.call + , defineProperties = Object.defineProperties, getPrototypeOf = Object.getPrototypeOf + , MapPoly; + +module.exports = MapPoly = function (/*iterable*/) { + var iterable = arguments[0], keys, values, self; + if (!(this instanceof MapPoly)) throw new TypeError('Constructor requires \'new\''); + if (isNative && setPrototypeOf && (Map !== MapPoly)) { + self = setPrototypeOf(new Map(), getPrototypeOf(this)); + } else { + self = this; + } + if (iterable != null) iterator(iterable); + defineProperties(self, { + __mapKeysData__: d('c', keys = []), + __mapValuesData__: d('c', values = []) + }); + if (!iterable) return self; + forOf(iterable, function (value) { + var key = validValue(value)[0]; + value = value[1]; + if (eIndexOf.call(keys, key) !== -1) return; + keys.push(key); + values.push(value); + }, self); + return self; +}; + +if (isNative) { + if (setPrototypeOf) setPrototypeOf(MapPoly, Map); + MapPoly.prototype = Object.create(Map.prototype, { + constructor: d(MapPoly) + }); +} + +ee(defineProperties(MapPoly.prototype, { + clear: d(function () { + if (!this.__mapKeysData__.length) return; + clear.call(this.__mapKeysData__); + clear.call(this.__mapValuesData__); + this.emit('_clear'); + }), + delete: d(function (key) { + var index = eIndexOf.call(this.__mapKeysData__, key); + if (index === -1) return false; + this.__mapKeysData__.splice(index, 1); + this.__mapValuesData__.splice(index, 1); + this.emit('_delete', index, key); + return true; + }), + entries: d(function () { return new Iterator(this, 'key+value'); }), + forEach: d(function (cb/*, thisArg*/) { + var thisArg = arguments[1], iterator, result; + callable(cb); + iterator = this.entries(); + result = iterator._next(); + while (result !== undefined) { + call.call(cb, thisArg, this.__mapValuesData__[result], + this.__mapKeysData__[result], this); + result = iterator._next(); + } + }), + get: d(function (key) { + var index = eIndexOf.call(this.__mapKeysData__, key); + if (index === -1) return; + return this.__mapValuesData__[index]; + }), + has: d(function (key) { + return (eIndexOf.call(this.__mapKeysData__, key) !== -1); + }), + keys: d(function () { return new Iterator(this, 'key'); }), + set: d(function (key, value) { + var index = eIndexOf.call(this.__mapKeysData__, key), emit; + if (index === -1) { + index = this.__mapKeysData__.push(key) - 1; + emit = true; + } + this.__mapValuesData__[index] = value; + if (emit) this.emit('_add', index, key); + return this; + }), + size: d.gs(function () { return this.__mapKeysData__.length; }), + values: d(function () { return new Iterator(this, 'value'); }), + toString: d(function () { return '[object Map]'; }) +})); +Object.defineProperty(MapPoly.prototype, Symbol.iterator, d(function () { + return this.entries(); +})); +Object.defineProperty(MapPoly.prototype, Symbol.toStringTag, d('c', 'Map')); + +},{"./is-native-implemented":69,"./lib/iterator":71,"d":16,"es5-ext/array/#/clear":19,"es5-ext/array/#/e-index-of":20,"es5-ext/object/set-prototype-of":51,"es5-ext/object/valid-callable":54,"es5-ext/object/valid-value":55,"es6-iterator/for-of":61,"es6-iterator/valid-iterable":66,"es6-symbol":73,"event-emitter":78}],73:[function(require,module,exports){ +'use strict'; + +module.exports = require('./is-implemented')() ? Symbol : require('./polyfill'); + +},{"./is-implemented":74,"./polyfill":76}],74:[function(require,module,exports){ +'use strict'; + +var validTypes = { object: true, symbol: true }; + +module.exports = function () { + var symbol; + if (typeof Symbol !== 'function') return false; + symbol = Symbol('test symbol'); + try { String(symbol); } catch (e) { return false; } + + // Return 'true' also for polyfills + if (!validTypes[typeof Symbol.iterator]) return false; + if (!validTypes[typeof Symbol.toPrimitive]) return false; + if (!validTypes[typeof Symbol.toStringTag]) return false; + + return true; +}; + +},{}],75:[function(require,module,exports){ +'use strict'; + +module.exports = function (x) { + if (!x) return false; + if (typeof x === 'symbol') return true; + if (!x.constructor) return false; + if (x.constructor.name !== 'Symbol') return false; + return (x[x.constructor.toStringTag] === 'Symbol'); +}; + +},{}],76:[function(require,module,exports){ +// ES2015 Symbol polyfill for environments that do not (or partially) support it + +'use strict'; + +var d = require('d') + , validateSymbol = require('./validate-symbol') + + , create = Object.create, defineProperties = Object.defineProperties + , defineProperty = Object.defineProperty, objPrototype = Object.prototype + , NativeSymbol, SymbolPolyfill, HiddenSymbol, globalSymbols = create(null) + , isNativeSafe; + +if (typeof Symbol === 'function') { + NativeSymbol = Symbol; + try { + String(NativeSymbol()); + isNativeSafe = true; + } catch (ignore) {} +} + +var generateName = (function () { + var created = create(null); + return function (desc) { + var postfix = 0, name, ie11BugWorkaround; + while (created[desc + (postfix || '')]) ++postfix; + desc += (postfix || ''); + created[desc] = true; + name = '@@' + desc; + defineProperty(objPrototype, name, d.gs(null, function (value) { + // For IE11 issue see: + // https://connect.microsoft.com/IE/feedbackdetail/view/1928508/ + // ie11-broken-getters-on-dom-objects + // https://github.com/medikoo/es6-symbol/issues/12 + if (ie11BugWorkaround) return; + ie11BugWorkaround = true; + defineProperty(this, name, d(value)); + ie11BugWorkaround = false; + })); + return name; + }; +}()); + +// Internal constructor (not one exposed) for creating Symbol instances. +// This one is used to ensure that `someSymbol instanceof Symbol` always return false +HiddenSymbol = function Symbol(description) { + if (this instanceof HiddenSymbol) throw new TypeError('Symbol is not a constructor'); + return SymbolPolyfill(description); +}; + +// Exposed `Symbol` constructor +// (returns instances of HiddenSymbol) +module.exports = SymbolPolyfill = function Symbol(description) { + var symbol; + if (this instanceof Symbol) throw new TypeError('Symbol is not a constructor'); + if (isNativeSafe) return NativeSymbol(description); + symbol = create(HiddenSymbol.prototype); + description = (description === undefined ? '' : String(description)); + return defineProperties(symbol, { + __description__: d('', description), + __name__: d('', generateName(description)) + }); +}; +defineProperties(SymbolPolyfill, { + for: d(function (key) { + if (globalSymbols[key]) return globalSymbols[key]; + return (globalSymbols[key] = SymbolPolyfill(String(key))); + }), + keyFor: d(function (s) { + var key; + validateSymbol(s); + for (key in globalSymbols) if (globalSymbols[key] === s) return key; + }), + + // To ensure proper interoperability with other native functions (e.g. Array.from) + // fallback to eventual native implementation of given symbol + hasInstance: d('', (NativeSymbol && NativeSymbol.hasInstance) || SymbolPolyfill('hasInstance')), + isConcatSpreadable: d('', (NativeSymbol && NativeSymbol.isConcatSpreadable) || + SymbolPolyfill('isConcatSpreadable')), + iterator: d('', (NativeSymbol && NativeSymbol.iterator) || SymbolPolyfill('iterator')), + match: d('', (NativeSymbol && NativeSymbol.match) || SymbolPolyfill('match')), + replace: d('', (NativeSymbol && NativeSymbol.replace) || SymbolPolyfill('replace')), + search: d('', (NativeSymbol && NativeSymbol.search) || SymbolPolyfill('search')), + species: d('', (NativeSymbol && NativeSymbol.species) || SymbolPolyfill('species')), + split: d('', (NativeSymbol && NativeSymbol.split) || SymbolPolyfill('split')), + toPrimitive: d('', (NativeSymbol && NativeSymbol.toPrimitive) || SymbolPolyfill('toPrimitive')), + toStringTag: d('', (NativeSymbol && NativeSymbol.toStringTag) || SymbolPolyfill('toStringTag')), + unscopables: d('', (NativeSymbol && NativeSymbol.unscopables) || SymbolPolyfill('unscopables')) +}); + +// Internal tweaks for real symbol producer +defineProperties(HiddenSymbol.prototype, { + constructor: d(SymbolPolyfill), + toString: d('', function () { return this.__name__; }) +}); + +// Proper implementation of methods exposed on Symbol.prototype +// They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype +defineProperties(SymbolPolyfill.prototype, { + toString: d(function () { return 'Symbol (' + validateSymbol(this).__description__ + ')'; }), + valueOf: d(function () { return validateSymbol(this); }) +}); +defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive, d('', function () { + var symbol = validateSymbol(this); + if (typeof symbol === 'symbol') return symbol; + return symbol.toString(); +})); +defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d('c', 'Symbol')); + +// Proper implementaton of toPrimitive and toStringTag for returned symbol instances +defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toStringTag, + d('c', SymbolPolyfill.prototype[SymbolPolyfill.toStringTag])); + +// Note: It's important to define `toPrimitive` as last one, as some implementations +// implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols) +// And that may invoke error in definition flow: +// See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149 +defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toPrimitive, + d('c', SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive])); + +},{"./validate-symbol":77,"d":16}],77:[function(require,module,exports){ +'use strict'; + +var isSymbol = require('./is-symbol'); + +module.exports = function (value) { + if (!isSymbol(value)) throw new TypeError(value + " is not a symbol"); + return value; +}; + +},{"./is-symbol":75}],78:[function(require,module,exports){ +'use strict'; + +var d = require('d') + , callable = require('es5-ext/object/valid-callable') + + , apply = Function.prototype.apply, call = Function.prototype.call + , create = Object.create, defineProperty = Object.defineProperty + , defineProperties = Object.defineProperties + , hasOwnProperty = Object.prototype.hasOwnProperty + , descriptor = { configurable: true, enumerable: false, writable: true } + + , on, once, off, emit, methods, descriptors, base; + +on = function (type, listener) { + var data; + + callable(listener); + + if (!hasOwnProperty.call(this, '__ee__')) { + data = descriptor.value = create(null); + defineProperty(this, '__ee__', descriptor); + descriptor.value = null; + } else { + data = this.__ee__; + } + if (!data[type]) data[type] = listener; + else if (typeof data[type] === 'object') data[type].push(listener); + else data[type] = [data[type], listener]; + + return this; +}; + +once = function (type, listener) { + var once, self; + + callable(listener); + self = this; + on.call(this, type, once = function () { + off.call(self, type, once); + apply.call(listener, this, arguments); + }); + + once.__eeOnceListener__ = listener; + return this; +}; + +off = function (type, listener) { + var data, listeners, candidate, i; + + callable(listener); + + if (!hasOwnProperty.call(this, '__ee__')) return this; + data = this.__ee__; + if (!data[type]) return this; + listeners = data[type]; + + if (typeof listeners === 'object') { + for (i = 0; (candidate = listeners[i]); ++i) { + if ((candidate === listener) || + (candidate.__eeOnceListener__ === listener)) { + if (listeners.length === 2) data[type] = listeners[i ? 0 : 1]; + else listeners.splice(i, 1); + } + } + } else { + if ((listeners === listener) || + (listeners.__eeOnceListener__ === listener)) { + delete data[type]; + } + } + + return this; +}; + +emit = function (type) { + var i, l, listener, listeners, args; + + if (!hasOwnProperty.call(this, '__ee__')) return; + listeners = this.__ee__[type]; + if (!listeners) return; + + if (typeof listeners === 'object') { + l = arguments.length; + args = new Array(l - 1); + for (i = 1; i < l; ++i) args[i - 1] = arguments[i]; + + listeners = listeners.slice(); + for (i = 0; (listener = listeners[i]); ++i) { + apply.call(listener, this, args); + } + } else { + switch (arguments.length) { + case 1: + call.call(listeners, this); + break; + case 2: + call.call(listeners, this, arguments[1]); + break; + case 3: + call.call(listeners, this, arguments[1], arguments[2]); + break; + default: + l = arguments.length; + args = new Array(l - 1); + for (i = 1; i < l; ++i) { + args[i - 1] = arguments[i]; + } + apply.call(listeners, this, args); + } + } +}; + +methods = { + on: on, + once: once, + off: off, + emit: emit +}; + +descriptors = { + on: d(on), + once: d(once), + off: d(off), + emit: d(emit) +}; + +base = defineProperties({}, descriptors); + +module.exports = exports = function (o) { + return (o == null) ? create(base) : defineProperties(Object(o), descriptors); +}; +exports.methods = methods; + +},{"d":16,"es5-ext/object/valid-callable":54}],79:[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],80:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],81:[function(require,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],82:[function(require,module,exports){ +'use strict' + +var Buffer = require('safe-buffer').Buffer + +/* Protocol - protocol constants */ +var protocol = module.exports + +/* Command code => mnemonic */ +protocol.types = { + 0: 'reserved', + 1: 'connect', + 2: 'connack', + 3: 'publish', + 4: 'puback', + 5: 'pubrec', + 6: 'pubrel', + 7: 'pubcomp', + 8: 'subscribe', + 9: 'suback', + 10: 'unsubscribe', + 11: 'unsuback', + 12: 'pingreq', + 13: 'pingresp', + 14: 'disconnect', + 15: 'auth' +} + +/* Mnemonic => Command code */ +protocol.codes = {} +for (var k in protocol.types) { + var v = protocol.types[k] + protocol.codes[v] = k +} + +/* Header */ +protocol.CMD_SHIFT = 4 +protocol.CMD_MASK = 0xF0 +protocol.DUP_MASK = 0x08 +protocol.QOS_MASK = 0x03 +protocol.QOS_SHIFT = 1 +protocol.RETAIN_MASK = 0x01 + +/* Length */ +protocol.LENGTH_MASK = 0x7F +protocol.LENGTH_FIN_MASK = 0x80 + +/* Connack */ +protocol.SESSIONPRESENT_MASK = 0x01 +protocol.SESSIONPRESENT_HEADER = Buffer.from([protocol.SESSIONPRESENT_MASK]) +protocol.CONNACK_HEADER = Buffer.from([protocol.codes['connack'] << protocol.CMD_SHIFT]) + +/* Connect */ +protocol.USERNAME_MASK = 0x80 +protocol.PASSWORD_MASK = 0x40 +protocol.WILL_RETAIN_MASK = 0x20 +protocol.WILL_QOS_MASK = 0x18 +protocol.WILL_QOS_SHIFT = 3 +protocol.WILL_FLAG_MASK = 0x04 +protocol.CLEAN_SESSION_MASK = 0x02 +protocol.CONNECT_HEADER = Buffer.from([protocol.codes['connect'] << protocol.CMD_SHIFT]) + +/* Properties */ +protocol.properties = { + sessionExpiryInterval: 17, + willDelayInterval: 24, + receiveMaximum: 33, + maximumPacketSize: 39, + topicAliasMaximum: 34, + requestResponseInformation: 25, + requestProblemInformation: 23, + userProperties: 38, + authenticationMethod: 21, + authenticationData: 22, + payloadFormatIndicator: 1, + messageExpiryInterval: 2, + contentType: 3, + responseTopic: 8, + correlationData: 9, + maximumQoS: 36, + retainAvailable: 37, + assignedClientIdentifier: 18, + reasonString: 31, + wildcardSubscriptionAvailable: 40, + subscriptionIdentifiersAvailable: 41, + sharedSubscriptionAvailable: 42, + serverKeepAlive: 19, + responseInformation: 26, + serverReference: 28, + topicAlias: 35, + subscriptionIdentifier: 11 +} +protocol.propertiesCodes = {} +for (var prop in protocol.properties) { + var id = protocol.properties[prop] + protocol.propertiesCodes[id] = prop +} +protocol.propertiesTypes = { + sessionExpiryInterval: 'int32', + willDelayInterval: 'int32', + receiveMaximum: 'int16', + maximumPacketSize: 'int32', + topicAliasMaximum: 'int16', + requestResponseInformation: 'byte', + requestProblemInformation: 'byte', + userProperties: 'pair', + authenticationMethod: 'string', + authenticationData: 'binary', + payloadFormatIndicator: 'byte', + messageExpiryInterval: 'int32', + contentType: 'string', + responseTopic: 'string', + correlationData: 'binary', + maximumQoS: 'int8', + retainAvailable: 'byte', + assignedClientIdentifier: 'string', + reasonString: 'string', + wildcardSubscriptionAvailable: 'byte', + subscriptionIdentifiersAvailable: 'byte', + sharedSubscriptionAvailable: 'byte', + serverKeepAlive: 'int32', + responseInformation: 'string', + serverReference: 'string', + topicAlias: 'int16', + subscriptionIdentifier: 'var' +} + +function genHeader (type) { + return [0, 1, 2].map(function (qos) { + return [0, 1].map(function (dup) { + return [0, 1].map(function (retain) { + var buf = new Buffer(1) + buf.writeUInt8( + protocol.codes[type] << protocol.CMD_SHIFT | + (dup ? protocol.DUP_MASK : 0) | + qos << protocol.QOS_SHIFT | retain, 0, true) + return buf + }) + }) + }) +} + +/* Publish */ +protocol.PUBLISH_HEADER = genHeader('publish') + +/* Subscribe */ +protocol.SUBSCRIBE_HEADER = genHeader('subscribe') +protocol.SUBSCRIBE_OPTIONS_QOS_MASK = 0x03 +protocol.SUBSCRIBE_OPTIONS_NL_MASK = 0x01 +protocol.SUBSCRIBE_OPTIONS_NL_SHIFT = 2 +protocol.SUBSCRIBE_OPTIONS_RAP_MASK = 0x01 +protocol.SUBSCRIBE_OPTIONS_RAP_SHIFT = 3 +protocol.SUBSCRIBE_OPTIONS_RH_MASK = 0x03 +protocol.SUBSCRIBE_OPTIONS_RH_SHIFT = 4 +protocol.SUBSCRIBE_OPTIONS_RH = [0x00, 0x10, 0x20] +protocol.SUBSCRIBE_OPTIONS_NL = 0x04 +protocol.SUBSCRIBE_OPTIONS_RAP = 0x08 +protocol.SUBSCRIBE_OPTIONS_QOS = [0x00, 0x01, 0x02] + +/* Unsubscribe */ +protocol.UNSUBSCRIBE_HEADER = genHeader('unsubscribe') + +/* Confirmations */ +protocol.ACKS = { + unsuback: genHeader('unsuback'), + puback: genHeader('puback'), + pubcomp: genHeader('pubcomp'), + pubrel: genHeader('pubrel'), + pubrec: genHeader('pubrec') +} + +protocol.SUBACK_HEADER = Buffer.from([protocol.codes['suback'] << protocol.CMD_SHIFT]) + +/* Protocol versions */ +protocol.VERSION3 = Buffer.from([3]) +protocol.VERSION4 = Buffer.from([4]) +protocol.VERSION5 = Buffer.from([5]) + +/* QoS */ +protocol.QOS = [0, 1, 2].map(function (qos) { + return Buffer.from([qos]) +}) + +/* Empty packets */ +protocol.EMPTY = { + pingreq: Buffer.from([protocol.codes['pingreq'] << 4, 0]), + pingresp: Buffer.from([protocol.codes['pingresp'] << 4, 0]), + disconnect: Buffer.from([protocol.codes['disconnect'] << 4, 0]) +} + +},{"safe-buffer":110}],83:[function(require,module,exports){ +'use strict' + +var Buffer = require('safe-buffer').Buffer +var writeToStream = require('./writeToStream') +var EE = require('events').EventEmitter +var inherits = require('inherits') + +function generate (packet, opts) { + var stream = new Accumulator() + writeToStream(packet, stream, opts) + return stream.concat() +} + +function Accumulator () { + this._array = new Array(20) + this._i = 0 +} + +inherits(Accumulator, EE) + +Accumulator.prototype.write = function (chunk) { + this._array[this._i++] = chunk + return true +} + +Accumulator.prototype.concat = function () { + var length = 0 + var lengths = new Array(this._array.length) + var list = this._array + var pos = 0 + var i + var result + + for (i = 0; i < list.length && list[i] !== undefined; i++) { + if (typeof list[i] !== 'string') lengths[i] = list[i].length + else lengths[i] = Buffer.byteLength(list[i]) + + length += lengths[i] + } + + result = Buffer.allocUnsafe(length) + + for (i = 0; i < list.length && list[i] !== undefined; i++) { + if (typeof list[i] !== 'string') { + list[i].copy(result, pos) + pos += lengths[i] + } else { + result.write(list[i], pos) + pos += lengths[i] + } + } + + return result +} + +module.exports = generate + +},{"./writeToStream":89,"events":13,"inherits":80,"safe-buffer":110}],84:[function(require,module,exports){ +'use strict' + +exports.parser = require('./parser') +exports.generate = require('./generate') +exports.writeToStream = require('./writeToStream') + +},{"./generate":83,"./parser":88,"./writeToStream":89}],85:[function(require,module,exports){ +var DuplexStream = require('readable-stream/duplex') + , util = require('util') + , Buffer = require('safe-buffer').Buffer + + +function BufferList (callback) { + if (!(this instanceof BufferList)) + return new BufferList(callback) + + this._bufs = [] + this.length = 0 + + if (typeof callback == 'function') { + this._callback = callback + + var piper = function piper (err) { + if (this._callback) { + this._callback(err) + this._callback = null + } + }.bind(this) + + this.on('pipe', function onPipe (src) { + src.on('error', piper) + }) + this.on('unpipe', function onUnpipe (src) { + src.removeListener('error', piper) + }) + } else { + this.append(callback) + } + + DuplexStream.call(this) +} + + +util.inherits(BufferList, DuplexStream) + + +BufferList.prototype._offset = function _offset (offset) { + var tot = 0, i = 0, _t + if (offset === 0) return [ 0, 0 ] + for (; i < this._bufs.length; i++) { + _t = tot + this._bufs[i].length + if (offset < _t || i == this._bufs.length - 1) + return [ i, offset - tot ] + tot = _t + } +} + + +BufferList.prototype.append = function append (buf) { + var i = 0 + + if (Buffer.isBuffer(buf)) { + this._appendBuffer(buf); + } else if (Array.isArray(buf)) { + for (; i < buf.length; i++) + this.append(buf[i]) + } else if (buf instanceof BufferList) { + // unwrap argument into individual BufferLists + for (; i < buf._bufs.length; i++) + this.append(buf._bufs[i]) + } else if (buf != null) { + // coerce number arguments to strings, since Buffer(number) does + // uninitialized memory allocation + if (typeof buf == 'number') + buf = buf.toString() + + this._appendBuffer(Buffer.from(buf)); + } + + return this +} + + +BufferList.prototype._appendBuffer = function appendBuffer (buf) { + this._bufs.push(buf) + this.length += buf.length +} + + +BufferList.prototype._write = function _write (buf, encoding, callback) { + this._appendBuffer(buf) + + if (typeof callback == 'function') + callback() +} + + +BufferList.prototype._read = function _read (size) { + if (!this.length) + return this.push(null) + + size = Math.min(size, this.length) + this.push(this.slice(0, size)) + this.consume(size) +} + + +BufferList.prototype.end = function end (chunk) { + DuplexStream.prototype.end.call(this, chunk) + + if (this._callback) { + this._callback(null, this.slice()) + this._callback = null + } +} + + +BufferList.prototype.get = function get (index) { + return this.slice(index, index + 1)[0] +} + + +BufferList.prototype.slice = function slice (start, end) { + if (typeof start == 'number' && start < 0) + start += this.length + if (typeof end == 'number' && end < 0) + end += this.length + return this.copy(null, 0, start, end) +} + + +BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) { + if (typeof srcStart != 'number' || srcStart < 0) + srcStart = 0 + if (typeof srcEnd != 'number' || srcEnd > this.length) + srcEnd = this.length + if (srcStart >= this.length) + return dst || Buffer.alloc(0) + if (srcEnd <= 0) + return dst || Buffer.alloc(0) + + var copy = !!dst + , off = this._offset(srcStart) + , len = srcEnd - srcStart + , bytes = len + , bufoff = (copy && dstStart) || 0 + , start = off[1] + , l + , i + + // copy/slice everything + if (srcStart === 0 && srcEnd == this.length) { + if (!copy) { // slice, but full concat if multiple buffers + return this._bufs.length === 1 + ? this._bufs[0] + : Buffer.concat(this._bufs, this.length) + } + + // copy, need to copy individual buffers + for (i = 0; i < this._bufs.length; i++) { + this._bufs[i].copy(dst, bufoff) + bufoff += this._bufs[i].length + } + + return dst + } + + // easy, cheap case where it's a subset of one of the buffers + if (bytes <= this._bufs[off[0]].length - start) { + return copy + ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes) + : this._bufs[off[0]].slice(start, start + bytes) + } + + if (!copy) // a slice, we need something to copy in to + dst = Buffer.allocUnsafe(len) + + for (i = off[0]; i < this._bufs.length; i++) { + l = this._bufs[i].length - start + + if (bytes > l) { + this._bufs[i].copy(dst, bufoff, start) + } else { + this._bufs[i].copy(dst, bufoff, start, start + bytes) + break + } + + bufoff += l + bytes -= l + + if (start) + start = 0 + } + + return dst +} + +BufferList.prototype.shallowSlice = function shallowSlice (start, end) { + start = start || 0 + end = end || this.length + + if (start < 0) + start += this.length + if (end < 0) + end += this.length + + var startOffset = this._offset(start) + , endOffset = this._offset(end) + , buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1) + + if (endOffset[1] == 0) + buffers.pop() + else + buffers[buffers.length-1] = buffers[buffers.length-1].slice(0, endOffset[1]) + + if (startOffset[1] != 0) + buffers[0] = buffers[0].slice(startOffset[1]) + + return new BufferList(buffers) +} + +BufferList.prototype.toString = function toString (encoding, start, end) { + return this.slice(start, end).toString(encoding) +} + +BufferList.prototype.consume = function consume (bytes) { + while (this._bufs.length) { + if (bytes >= this._bufs[0].length) { + bytes -= this._bufs[0].length + this.length -= this._bufs[0].length + this._bufs.shift() + } else { + this._bufs[0] = this._bufs[0].slice(bytes) + this.length -= bytes + break + } + } + return this +} + + +BufferList.prototype.duplicate = function duplicate () { + var i = 0 + , copy = new BufferList() + + for (; i < this._bufs.length; i++) + copy.append(this._bufs[i]) + + return copy +} + + +BufferList.prototype.destroy = function destroy () { + this._bufs.length = 0 + this.length = 0 + this.push(null) +} + + +;(function () { + var methods = { + 'readDoubleBE' : 8 + , 'readDoubleLE' : 8 + , 'readFloatBE' : 4 + , 'readFloatLE' : 4 + , 'readInt32BE' : 4 + , 'readInt32LE' : 4 + , 'readUInt32BE' : 4 + , 'readUInt32LE' : 4 + , 'readInt16BE' : 2 + , 'readInt16LE' : 2 + , 'readUInt16BE' : 2 + , 'readUInt16LE' : 2 + , 'readInt8' : 1 + , 'readUInt8' : 1 + } + + for (var m in methods) { + (function (m) { + BufferList.prototype[m] = function (offset) { + return this.slice(offset, offset + methods[m])[m](0) + } + }(m)) + } +}()) + + +module.exports = BufferList + +},{"readable-stream/duplex":97,"safe-buffer":110,"util":117}],86:[function(require,module,exports){ +'use strict' + +var Buffer = require('safe-buffer').Buffer +var max = 65536 +var cache = {} + +function generateBuffer (i) { + var buffer = Buffer.allocUnsafe(2) + buffer.writeUInt8(i >> 8, 0) + buffer.writeUInt8(i & 0x00FF, 0 + 1) + + return buffer +} + +function generateCache () { + for (var i = 0; i < max; i++) { + cache[i] = generateBuffer(i) + } +} + +/** + * calcVariableByteIntLength - calculate the variable byte integer + * length field + * + * @api private + */ +function calcVariableByteIntLength (length) { + if (length >= 0 && length < 128) return 1 + else if (length >= 128 && length < 16384) return 2 + else if (length >= 16384 && length < 2097152) return 3 + else if (length >= 2097152 && length < 268435456) return 4 + else return 0 +} + +function genBufVariableByteInt (num) { + var digit = 0 + var pos = 0 + var length = calcVariableByteIntLength(num) + var buffer = Buffer.allocUnsafe(length) + + do { + digit = num % 128 | 0 + num = num / 128 | 0 + if (num > 0) digit = digit | 0x80 + + buffer.writeUInt8(digit, pos++) + } while (num > 0) + + return { + data: buffer, + length: length + } +} + +function generate4ByteBuffer (num) { + var buffer = Buffer.allocUnsafe(4) + buffer.writeUInt32BE(num, 0) + return buffer +} + +module.exports = { + cache: cache, + generateCache: generateCache, + generateNumber: generateBuffer, + genBufVariableByteInt: genBufVariableByteInt, + generate4ByteBuffer: generate4ByteBuffer +} + +},{"safe-buffer":110}],87:[function(require,module,exports){ + +function Packet () { + this.cmd = null + this.retain = false + this.qos = 0 + this.dup = false + this.length = -1 + this.topic = null + this.payload = null +} + +module.exports = Packet + +},{}],88:[function(require,module,exports){ +'use strict' + +var bl = require('bl') +var inherits = require('inherits') +var EE = require('events').EventEmitter +var Packet = require('./packet') +var constants = require('./constants') + +function Parser (opt) { + if (!(this instanceof Parser)) return new Parser(opt) + + this.settings = opt || {} + + this._states = [ + '_parseHeader', + '_parseLength', + '_parsePayload', + '_newPacket' + ] + + this._resetState() +} + +inherits(Parser, EE) + +Parser.prototype._resetState = function () { + this.packet = new Packet() + this.error = null + this._list = bl() + this._stateCounter = 0 +} + +Parser.prototype.parse = function (buf) { + if (this.error) this._resetState() + + this._list.append(buf) + + while ((this.packet.length !== -1 || this._list.length > 0) && + this[this._states[this._stateCounter]]() && + !this.error) { + this._stateCounter++ + + if (this._stateCounter >= this._states.length) this._stateCounter = 0 + } + + return this._list.length +} + +Parser.prototype._parseHeader = function () { + // There is at least one byte in the buffer + var zero = this._list.readUInt8(0) + this.packet.cmd = constants.types[zero >> constants.CMD_SHIFT] + this.packet.retain = (zero & constants.RETAIN_MASK) !== 0 + this.packet.qos = (zero >> constants.QOS_SHIFT) & constants.QOS_MASK + this.packet.dup = (zero & constants.DUP_MASK) !== 0 + + this._list.consume(1) + + return true +} + +Parser.prototype._parseLength = function () { + // There is at least one byte in the list + var result = this._parseVarByteNum(true) + + if (result) { + this.packet.length = result.value + this._list.consume(result.bytes) + } + + return !!result +} + +Parser.prototype._parsePayload = function () { + var result = false + + // Do we have a payload? Do we have enough data to complete the payload? + // PINGs have no payload + if (this.packet.length === 0 || this._list.length >= this.packet.length) { + this._pos = 0 + + switch (this.packet.cmd) { + case 'connect': + this._parseConnect() + break + case 'connack': + this._parseConnack() + break + case 'publish': + this._parsePublish() + break + case 'puback': + case 'pubrec': + case 'pubrel': + case 'pubcomp': + this._parseConfirmation() + break + case 'subscribe': + this._parseSubscribe() + break + case 'suback': + this._parseSuback() + break + case 'unsubscribe': + this._parseUnsubscribe() + break + case 'unsuback': + this._parseUnsuback() + break + case 'pingreq': + case 'pingresp': + // These are empty, nothing to do + break + case 'disconnect': + this._parseDisconnect() + break + case 'auth': + this._parseAuth() + break + default: + this._emitError(new Error('Not supported')) + } + + result = true + } + + return result +} + +Parser.prototype._parseConnect = function () { + var protocolId // Protocol ID + var clientId // Client ID + var topic // Will topic + var payload // Will payload + var password // Password + var username // Username + var flags = {} + var packet = this.packet + + // Parse protocolId + protocolId = this._parseString() + + if (protocolId === null) return this._emitError(new Error('Cannot parse protocolId')) + if (protocolId !== 'MQTT' && protocolId !== 'MQIsdp') { + return this._emitError(new Error('Invalid protocolId')) + } + + packet.protocolId = protocolId + + // Parse constants version number + if (this._pos >= this._list.length) return this._emitError(new Error('Packet too short')) + + packet.protocolVersion = this._list.readUInt8(this._pos) + + if (packet.protocolVersion !== 3 && packet.protocolVersion !== 4 && packet.protocolVersion !== 5) { + return this._emitError(new Error('Invalid protocol version')) + } + + this._pos++ + + if (this._pos >= this._list.length) { + return this._emitError(new Error('Packet too short')) + } + + // Parse connect flags + flags.username = (this._list.readUInt8(this._pos) & constants.USERNAME_MASK) + flags.password = (this._list.readUInt8(this._pos) & constants.PASSWORD_MASK) + flags.will = (this._list.readUInt8(this._pos) & constants.WILL_FLAG_MASK) + + if (flags.will) { + packet.will = {} + packet.will.retain = (this._list.readUInt8(this._pos) & constants.WILL_RETAIN_MASK) !== 0 + packet.will.qos = (this._list.readUInt8(this._pos) & + constants.WILL_QOS_MASK) >> constants.WILL_QOS_SHIFT + } + + packet.clean = (this._list.readUInt8(this._pos) & constants.CLEAN_SESSION_MASK) !== 0 + this._pos++ + + // Parse keepalive + packet.keepalive = this._parseNum() + if (packet.keepalive === -1) return this._emitError(new Error('Packet too short')) + + // parse properties + if (packet.protocolVersion === 5) { + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } + // Parse clientId + clientId = this._parseString() + if (clientId === null) return this._emitError(new Error('Packet too short')) + packet.clientId = clientId + + if (flags.will) { + if (packet.protocolVersion === 5) { + var willProperties = this._parseProperties() + if (Object.getOwnPropertyNames(willProperties).length) { + packet.will.properties = willProperties + } + } + // Parse will topic + topic = this._parseString() + if (topic === null) return this._emitError(new Error('Cannot parse will topic')) + packet.will.topic = topic + + // Parse will payload + payload = this._parseBuffer() + if (payload === null) return this._emitError(new Error('Cannot parse will payload')) + packet.will.payload = payload + } + + // Parse username + if (flags.username) { + username = this._parseString() + if (username === null) return this._emitError(new Error('Cannot parse username')) + packet.username = username + } + + // Parse password + if (flags.password) { + password = this._parseBuffer() + if (password === null) return this._emitError(new Error('Cannot parse password')) + packet.password = password + } + // need for right parse auth packet and self set up + this.settings = packet + + return packet +} + +Parser.prototype._parseConnack = function () { + var packet = this.packet + + if (this._list.length < 2) return null + + packet.sessionPresent = !!(this._list.readUInt8(this._pos++) & constants.SESSIONPRESENT_MASK) + if (this.settings.protocolVersion === 5) { + packet.reasonCode = this._list.readUInt8(this._pos++) + } else { + packet.returnCode = this._list.readUInt8(this._pos++) + } + + if (packet.returnCode === -1 || packet.reasonCode === -1) return this._emitError(new Error('Cannot parse return code')) + // mqtt 5 properties + if (this.settings.protocolVersion === 5) { + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } +} + +Parser.prototype._parsePublish = function () { + var packet = this.packet + packet.topic = this._parseString() + + if (packet.topic === null) return this._emitError(new Error('Cannot parse topic')) + + // Parse messageId + if (packet.qos > 0) if (!this._parseMessageId()) { return } + + // Properties mqtt 5 + if (this.settings.protocolVersion === 5) { + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } + + packet.payload = this._list.slice(this._pos, packet.length) +} + +Parser.prototype._parseSubscribe = function () { + var packet = this.packet + var topic + var options + var qos + var rh + var rap + var nl + var subscription + + if (packet.qos !== 1) { + return this._emitError(new Error('Wrong subscribe header')) + } + + packet.subscriptions = [] + + if (!this._parseMessageId()) { return } + + // Properties mqtt 5 + if (this.settings.protocolVersion === 5) { + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } + + while (this._pos < packet.length) { + // Parse topic + topic = this._parseString() + if (topic === null) return this._emitError(new Error('Cannot parse topic')) + + options = this._parseByte() + qos = options & constants.SUBSCRIBE_OPTIONS_QOS_MASK + nl = ((options >> constants.SUBSCRIBE_OPTIONS_NL_SHIFT) & constants.SUBSCRIBE_OPTIONS_NL_MASK) !== 0 + rap = ((options >> constants.SUBSCRIBE_OPTIONS_RAP_SHIFT) & constants.SUBSCRIBE_OPTIONS_RAP_MASK) !== 0 + rh = (options >> constants.SUBSCRIBE_OPTIONS_RH_SHIFT) & constants.SUBSCRIBE_OPTIONS_RH_MASK + + subscription = { topic: topic, qos: qos } + + // mqtt 5 options + if (this.settings.protocolVersion === 5) { + subscription.nl = nl + subscription.rap = rap + subscription.rh = rh + } + + // Push pair to subscriptions + packet.subscriptions.push(subscription) + } +} + +Parser.prototype._parseSuback = function () { + var packet = this.packet + this.packet.granted = [] + + if (!this._parseMessageId()) { return } + + // Properties mqtt 5 + if (this.settings.protocolVersion === 5) { + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } + + // Parse granted QoSes + while (this._pos < this.packet.length) { + this.packet.granted.push(this._list.readUInt8(this._pos++)) + } +} + +Parser.prototype._parseUnsubscribe = function () { + var packet = this.packet + + packet.unsubscriptions = [] + + // Parse messageId + if (!this._parseMessageId()) { return } + + // Properties mqtt 5 + if (this.settings.protocolVersion === 5) { + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } + + while (this._pos < packet.length) { + var topic + + // Parse topic + topic = this._parseString() + if (topic === null) return this._emitError(new Error('Cannot parse topic')) + + // Push topic to unsubscriptions + packet.unsubscriptions.push(topic) + } +} + +Parser.prototype._parseUnsuback = function () { + var packet = this.packet + if (!this._parseMessageId()) return this._emitError(new Error('Cannot parse messageId')) + // Properties mqtt 5 + if (this.settings.protocolVersion === 5) { + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + // Parse granted QoSes + packet.granted = [] + while (this._pos < this.packet.length) { + this.packet.granted.push(this._list.readUInt8(this._pos++)) + } + } +} + +// parse packets like puback, pubrec, pubrel, pubcomp +Parser.prototype._parseConfirmation = function () { + var packet = this.packet + + this._parseMessageId() + + if (this.settings.protocolVersion === 5) { + if (packet.length > 2) { + // response code + packet.reasonCode = this._parseByte() + // properies mqtt 5 + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } + } + + return true +} + +// parse disconnect packet +Parser.prototype._parseDisconnect = function () { + var packet = this.packet + + if (this.settings.protocolVersion === 5) { + // response code + packet.reasonCode = this._parseByte() + // properies mqtt 5 + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + } + + return true +} + +// parse auth packet +Parser.prototype._parseAuth = function () { + var packet = this.packet + + if (this.settings.protocolVersion !== 5) { + return this._emitError(new Error('Not supported auth packet for this version MQTT')) + } + + // response code + packet.reasonCode = this._parseByte() + // properies mqtt 5 + var properties = this._parseProperties() + if (Object.getOwnPropertyNames(properties).length) { + packet.properties = properties + } + + return true +} + +Parser.prototype._parseMessageId = function () { + var packet = this.packet + + packet.messageId = this._parseNum() + + if (packet.messageId === null) { + this._emitError(new Error('Cannot parse messageId')) + return false + } + + return true +} + +Parser.prototype._parseString = function (maybeBuffer) { + var length = this._parseNum() + var result + var end = length + this._pos + + if (length === -1 || end > this._list.length || end > this.packet.length) return null + + result = this._list.toString('utf8', this._pos, end) + this._pos += length + + return result +} + +Parser.prototype._parseStringPair = function () { + return { + name: this._parseString(), + value: this._parseString() + } +} + +Parser.prototype._parseBuffer = function () { + var length = this._parseNum() + var result + var end = length + this._pos + + if (length === -1 || end > this._list.length || end > this.packet.length) return null + + result = this._list.slice(this._pos, end) + + this._pos += length + + return result +} + +Parser.prototype._parseNum = function () { + if (this._list.length - this._pos < 2) return -1 + + var result = this._list.readUInt16BE(this._pos) + this._pos += 2 + + return result +} + +Parser.prototype._parse4ByteNum = function () { + if (this._list.length - this._pos < 4) return -1 + + var result = this._list.readUInt32BE(this._pos) + this._pos += 4 + + return result +} + +Parser.prototype._parseVarByteNum = function (fullInfoFlag) { + var bytes = 0 + var mul = 1 + var length = 0 + var result = true + var current + var padding = this._pos ? this._pos : 0 + + while (bytes < 5) { + current = this._list.readUInt8(padding + bytes++) + length += mul * (current & constants.LENGTH_MASK) + mul *= 0x80 + + if ((current & constants.LENGTH_FIN_MASK) === 0) break + if (this._list.length <= bytes) { + result = false + break + } + } + + if (padding) { + this._pos += bytes + } + + result = result + ? fullInfoFlag ? { + bytes: bytes, + value: length + } : length + : false + + return result +} + +Parser.prototype._parseByte = function () { + var result = this._list.readUInt8(this._pos) + this._pos++ + return result +} + +Parser.prototype._parseByType = function (type) { + switch (type) { + case 'byte': { + return this._parseByte() !== 0 + } + case 'int8': { + return this._parseByte() + } + case 'int16': { + return this._parseNum() + } + case 'int32': { + return this._parse4ByteNum() + } + case 'var': { + return this._parseVarByteNum() + } + case 'string': { + return this._parseString() + } + case 'pair': { + return this._parseStringPair() + } + case 'binary': { + return this._parseBuffer() + } + } +} + +Parser.prototype._parseProperties = function () { + var length = this._parseVarByteNum() + var start = this._pos + var end = start + length + var result = {} + while (this._pos < end) { + var type = this._parseByte() + var name = constants.propertiesCodes[type] + if (!name) { + this._emitError(new Error('Unknown property')) + return false + } + // user properties process + if (name === 'userProperties') { + if (!result[name]) { + result[name] = {} + } + var currentUserProperty = this._parseByType(constants.propertiesTypes[name]) + result[name][currentUserProperty.name] = currentUserProperty.value + continue + } + result[name] = this._parseByType(constants.propertiesTypes[name]) + } + return result +} + +Parser.prototype._newPacket = function () { + if (this.packet) { + this._list.consume(this.packet.length) + this.emit('packet', this.packet) + } + + this.packet = new Packet() + + this._pos = 0 + + return true +} + +Parser.prototype._emitError = function (err) { + this.error = err + this.emit('error', err) +} + +module.exports = Parser + +},{"./constants":82,"./packet":87,"bl":85,"events":13,"inherits":80}],89:[function(require,module,exports){ +'use strict' + +var protocol = require('./constants') +var Buffer = require('safe-buffer').Buffer +var empty = Buffer.allocUnsafe(0) +var zeroBuf = Buffer.from([0]) +var numbers = require('./numbers') +var nextTick = require('process-nextick-args').nextTick + +var numCache = numbers.cache +var generateNumber = numbers.generateNumber +var generateCache = numbers.generateCache +var genBufVariableByteInt = numbers.genBufVariableByteInt +var generate4ByteBuffer = numbers.generate4ByteBuffer +var writeNumber = writeNumberCached +var toGenerate = true + +function generate (packet, stream, opts) { + if (stream.cork) { + stream.cork() + nextTick(uncork, stream) + } + + if (toGenerate) { + toGenerate = false + generateCache() + } + + switch (packet.cmd) { + case 'connect': + return connect(packet, stream, opts) + case 'connack': + return connack(packet, stream, opts) + case 'publish': + return publish(packet, stream, opts) + case 'puback': + case 'pubrec': + case 'pubrel': + case 'pubcomp': + return confirmation(packet, stream, opts) + case 'subscribe': + return subscribe(packet, stream, opts) + case 'suback': + return suback(packet, stream, opts) + case 'unsubscribe': + return unsubscribe(packet, stream, opts) + case 'unsuback': + return unsuback(packet, stream, opts) + case 'pingreq': + case 'pingresp': + return emptyPacket(packet, stream, opts) + case 'disconnect': + return disconnect(packet, stream, opts) + case 'auth': + return auth(packet, stream, opts) + default: + stream.emit('error', new Error('Unknown command')) + return false + } +} +/** + * Controls numbers cache. + * Set to "false" to allocate buffers on-the-flight instead of pre-generated cache + */ +Object.defineProperty(generate, 'cacheNumbers', { + get: function () { + return writeNumber === writeNumberCached + }, + set: function (value) { + if (value) { + if (!numCache || Object.keys(numCache).length === 0) toGenerate = true + writeNumber = writeNumberCached + } else { + toGenerate = false + writeNumber = writeNumberGenerated + } + } +}) + +function uncork (stream) { + stream.uncork() +} + +function connect (packet, stream, opts) { + var settings = packet || {} + var protocolId = settings.protocolId || 'MQTT' + var protocolVersion = settings.protocolVersion || 4 + var will = settings.will + var clean = settings.clean + var keepalive = settings.keepalive || 0 + var clientId = settings.clientId || '' + var username = settings.username + var password = settings.password + /* mqtt5 new oprions */ + var properties = settings.properties + + if (clean === undefined) clean = true + + var length = 0 + + // Must be a string and non-falsy + if (!protocolId || + (typeof protocolId !== 'string' && !Buffer.isBuffer(protocolId))) { + stream.emit('error', new Error('Invalid protocolId')) + return false + } else length += protocolId.length + 2 + + // Must be 3 or 4 or 5 + if (protocolVersion !== 3 && protocolVersion !== 4 && protocolVersion !== 5) { + stream.emit('error', new Error('Invalid protocol version')) + return false + } else length += 1 + + // ClientId might be omitted in 3.1.1, but only if cleanSession is set to 1 + if ((typeof clientId === 'string' || Buffer.isBuffer(clientId)) && + (clientId || protocolVersion === 4) && (clientId || clean)) { + length += clientId.length + 2 + } else { + if (protocolVersion < 4) { + stream.emit('error', new Error('clientId must be supplied before 3.1.1')) + return false + } + if ((clean * 1) === 0) { + stream.emit('error', new Error('clientId must be given if cleanSession set to 0')) + return false + } + } + + // Must be a two byte number + if (typeof keepalive !== 'number' || + keepalive < 0 || + keepalive > 65535 || + keepalive % 1 !== 0) { + stream.emit('error', new Error('Invalid keepalive')) + return false + } else length += 2 + + // Connect flags + length += 1 + + // Properties + if (protocolVersion === 5) { + var propertiesData = getProperties(stream, properties) + length += propertiesData.length + } + + // If will exists... + if (will) { + // It must be an object + if (typeof will !== 'object') { + stream.emit('error', new Error('Invalid will')) + return false + } + // It must have topic typeof string + if (!will.topic || typeof will.topic !== 'string') { + stream.emit('error', new Error('Invalid will topic')) + return false + } else { + length += Buffer.byteLength(will.topic) + 2 + } + + // Payload + if (will.payload) { + if (will.payload.length >= 0) { + if (typeof will.payload === 'string') { + length += Buffer.byteLength(will.payload) + 2 + } else { + length += will.payload.length + 2 + } + } else { + stream.emit('error', new Error('Invalid will payload')) + return false + } + + // will properties + var willProperties = {} + if (protocolVersion === 5) { + willProperties = getProperties(stream, will.properties) + length += willProperties.length + } + } + } + + // Username + var providedUsername = false + if (username != null) { + if (isStringOrBuffer(username)) { + providedUsername = true + length += Buffer.byteLength(username) + 2 + } else { + stream.emit('error', new Error('Invalid username')) + return false + } + } + + // Password + if (password != null) { + if (!providedUsername) { + stream.emit('error', new Error('Username is required to use password')) + return false + } + + if (isStringOrBuffer(password)) { + length += byteLength(password) + 2 + } else { + stream.emit('error', new Error('Invalid password')) + return false + } + } + + // Generate header + stream.write(protocol.CONNECT_HEADER) + + // Generate length + writeVarByteInt(stream, length) + + // Generate protocol ID + writeStringOrBuffer(stream, protocolId) + stream.write( + protocolVersion === 4 + ? protocol.VERSION4 + : protocolVersion === 5 + ? protocol.VERSION5 + : protocol.VERSION3 + ) + + // Connect flags + var flags = 0 + flags |= (username != null) ? protocol.USERNAME_MASK : 0 + flags |= (password != null) ? protocol.PASSWORD_MASK : 0 + flags |= (will && will.retain) ? protocol.WILL_RETAIN_MASK : 0 + flags |= (will && will.qos) ? will.qos << protocol.WILL_QOS_SHIFT : 0 + flags |= will ? protocol.WILL_FLAG_MASK : 0 + flags |= clean ? protocol.CLEAN_SESSION_MASK : 0 + + stream.write(Buffer.from([flags])) + + // Keepalive + writeNumber(stream, keepalive) + + // Properties + if (protocolVersion === 5) { + propertiesData.write() + } + + // Client ID + writeStringOrBuffer(stream, clientId) + + // Will + if (will) { + if (protocolVersion === 5) { + willProperties.write() + } + writeString(stream, will.topic) + writeStringOrBuffer(stream, will.payload) + } + + // Username and password + if (username != null) { + writeStringOrBuffer(stream, username) + } + if (password != null) { + writeStringOrBuffer(stream, password) + } + // This is a small packet that happens only once on a stream + // We assume the stream is always free to receive more data after this + return true +} + +function connack (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var rc = version === 5 ? settings.reasonCode : settings.returnCode + var properties = settings.properties + var length = 2 // length of rc and sessionHeader + + // Check return code + if (typeof rc !== 'number') { + stream.emit('error', new Error('Invalid return code')) + return false + } + // mqtt5 properties + var propertiesData = null + if (version === 5) { + propertiesData = getProperties(stream, properties) + length += propertiesData.length + } + + stream.write(protocol.CONNACK_HEADER) + // length + writeVarByteInt(stream, length) + stream.write(settings.sessionPresent ? protocol.SESSIONPRESENT_HEADER : zeroBuf) + + stream.write(Buffer.from([rc])) + if (propertiesData != null) { + propertiesData.write() + } + return true +} + +function publish (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var qos = settings.qos || 0 + var retain = settings.retain ? protocol.RETAIN_MASK : 0 + var topic = settings.topic + var payload = settings.payload || empty + var id = settings.messageId + var properties = settings.properties + + var length = 0 + + // Topic must be a non-empty string or Buffer + if (typeof topic === 'string') length += Buffer.byteLength(topic) + 2 + else if (Buffer.isBuffer(topic)) length += topic.length + 2 + else { + stream.emit('error', new Error('Invalid topic')) + return false + } + + // Get the payload length + if (!Buffer.isBuffer(payload)) length += Buffer.byteLength(payload) + else length += payload.length + + // Message ID must a number if qos > 0 + if (qos && typeof id !== 'number') { + stream.emit('error', new Error('Invalid messageId')) + return false + } else if (qos) length += 2 + + // mqtt5 properties + var propertiesData = null + if (version === 5) { + propertiesData = getProperties(stream, properties) + length += propertiesData.length + } + + // Header + stream.write(protocol.PUBLISH_HEADER[qos][settings.dup ? 1 : 0][retain ? 1 : 0]) + + // Remaining length + writeVarByteInt(stream, length) + + // Topic + writeNumber(stream, byteLength(topic)) + stream.write(topic) + + // Message ID + if (qos > 0) writeNumber(stream, id) + + // Properties + if (propertiesData != null) { + propertiesData.write() + } + + // Payload + return stream.write(payload) +} + +/* Puback, pubrec, pubrel and pubcomp */ +function confirmation (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var type = settings.cmd || 'puback' + var id = settings.messageId + var dup = (settings.dup && type === 'pubrel') ? protocol.DUP_MASK : 0 + var qos = 0 + var reasonCode = settings.reasonCode + var properties = settings.properties + var length = version === 5 ? 3 : 2 + + if (type === 'pubrel') qos = 1 + + // Check message ID + if (typeof id !== 'number') { + stream.emit('error', new Error('Invalid messageId')) + return false + } + + // properies mqtt 5 + var propertiesData = null + if (version === 5) { + propertiesData = getPropertiesByMaximumPacketSize(stream, properties, opts, length) + if (!propertiesData) { return false } + length += propertiesData.length + } + + // Header + stream.write(protocol.ACKS[type][qos][dup][0]) + + // Length + writeVarByteInt(stream, length) + + // Message ID + writeNumber(stream, id) + + // reason code in header + if (version === 5) { + stream.write(Buffer.from([reasonCode])) + } + + // properies mqtt 5 + if (propertiesData !== null) { + propertiesData.write() + } + return true +} + +function subscribe (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var dup = settings.dup ? protocol.DUP_MASK : 0 + var id = settings.messageId + var subs = settings.subscriptions + var properties = settings.properties + + var length = 0 + + // Check message ID + if (typeof id !== 'number') { + stream.emit('error', new Error('Invalid messageId')) + return false + } else length += 2 + + // properies mqtt 5 + var propertiesData = null + if (version === 5) { + propertiesData = getProperties(stream, properties) + length += propertiesData.length + } + + // Check subscriptions + if (typeof subs === 'object' && subs.length) { + for (var i = 0; i < subs.length; i += 1) { + var itopic = subs[i].topic + var iqos = subs[i].qos + + if (typeof itopic !== 'string') { + stream.emit('error', new Error('Invalid subscriptions - invalid topic')) + return false + } + if (typeof iqos !== 'number') { + stream.emit('error', new Error('Invalid subscriptions - invalid qos')) + return false + } + + if (version === 5) { + var nl = subs[i].nl || false + if (typeof nl !== 'boolean') { + stream.emit('error', new Error('Invalid subscriptions - invalid No Local')) + return false + } + var rap = subs[i].rap || false + if (typeof rap !== 'boolean') { + stream.emit('error', new Error('Invalid subscriptions - invalid Retain as Published')) + return false + } + var rh = subs[i].rh || 0 + if (typeof rh !== 'number' || rh > 2) { + stream.emit('error', new Error('Invalid subscriptions - invalid Retain Handling')) + return false + } + } + + length += Buffer.byteLength(itopic) + 2 + 1 + } + } else { + stream.emit('error', new Error('Invalid subscriptions')) + return false + } + + // Generate header + stream.write(protocol.SUBSCRIBE_HEADER[1][dup ? 1 : 0][0]) + + // Generate length + writeVarByteInt(stream, length) + + // Generate message ID + writeNumber(stream, id) + + // properies mqtt 5 + if (propertiesData !== null) { + propertiesData.write() + } + + var result = true + + // Generate subs + for (var j = 0; j < subs.length; j++) { + var sub = subs[j] + var jtopic = sub.topic + var jqos = sub.qos + var jnl = +sub.nl + var jrap = +sub.rap + var jrh = sub.rh + var joptions + + // Write topic string + writeString(stream, jtopic) + + // options process + joptions = protocol.SUBSCRIBE_OPTIONS_QOS[jqos] + if (version === 5) { + joptions |= jnl ? protocol.SUBSCRIBE_OPTIONS_NL : 0 + joptions |= jrap ? protocol.SUBSCRIBE_OPTIONS_RAP : 0 + joptions |= jrh ? protocol.SUBSCRIBE_OPTIONS_RH[jrh] : 0 + } + // Write options + result = stream.write(Buffer.from([joptions])) + } + + return result +} + +function suback (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var id = settings.messageId + var granted = settings.granted + var properties = settings.properties + var length = 0 + + // Check message ID + if (typeof id !== 'number') { + stream.emit('error', new Error('Invalid messageId')) + return false + } else length += 2 + + // Check granted qos vector + if (typeof granted === 'object' && granted.length) { + for (var i = 0; i < granted.length; i += 1) { + if (typeof granted[i] !== 'number') { + stream.emit('error', new Error('Invalid qos vector')) + return false + } + length += 1 + } + } else { + stream.emit('error', new Error('Invalid qos vector')) + return false + } + + // properies mqtt 5 + var propertiesData = null + if (version === 5) { + propertiesData = getPropertiesByMaximumPacketSize(stream, properties, opts, length) + if (!propertiesData) { return false } + length += propertiesData.length + } + + // header + stream.write(protocol.SUBACK_HEADER) + + // Length + writeVarByteInt(stream, length) + + // Message ID + writeNumber(stream, id) + + // properies mqtt 5 + if (propertiesData !== null) { + propertiesData.write() + } + + return stream.write(Buffer.from(granted)) +} + +function unsubscribe (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var id = settings.messageId + var dup = settings.dup ? protocol.DUP_MASK : 0 + var unsubs = settings.unsubscriptions + var properties = settings.properties + + var length = 0 + + // Check message ID + if (typeof id !== 'number') { + stream.emit('error', new Error('Invalid messageId')) + return false + } else { + length += 2 + } + // Check unsubs + if (typeof unsubs === 'object' && unsubs.length) { + for (var i = 0; i < unsubs.length; i += 1) { + if (typeof unsubs[i] !== 'string') { + stream.emit('error', new Error('Invalid unsubscriptions')) + return false + } + length += Buffer.byteLength(unsubs[i]) + 2 + } + } else { + stream.emit('error', new Error('Invalid unsubscriptions')) + return false + } + // properies mqtt 5 + var propertiesData = null + if (version === 5) { + propertiesData = getProperties(stream, properties) + length += propertiesData.length + } + + // Header + stream.write(protocol.UNSUBSCRIBE_HEADER[1][dup ? 1 : 0][0]) + + // Length + writeVarByteInt(stream, length) + + // Message ID + writeNumber(stream, id) + + // properies mqtt 5 + if (propertiesData !== null) { + propertiesData.write() + } + + // Unsubs + var result = true + for (var j = 0; j < unsubs.length; j++) { + result = writeString(stream, unsubs[j]) + } + + return result +} + +function unsuback (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var id = settings.messageId + var dup = settings.dup ? protocol.DUP_MASK : 0 + var granted = settings.granted + var properties = settings.properties + var type = settings.cmd + var qos = 0 + + var length = 2 + + // Check message ID + if (typeof id !== 'number') { + stream.emit('error', new Error('Invalid messageId')) + return false + } + + // Check granted + if (version === 5) { + if (typeof granted === 'object' && granted.length) { + for (var i = 0; i < granted.length; i += 1) { + if (typeof granted[i] !== 'number') { + stream.emit('error', new Error('Invalid qos vector')) + return false + } + length += 1 + } + } else { + stream.emit('error', new Error('Invalid qos vector')) + return false + } + } + + // properies mqtt 5 + var propertiesData = null + if (version === 5) { + propertiesData = getPropertiesByMaximumPacketSize(stream, properties, opts, length) + if (!propertiesData) { return false } + length += propertiesData.length + } + + // Header + stream.write(protocol.ACKS[type][qos][dup][0]) + + // Length + writeVarByteInt(stream, length) + + // Message ID + writeNumber(stream, id) + + // properies mqtt 5 + if (propertiesData !== null) { + propertiesData.write() + } + + // payload + if (version === 5) { + stream.write(Buffer.from(granted)) + } + return true +} + +function emptyPacket (packet, stream, opts) { + return stream.write(protocol.EMPTY[packet.cmd]) +} + +function disconnect (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var reasonCode = settings.reasonCode + var properties = settings.properties + var length = version === 5 ? 1 : 0 + + // properies mqtt 5 + var propertiesData = null + if (version === 5) { + propertiesData = getPropertiesByMaximumPacketSize(stream, properties, opts, length) + if (!propertiesData) { return false } + length += propertiesData.length + } + + // Header + stream.write(Buffer.from([protocol.codes['disconnect'] << 4])) + + // Length + writeVarByteInt(stream, length) + + // reason code in header + if (version === 5) { + stream.write(Buffer.from([reasonCode])) + } + + // properies mqtt 5 + if (propertiesData !== null) { + propertiesData.write() + } + + return true +} + +function auth (packet, stream, opts) { + var version = opts ? opts.protocolVersion : 4 + var settings = packet || {} + var reasonCode = settings.reasonCode + var properties = settings.properties + var length = version === 5 ? 1 : 0 + + if (version !== 5) stream.emit('error', new Error('Invalid mqtt version for auth packet')) + + // properies mqtt 5 + var propertiesData = getPropertiesByMaximumPacketSize(stream, properties, opts, length) + if (!propertiesData) { return false } + length += propertiesData.length + + // Header + stream.write(Buffer.from([protocol.codes['auth'] << 4])) + + // Length + writeVarByteInt(stream, length) + + // reason code in header + stream.write(Buffer.from([reasonCode])) + + // properies mqtt 5 + if (propertiesData !== null) { + propertiesData.write() + } + return true +} + +/** + * writeVarByteInt - write an MQTT style variable byte integer to the buffer + * + * @param buffer - destination + * @param pos - offset + * @param length - length (>0) + * @returns number of bytes written + * + * @api private + */ + +var varByteIntCache = {} +function writeVarByteInt (stream, num) { + var buffer = varByteIntCache[num] + + if (!buffer) { + buffer = genBufVariableByteInt(num).data + if (num < 16384) varByteIntCache[num] = buffer + } + + stream.write(buffer) +} + +/** + * writeString - write a utf8 string to the buffer + * + * @param buffer - destination + * @param pos - offset + * @param string - string to write + * @return number of bytes written + * + * @api private + */ + +function writeString (stream, string) { + var strlen = Buffer.byteLength(string) + writeNumber(stream, strlen) + + stream.write(string, 'utf8') +} + +/** + * writeStringPair - write a utf8 string pairs to the buffer + * + * @param buffer - destination + * @param name - string name to write + * @param value - string value to write + * @return number of bytes written + * + * @api private + */ +function writeStringPair (stream, name, value) { + writeString(stream, name) + writeString(stream, value) +} + +/** + * writeNumber - write a two byte number to the buffer + * + * @param buffer - destination + * @param pos - offset + * @param number - number to write + * @return number of bytes written + * + * @api private + */ +function writeNumberCached (stream, number) { + return stream.write(numCache[number]) +} +function writeNumberGenerated (stream, number) { + return stream.write(generateNumber(number)) +} +function write4ByteNumber (stream, number) { + return stream.write(generate4ByteBuffer(number)) +} +/** + * writeStringOrBuffer - write a String or Buffer with the its length prefix + * + * @param buffer - destination + * @param pos - offset + * @param toWrite - String or Buffer + * @return number of bytes written + */ +function writeStringOrBuffer (stream, toWrite) { + if (typeof toWrite === 'string') { + writeString(stream, toWrite) + } else if (toWrite) { + writeNumber(stream, toWrite.length) + stream.write(toWrite) + } else writeNumber(stream, 0) +} + +function getProperties (stream, properties) { + /* connect properties */ + if (typeof properties !== 'object' || properties.length != null) { + return { + length: 1, + write: function () { + writeProperties(stream, {}, 0) + } + } + } + var propertiesLength = 0 + function getLengthProperty (name) { + var type = protocol.propertiesTypes[name] + var value = properties[name] + var length = 0 + switch (type) { + case 'byte': { + if (typeof value !== 'boolean') { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += 1 + 1 + break + } + case 'int8': { + if (typeof value !== 'number') { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += 1 + 1 + break + } + case 'binary': { + if (value && value === null) { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += 1 + Buffer.byteLength(value) + 2 + break + } + case 'int16': { + if (typeof value !== 'number') { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += 1 + 2 + break + } + case 'int32': { + if (typeof value !== 'number') { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += 1 + 4 + break + } + case 'var': { + if (typeof value !== 'number') { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += 1 + genBufVariableByteInt(value).length + break + } + case 'string': { + if (typeof value !== 'string') { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += 1 + 2 + Buffer.byteLength(value.toString()) + break + } + case 'pair': { + if (typeof value !== 'object') { + stream.emit('error', new Error('Invalid ' + name)) + return false + } + length += Object.getOwnPropertyNames(value).reduce(function (result, name) { + result += 1 + 2 + Buffer.byteLength(name.toString()) + 2 + Buffer.byteLength(value[name].toString()) + return result + }, 0) + break + } + default: { + stream.emit('error', new Error('Invalid property ' + name)) + return false + } + } + return length + } + if (properties) { + for (var propName in properties) { + var propLength = getLengthProperty(propName) + if (!propLength) return false + propertiesLength += propLength + } + } + var propertiesLengthLength = genBufVariableByteInt(propertiesLength).length + + return { + length: propertiesLengthLength + propertiesLength, + write: function () { + writeProperties(stream, properties, propertiesLength) + } + } +} + +function getPropertiesByMaximumPacketSize (stream, properties, opts, length) { + var mayEmptyProps = ['reasonString', 'userProperties'] + var maximumPacketSize = opts && opts.properties && opts.properties.maximumPacketSize ? opts.properties.maximumPacketSize : 0 + + var propertiesData = getProperties(stream, properties) + if (maximumPacketSize) { + while (length + propertiesData.length > maximumPacketSize) { + var currentMayEmptyProp = mayEmptyProps.shift() + if (currentMayEmptyProp && properties[currentMayEmptyProp]) { + delete properties[currentMayEmptyProp] + propertiesData = getProperties(stream, properties) + } else { + return false + } + } + } + return propertiesData +} + +function writeProperties (stream, properties, propertiesLength) { + /* write properties to stream */ + writeVarByteInt(stream, propertiesLength) + for (var propName in properties) { + if (properties.hasOwnProperty(propName) && properties[propName] !== null) { + var value = properties[propName] + var type = protocol.propertiesTypes[propName] + switch (type) { + case 'byte': { + stream.write(Buffer.from([protocol.properties[propName]])) + stream.write(Buffer.from([+value])) + break + } + case 'int8': { + stream.write(Buffer.from([protocol.properties[propName]])) + stream.write(Buffer.from([value])) + break + } + case 'binary': { + stream.write(Buffer.from([protocol.properties[propName]])) + writeStringOrBuffer(stream, value) + break + } + case 'int16': { + stream.write(Buffer.from([protocol.properties[propName]])) + writeNumber(stream, value) + break + } + case 'int32': { + stream.write(Buffer.from([protocol.properties[propName]])) + write4ByteNumber(stream, value) + break + } + case 'var': { + stream.write(Buffer.from([protocol.properties[propName]])) + writeVarByteInt(stream, value) + break + } + case 'string': { + stream.write(Buffer.from([protocol.properties[propName]])) + writeString(stream, value) + break + } + case 'pair': { + Object.getOwnPropertyNames(value).forEach(function (name) { + stream.write(Buffer.from([protocol.properties[propName]])) + writeStringPair(stream, name.toString(), value[name].toString()) + }) + break + } + default: { + stream.emit('error', new Error('Invalid property ' + propName)) + return false + } + } + } + } +} + +function byteLength (bufOrString) { + if (!bufOrString) return 0 + else if (bufOrString instanceof Buffer) return bufOrString.length + else return Buffer.byteLength(bufOrString) +} + +function isStringOrBuffer (field) { + return typeof field === 'string' || field instanceof Buffer +} + +module.exports = generate + +},{"./constants":82,"./numbers":86,"process-nextick-args":91,"safe-buffer":110}],90:[function(require,module,exports){ +var wrappy = require('wrappy') +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + +},{"wrappy":120}],91:[function(require,module,exports){ +(function (process){ +'use strict'; + +if (!process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = { nextTick: nextTick }; +} else { + module.exports = process +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + + +}).call(this,require('_process')) +},{"_process":92}],92:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],93:[function(require,module,exports){ +(function (global){ +/*! https://mths.be/punycode v1.4.1 by @mathias */ +;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.4.1', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define('punycode', function() { + return punycode; + }); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + +}(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],94:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +// If obj.hasOwnProperty has been overridden, then calling +// obj.hasOwnProperty(prop) will break. +// See: https://github.com/joyent/node/issues/1707 +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +},{}],95:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } +}; + +module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return map(objectKeys(obj), function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (isArray(obj[k])) { + return map(obj[k], function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +function map (xs, f) { + if (xs.map) return xs.map(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + res.push(f(xs[i], i)); + } + return res; +} + +var objectKeys = Object.keys || function (obj) { + var res = []; + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); + } + return res; +}; + +},{}],96:[function(require,module,exports){ +'use strict'; + +exports.decode = exports.parse = require('./decode'); +exports.encode = exports.stringify = require('./encode'); + +},{"./decode":94,"./encode":95}],97:[function(require,module,exports){ +module.exports = require('./lib/_stream_duplex.js'); + +},{"./lib/_stream_duplex.js":98}],98:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; +},{"./_stream_readable":100,"./_stream_writable":102,"core-util-is":14,"inherits":80,"process-nextick-args":91}],99:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; +},{"./_stream_transform":101,"core-util-is":14,"inherits":80}],100:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./_stream_duplex":98,"./internal/streams/BufferList":103,"./internal/streams/destroy":104,"./internal/streams/stream":105,"_process":92,"core-util-is":14,"events":13,"inherits":80,"isarray":106,"process-nextick-args":91,"safe-buffer":110,"string_decoder/":107,"util":11}],101:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} +},{"./_stream_duplex":98,"core-util-is":14,"inherits":80}],102:[function(require,module,exports){ +(function (process,global,setImmediate){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate) +},{"./_stream_duplex":98,"./internal/streams/destroy":104,"./internal/streams/stream":105,"_process":92,"core-util-is":14,"inherits":80,"process-nextick-args":91,"safe-buffer":110,"timers":112,"util-deprecate":115}],103:[function(require,module,exports){ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('safe-buffer').Buffer; +var util = require('util'); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} +},{"safe-buffer":110,"util":11}],104:[function(require,module,exports){ +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + pna.nextTick(emitErrorNT, this, err); + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + pna.nextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; +},{"process-nextick-args":91}],105:[function(require,module,exports){ +module.exports = require('events').EventEmitter; + +},{"events":13}],106:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + +},{}],107:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var Buffer = require('safe-buffer').Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"safe-buffer":110}],108:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":98,"./lib/_stream_passthrough.js":99,"./lib/_stream_readable.js":100,"./lib/_stream_transform.js":101,"./lib/_stream_writable.js":102}],109:[function(require,module,exports){ +'use strict' + +function ReInterval (callback, interval, args) { + var self = this; + + this._callback = callback; + this._args = args; + + this._interval = setInterval(callback, interval, this._args); + + this.reschedule = function (interval) { + // if no interval entered, use the interval passed in on creation + if (!interval) + interval = self._interval; + + if (self._interval) + clearInterval(self._interval); + self._interval = setInterval(self._callback, interval, self._args); + }; + + this.clear = function () { + if (self._interval) { + clearInterval(self._interval); + self._interval = undefined; + } + }; + + this.destroy = function () { + if (self._interval) { + clearInterval(self._interval); + } + self._callback = undefined; + self._interval = undefined; + self._args = undefined; + }; +} + +function reInterval () { + if (typeof arguments[0] !== 'function') + throw new Error('callback needed'); + if (typeof arguments[1] !== 'number') + throw new Error('interval needed'); + + var args; + + if (arguments.length > 0) { + args = new Array(arguments.length - 2); + + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i + 2]; + } + } + + return new ReInterval(arguments[0], arguments[1], args); +} + +module.exports = reInterval; + +},{}],110:[function(require,module,exports){ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"buffer":12}],111:[function(require,module,exports){ +module.exports = shift + +function shift (stream) { + var rs = stream._readableState + if (!rs) return null + return rs.objectMode ? stream.read() : stream.read(getStateLength(rs)) +} + +function getStateLength (state) { + if (state.buffer.length) { + // Since node 6.3.0 state.buffer is a BufferList not an array + if (state.buffer.head) { + return state.buffer.head.data.length + } + + return state.buffer[0].length + } + + return state.length +} + +},{}],112:[function(require,module,exports){ +(function (setImmediate,clearImmediate){ +var nextTick = require('process/browser.js').nextTick; +var apply = Function.prototype.apply; +var slice = Array.prototype.slice; +var immediateIds = {}; +var nextImmediateId = 0; + +// DOM APIs, for completeness + +exports.setTimeout = function() { + return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); +}; +exports.setInterval = function() { + return new Timeout(apply.call(setInterval, window, arguments), clearInterval); +}; +exports.clearTimeout = +exports.clearInterval = function(timeout) { timeout.close(); }; + +function Timeout(id, clearFn) { + this._id = id; + this._clearFn = clearFn; +} +Timeout.prototype.unref = Timeout.prototype.ref = function() {}; +Timeout.prototype.close = function() { + this._clearFn.call(window, this._id); +}; + +// Does not start the time, just sets up the members needed. +exports.enroll = function(item, msecs) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = msecs; +}; + +exports.unenroll = function(item) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = -1; +}; + +exports._unrefActive = exports.active = function(item) { + clearTimeout(item._idleTimeoutId); + + var msecs = item._idleTimeout; + if (msecs >= 0) { + item._idleTimeoutId = setTimeout(function onTimeout() { + if (item._onTimeout) + item._onTimeout(); + }, msecs); + } +}; + +// That's not how node.js implements it but the exposed api is the same. +exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { + var id = nextImmediateId++; + var args = arguments.length < 2 ? false : slice.call(arguments, 1); + + immediateIds[id] = true; + + nextTick(function onNextTick() { + if (immediateIds[id]) { + // fn.call() is faster so we optimize for the common use-case + // @see http://jsperf.com/call-apply-segu + if (args) { + fn.apply(null, args); + } else { + fn.call(null); + } + // Prevent ids from leaking + exports.clearImmediate(id); + } + }); + + return id; +}; + +exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { + delete immediateIds[id]; +}; +}).call(this,require("timers").setImmediate,require("timers").clearImmediate) +},{"process/browser.js":92,"timers":112}],113:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +var punycode = require('punycode'); +var util = require('./util'); + +exports.parse = urlParse; +exports.resolve = urlResolve; +exports.resolveObject = urlResolveObject; +exports.format = urlFormat; + +exports.Url = Url; + +function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; +} + +// Reference: RFC 3986, RFC 1808, RFC 2396 + +// define these here so at least they only have to be +// compiled once on the first module load. +var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // Special case for a simple path URL + simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = require('querystring'); + +function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && util.isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; +} + +Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!util.isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + var queryIndex = url.indexOf('?'), + splitter = + (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', + uSplit = url.split(splitter), + slashRegex = /\\/g; + uSplit[0] = uSplit[0].replace(slashRegex, '/'); + url = uSplit.join(splitter); + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + if (!slashesDenoteHost && url.split('#').length === 1) { + // Try fast path regexp + var simplePath = simplePathPattern.exec(rest); + if (simplePath) { + this.path = rest; + this.href = rest; + this.pathname = simplePath[1]; + if (simplePath[2]) { + this.search = simplePath[2]; + if (parseQueryString) { + this.query = querystring.parse(this.search.substr(1)); + } else { + this.query = this.search.substr(1); + } + } else if (parseQueryString) { + this.search = ''; + this.query = {}; + } + return this; + } + } + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a punycoded representation of "domain". + // It only converts parts of the domain name that + // have non-ASCII characters, i.e. it doesn't matter if + // you call it with a domain that already is ASCII-only. + this.hostname = punycode.toASCII(this.hostname); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + if (rest.indexOf(ae) === -1) + continue; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; +}; + +// format a parsed object into a url string +function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (util.isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); +} + +Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + util.isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; +}; + +function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); +} + +Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); +}; + +function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); +} + +Url.prototype.resolveObject = function(relative) { + if (util.isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + var tkeys = Object.keys(this); + for (var tk = 0; tk < tkeys.length; tk++) { + var tkey = tkeys[tk]; + result[tkey] = this[tkey]; + } + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + var rkeys = Object.keys(relative); + for (var rk = 0; rk < rkeys.length; rk++) { + var rkey = rkeys[rk]; + if (rkey !== 'protocol') + result[rkey] = relative[rkey]; + } + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + var keys = Object.keys(relative); + for (var v = 0; v < keys.length; v++) { + var k = keys[v]; + result[k] = relative[k]; + } + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!util.isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!util.isNull(result.pathname) || !util.isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host || srcPath.length > 1) && + (last === '.' || last === '..') || last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last === '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!util.isNull(result.pathname) || !util.isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; +}; + +Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; +}; + +},{"./util":114,"punycode":93,"querystring":96}],114:[function(require,module,exports){ +'use strict'; + +module.exports = { + isString: function(arg) { + return typeof(arg) === 'string'; + }, + isObject: function(arg) { + return typeof(arg) === 'object' && arg !== null; + }, + isNull: function(arg) { + return arg === null; + }, + isNullOrUndefined: function(arg) { + return arg == null; + } +}; + +},{}],115:[function(require,module,exports){ +(function (global){ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],116:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],117:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":116,"_process":92,"inherits":80}],118:[function(require,module,exports){ +(function (process,global){ +'use strict' + +var Transform = require('readable-stream').Transform +var duplexify = require('duplexify') +var WS = require('ws') +var Buffer = require('safe-buffer').Buffer + +module.exports = WebSocketStream + +function buildProxy (options, socketWrite, socketEnd) { + var proxy = new Transform({ + objectMode: options.objectMode + }) + + proxy._write = socketWrite + proxy._flush = socketEnd + + return proxy +} + +function WebSocketStream(target, protocols, options) { + var stream, socket + + var isBrowser = process.title === 'browser' + var isNative = !!global.WebSocket + var socketWrite = isBrowser ? socketWriteBrowser : socketWriteNode + + if (protocols && !Array.isArray(protocols) && 'object' === typeof protocols) { + // accept the "options" Object as the 2nd argument + options = protocols + protocols = null + + if (typeof options.protocol === 'string' || Array.isArray(options.protocol)) { + protocols = options.protocol; + } + } + + if (!options) options = {} + + if (options.objectMode === undefined) { + options.objectMode = !(options.binary === true || options.binary === undefined) + } + + var proxy = buildProxy(options, socketWrite, socketEnd) + + if (!options.objectMode) { + proxy._writev = writev + } + + // browser only: sets the maximum socket buffer size before throttling + var bufferSize = options.browserBufferSize || 1024 * 512 + + // browser only: how long to wait when throttling + var bufferTimeout = options.browserBufferTimeout || 1000 + + // use existing WebSocket object that was passed in + if (typeof target === 'object') { + socket = target + // otherwise make a new one + } else { + // special constructor treatment for native websockets in browsers, see + // https://github.com/maxogden/websocket-stream/issues/82 + if (isNative && isBrowser) { + socket = new WS(target, protocols) + } else { + socket = new WS(target, protocols, options) + } + + socket.binaryType = 'arraybuffer' + } + + // was already open when passed in + if (socket.readyState === socket.OPEN) { + stream = proxy + } else { + stream = duplexify.obj() + socket.onopen = onopen + } + + stream.socket = socket + + socket.onclose = onclose + socket.onerror = onerror + socket.onmessage = onmessage + + proxy.on('close', destroy) + + var coerceToBuffer = !options.objectMode + + function socketWriteNode(chunk, enc, next) { + // avoid errors, this never happens unless + // destroy() is called + if (socket.readyState !== socket.OPEN) { + next() + return + } + + if (coerceToBuffer && typeof chunk === 'string') { + chunk = Buffer.from(chunk, 'utf8') + } + socket.send(chunk, next) + } + + function socketWriteBrowser(chunk, enc, next) { + if (socket.bufferedAmount > bufferSize) { + setTimeout(socketWriteBrowser, bufferTimeout, chunk, enc, next) + return + } + + if (coerceToBuffer && typeof chunk === 'string') { + chunk = Buffer.from(chunk, 'utf8') + } + + try { + socket.send(chunk) + } catch(err) { + return next(err) + } + + next() + } + + function socketEnd(done) { + socket.close() + done() + } + + function onopen() { + stream.setReadable(proxy) + stream.setWritable(proxy) + stream.emit('connect') + } + + function onclose() { + stream.end() + stream.destroy() + } + + function onerror(err) { + stream.destroy(err) + } + + function onmessage(event) { + var data = event.data + if (data instanceof ArrayBuffer) data = Buffer.from(data) + else data = Buffer.from(data, 'utf8') + proxy.push(data) + } + + function destroy() { + socket.close() + } + + // this is to be enabled only if objectMode is false + function writev (chunks, cb) { + var buffers = new Array(chunks.length) + for (var i = 0; i < chunks.length; i++) { + if (typeof chunks[i].chunk === 'string') { + buffers[i] = Buffer.from(chunks[i], 'utf8') + } else { + buffers[i] = chunks[i].chunk + } + } + + this._write(Buffer.concat(buffers), 'binary', cb) + } + + return stream +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":92,"duplexify":17,"readable-stream":108,"safe-buffer":110,"ws":119}],119:[function(require,module,exports){ + +var ws = null + +if (typeof WebSocket !== 'undefined') { + ws = WebSocket +} else if (typeof MozWebSocket !== 'undefined') { + ws = MozWebSocket +} else if (typeof window !== 'undefined') { + ws = window.WebSocket || window.MozWebSocket +} + +module.exports = ws + +},{}],120:[function(require,module,exports){ +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + +},{}],121:[function(require,module,exports){ +module.exports = extend + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + target[key] = source[key] + } + } + } + + return target +} + +},{}]},{},[9])(9) +}); diff --git a/common/mqttClient.js b/common/mqttClient.js new file mode 100644 index 0000000..31647db --- /dev/null +++ b/common/mqttClient.js @@ -0,0 +1,40 @@ +import crypto from 'crypto' +import mqtt from './mqtt' + +const host = '39.98.253.192' +const url = `wx://${host}/mqtt` + +export function getMQTTClient(productId, deviceName, deviceSecret) { + const clientId = 'iotx_admin_' + Math.random().toString(16).substr(2, 8) + const content = productId + deviceName + clientId + const hmac = crypto.createHmac('md5', deviceSecret) + const up = hmac.update(content) + const sign = up.digest('hex') + const options = { + keepalive: 200, + clean: true, + reconnectPeriod: 5000, + connectTimeout: 5000, + clientId: clientId, + username: `${deviceName}&${productId}`, + password: sign + } + const client = mqtt.connect(url, options) + client.on('error', (e) => { + console.log(e) + client.end() + }) + let reconnectCount = 1 + client.on('reconnect', () => { + console.log(clientId + ' reconnect ' + reconnectCount + ' times') + reconnectCount++ + if (reconnectCount > 3) { + client.end() + console.log(clientId + ' reconnect failed') + } + }) + client.on('close', () => { + console.log(clientId + ' disconnected') + }) + return client +} diff --git a/common/qiun.css b/common/qiun.css new file mode 100644 index 0000000..9dde573 --- /dev/null +++ b/common/qiun.css @@ -0,0 +1,114 @@ +page { + background: #F4F5F6; + width: 750upx; + overflow-x: hidden; +} + +.qiun-padding { + padding: 2%; + width: 96%; +} + +.qiun-wrap { + display: flex; + flex-wrap: wrap; +} + +.qiun-rows { + display: flex; + flex-direction: row !important; +} + +.qiun-columns { + display: flex; + flex-direction: column !important; +} + +.qiun-common-mt { + margin-top: 10upx; +} + +.qiun-common-border-bottom { + border-bottom: 1px solid #E9E9E9; +} + +.qiun-bg-white { + background: #FFFFFF; +} + +.qiun-title-bar { + width: 96%; + padding: 10upx 2%; + flex-wrap: nowrap; +} + +.qiun-title-dot-light { + border-left: 10upx solid #0ea391; + padding-left: 10upx; + font-size: 32upx; + color: #000000 +} + +.qiun-textarea { + height: 400upx; + font-size: 34upx; + box-sizing: border-box; + line-height: 50upx; + width: 100%; + background-color: #FFFFFF; +} + +.qiun-text-tips { + font-size: 28upx; + color: #dc2626; + line-height: 40upx; + padding: 6upx; +} + +.qiun-button { + background: #2fc25b; + color: #FFFFFF; + margin: 20upx; +} + +/* 通用样式 */ +.qiun-charts { + width: 750upx; + height: 500upx; + background-color: #FFFFFF; +} + +.charts { + width: 750upx; + height: 500upx; + background-color: #FFFFFF; +} + +/* 横屏样式 */ +.qiun-charts-rotate { + width: 700upx; + height: 1100upx; + background-color: #FFFFFF; + padding: 25upx; +} + +.charts-rotate { + width: 700upx; + height: 1100upx; + background-color: #FFFFFF; +} + +/* 圆弧进度样式 */ +.qiun-charts3 { + width: 750upx; + height: 250upx; + background-color: #FFFFFF; + position: relative; +} + +.charts3 { + position: absolute; + width: 250upx; + height: 250upx; + background-color: #FFFFFF; +} diff --git a/common/request.js b/common/request.js new file mode 100644 index 0000000..5ad9cde --- /dev/null +++ b/common/request.js @@ -0,0 +1,42 @@ +import Request from '@/js_sdk/luch-request/request' +import store from '@/store' +import { getToken } from '@/common/auth' + +const http = new Request(); + +http.setConfig((config) => { /* 设置全局配置 */ + config.baseUrl = 'http://39.98.253.192/api'; /* 根域名不同 */ + return config; +}) + +http.interceptor.request((config, cancel) => { /* 请求之前拦截器 */ + if (store.getters.token) { + config.header['token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + } + return config; +}) + +http.interceptor.response((response) => { /* 请求之后拦截器 */ + const res = response.data + if (res.code !== 0) { + uni.showToast({title: res.msg, duration:2000}); + + // 10001 无效的token或者token已过期 + if (res.code === 10001) { + uni.showModal({ + title: '重新登录', + content: 'token已经过期,需重新登录', + success: function (res) { + store.dispatch('FedLogOut').then(() => { + location.reload() // 为了重新实例化vue-router对象 避免bug + }) + } + }); + } + return Promise.reject('error') + } else { + return response.data + } +}) + +export default http; \ No newline at end of file diff --git a/common/uni.css b/common/uni.css new file mode 100644 index 0000000..263225c --- /dev/null +++ b/common/uni.css @@ -0,0 +1,1447 @@ +@font-face { + font-family: uniicons; + font-weight: normal; + font-style: normal; + src: url('https://img-cdn-qiniu.dcloud.net.cn/fonts/uni.ttf') format('truetype'); +} + +/*通用 */ +view{ + font-size:28upx; + line-height:1.8; +} +progress, checkbox-group{ + width: 100%; +} +form { + width: 100%; +} +.uni-flex { + display: flex; + flex-direction: row; +} +.uni-flex-item { + flex: 1; +} +.uni-row { + flex-direction: row; +} +.uni-column { + flex-direction: column; +} +.uni-link{ + color:#576B95; + font-size:26upx; +} +.uni-center{ + text-align:center; +} +.uni-inline-item{ + display: flex; + flex-direction: row; + align-items:center; +} +.uni-inline-item text{ + margin-right: 20upx; +} +.uni-inline-item text:last-child{ + margin-right: 0upx; + margin-left: 20upx; +} + +/* page */ +.uni-page-head{ + padding:35upx; + text-align: center; +} +.uni-page-head-title { + display: inline-block; + padding: 0 40upx; + font-size: 30upx; + height: 88upx; + line-height: 88upx; + color: #BEBEBE; + box-sizing: border-box; + border-bottom: 2upx solid #D8D8D8; +} +.uni-page-body { + width: 100%; + flex-grow: 1; + overflow-x: hidden; +} +.uni-padding-wrap{ + width:690upx; + padding:0 30upx; +} +.uni-word { + text-align: center; + padding:200upx 100upx; +} +.uni-title { + font-size:30upx; + font-weight:500; + padding:20upx 0; + line-height:1.5; +} +.uni-text{ + font-size:28upx; +} +.uni-title text{ + font-size:24upx; + color:#888; +} + +.uni-text-gray{ + color: #ccc; +} +.uni-text-small { + font-size:24upx; +} +.uni-common-mb{ + margin-bottom:30upx; +} +.uni-common-pb{ + padding-bottom:30upx; +} +.uni-common-pl{ + padding-left:30upx; +} +.uni-common-mt{ + margin-top:30upx; +} +/* 背景色 */ +.uni-bg-red{ + background:#F76260; color:#FFF; +} +.uni-bg-green{ + background:#09BB07; color:#FFF; +} +.uni-bg-blue{ + background:#007AFF; color:#FFF; +} +/* 标题 */ +.uni-h1 {font-size: 80upx; font-weight:700;} +.uni-h2 {font-size: 60upx; font-weight:700;} +.uni-h3 {font-size: 48upx; font-weight:700;} +.uni-h4 {font-size: 36upx; font-weight:700;} +.uni-h5 {font-size: 28upx; color: #8f8f94;} +.uni-h6 {font-size: 24upx; color: #8f8f94;} +.uni-bold{font-weight:bold;} + +/* 文本溢出隐藏 */ +.uni-ellipsis {overflow: hidden; white-space: nowrap; text-overflow: ellipsis;} + +/* 竖向百分百按钮 */ +.uni-btn-v{ + padding:10upx 0; +} +.uni-btn-v button{margin:20upx 0;} + +/* 表单 */ +.uni-form-item{ + display:flex; + width:100%; + padding:10upx 0; +} +.uni-form-item .title{ + padding:10upx 25upx; +} +.uni-label { + width: 210upx; + word-wrap: break-word; + word-break: break-all; + text-indent:20upx; +} +.uni-input { + height: 50upx; + padding: 15upx 25upx; + line-height:50upx; + font-size:28upx; + background:#FFF; + flex: 1; +} +radio-group, checkbox-group{ + width:100%; +} +radio-group label, checkbox-group label{ + padding-right:20upx; +} +.uni-form-item .with-fun{ + display:flex; + flex-wrap:nowrap; + background:#FFFFFF; +} +.uni-form-item .with-fun .uni-icon{ + width:40px; + height:80upx; + line-height:80upx; + flex-shrink:0; +} + +/* loadmore */ +.uni-loadmore{ + height:80upx; + line-height:80upx; + text-align:center; + padding-bottom:30upx; +} +/*数字角标*/ +.uni-badge, +.uni-badge-default { + font-family: 'Helvetica Neue', Helvetica, sans-serif; + font-size: 12px; + line-height: 1; + display: inline-block; + padding: 3px 6px; + color: #333; + border-radius: 100px; + background-color: rgba(0, 0, 0, .15); +} +.uni-badge.uni-badge-inverted { + padding: 0 5px 0 0; + color: #929292; + background-color: transparent +} +.uni-badge-primary { + color: #fff; + background-color: #007aff +} +.uni-badge-blue.uni-badge-inverted, +.uni-badge-primary.uni-badge-inverted { + color: #007aff; + background-color: transparent +} +.uni-badge-green, +.uni-badge-success { + color: #fff; + background-color: #4cd964; +} +.uni-badge-green.uni-badge-inverted, +.uni-badge-success.uni-badge-inverted { + color: #4cd964; + background-color: transparent +} +.uni-badge-warning, +.uni-badge-yellow { + color: #fff; + background-color: #f0ad4e +} +.uni-badge-warning.uni-badge-inverted, +.uni-badge-yellow.uni-badge-inverted { + color: #f0ad4e; + background-color: transparent +} +.uni-badge-danger, +.uni-badge-red { + color: #fff; + background-color: #dd524d +} +.uni-badge-danger.uni-badge-inverted, +.uni-badge-red.uni-badge-inverted { + color: #dd524d; + background-color: transparent +} +.uni-badge-purple, +.uni-badge-royal { + color: #fff; + background-color: #8a6de9 +} +.uni-badge-purple.uni-badge-inverted, +.uni-badge-royal.uni-badge-inverted { + color: #8a6de9; + background-color: transparent +} + +/*折叠面板 */ +.uni-collapse-content { + height: 0; + width: 100%; + overflow: hidden; +} +.uni-collapse-content.uni-active { + height: auto; +} + +/*卡片视图 */ +.uni-card { + background: #fff; + border-radius: 8upx; + margin:20upx 0; + position: relative; + box-shadow: 0 2upx 4upx rgba(0, 0, 0, .3); +} +.uni-card-content { + font-size: 30upx; +} +.uni-card-content.image-view{ + width: 100%; + margin: 0; +} +.uni-card-content-inner { + position: relative; + padding: 30upx; +} +.uni-card-footer, +.uni-card-header { + position: relative; + display: flex; + min-height: 50upx; + padding: 20upx 30upx; + justify-content: space-between; + align-items: center; +} +.uni-card-header { + font-size: 36upx; +} +.uni-card-footer { + color: #6d6d72; +} +.uni-card-footer:before, +.uni-card-header:after { + position: absolute; + top: 0; + right: 0; + left: 0; + height: 2upx; + content: ''; + -webkit-transform: scaleY(.5); + transform: scaleY(.5); + background-color: #c8c7cc; +} +.uni-card-header:after { + top: auto; + bottom: 0; +} +.uni-card-media { + justify-content: flex-start; +} +.uni-card-media-logo { + height: 84upx; + width: 84upx; + margin-right: 20upx; +} +.uni-card-media-body { + height: 84upx; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; +} +.uni-card-media-text-top { + line-height: 36upx; + font-size: 34upx; +} +.uni-card-media-text-bottom { + line-height: 30upx; + font-size: 28upx; + color: #8f8f94; +} +.uni-card-link { + color: #007AFF; +} + +/* 列表 */ +.uni-list { + background-color: #FFFFFF; + position: relative; + width: 100%; + display: flex; + flex-direction: column; +} +.uni-list:after { + position: absolute; + z-index: 10; + right: 0; + bottom: 0; + left: 0; + height: 1px; + content: ''; + -webkit-transform: scaleY(.5); + transform: scaleY(.5); + background-color: #c8c7cc; +} +.uni-list::before { + position: absolute; + z-index: 10; + right: 0; + top: 0; + left: 0; + height: 1px; + content: ''; + -webkit-transform: scaleY(.5); + transform: scaleY(.5); + background-color: #c8c7cc; +} +.uni-list-cell { + position: relative; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +} +.uni-list-cell-hover { + background-color: #eee; +} +.uni-list-cell-pd { + padding: 22upx 30upx; +} +.uni-list-cell-left { + font-size:28upx; + padding: 0 30upx; +} +.uni-list-cell-db, +.uni-list-cell-right { + flex: 1; +} +.uni-list-cell::after { + position: absolute; + z-index: 3; + right: 0; + bottom: 0; + left: 30upx; + height: 1px; + content: ''; + -webkit-transform: scaleY(.5); + transform: scaleY(.5); + background-color: #c8c7cc; +} +.uni-list .uni-list-cell:last-child::after { + height: 0upx; +} +.uni-list-cell-last.uni-list-cell::after { + height: 0upx; +} +.uni-list-cell-divider { + position: relative; + display: flex; + color: #999; + background-color: #f7f7f7; + padding:15upx 20upx; +} +.uni-list-cell-divider::before { + position: absolute; + right: 0; + top: 0; + left: 0; + height: 1px; + content: ''; + -webkit-transform: scaleY(.5); + transform: scaleY(.5); + background-color: #c8c7cc; +} +.uni-list-cell-divider::after { + position: absolute; + right: 0; + bottom: 0; + left: 0upx; + height: 1px; + content: ''; + -webkit-transform: scaleY(.5); + transform: scaleY(.5); + background-color: #c8c7cc; +} +.uni-list-cell-navigate { + font-size:30upx; + padding: 22upx 30upx; + line-height: 48upx; + position: relative; + display: flex; + box-sizing: border-box; + width: 100%; + flex: 1; + justify-content: space-between; + align-items: center; +} +.uni-list-cell-navigate { + padding-right: 36upx; +} +.uni-navigate-badge { + padding-right: 50upx; +} +.uni-list-cell-navigate.uni-navigate-right:after { + font-family: uniicons; + content: '\e583'; + position: absolute; + right: 24upx; + top: 50%; + color: #bbb; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} +.uni-list-cell-navigate.uni-navigate-bottom:after { + font-family: uniicons; + content: '\e581'; + position: absolute; + right: 24upx; + top: 50%; + color: #bbb; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} +.uni-list-cell-navigate.uni-navigate-bottom.uni-active::after { + font-family: uniicons; + content: '\e580'; + position: absolute; + right: 24upx; + top: 50%; + color: #bbb; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} +.uni-collapse.uni-list-cell { + flex-direction: column; +} +.uni-list-cell-navigate.uni-active { + background: #eee; +} +.uni-list.uni-collapse { + box-sizing: border-box; + height: 0; + overflow: hidden; +} +.uni-collapse .uni-list-cell { + padding-left: 20upx; +} +.uni-collapse .uni-list-cell::after { + left: 52upx; +} +.uni-list.uni-active { + height: auto; +} + +/* 三行列表 */ +.uni-triplex-row { + display: flex; + flex: 1; + width: 100%; + box-sizing: border-box; + flex-direction: row; + padding: 22upx 30upx; +} +.uni-triplex-right, +.uni-triplex-left { + display: flex; + flex-direction: column; +} +.uni-triplex-left { + width: 84%; +} +.uni-triplex-left .uni-title{ + padding:8upx 0; +} +.uni-triplex-left .uni-text, .uni-triplex-left .uni-text-small{color:#999999;} +.uni-triplex-right { + width: 16%; + text-align: right; +} + +/* 图文列表 */ +.uni-media-list { + padding: 22upx 30upx; + box-sizing: border-box; + display: flex; + width: 100%; + flex-direction: row; +} +.uni-navigate-right.uni-media-list { + padding-right: 74upx; +} +.uni-pull-right { + flex-direction: row-reverse; +} +.uni-pull-right>.uni-media-list-logo { + margin-right: 0upx; + margin-left: 20upx; +} +.uni-media-list-logo { + height: 84upx; + width: 84upx; + margin-right: 20upx; +} +.uni-media-list-logo image { + height: 100%; + width: 100%; +} +.uni-media-list-body { + height: 84upx; + display: flex; + flex: 1; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + overflow: hidden; +} +.uni-media-list-text-top { + width: 100%; + line-height: 36upx; + font-size: 30upx; +} +.uni-media-list-text-bottom { + width: 100%; + line-height: 30upx; + font-size: 26upx; + color: #8f8f94; +} + +/* 九宫格 */ +.uni-grid-9 { + background: #f2f2f2; + width: 750upx; + display: flex; + flex-direction: row; + flex-wrap: wrap; + border-top: 2upx solid #eee; +} +.uni-grid-9-item { + width: 250upx; + height: 200upx; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-bottom: 2upx solid; + border-right: 2upx solid; + border-color: #eee; + box-sizing: border-box; +} +.no-border-right { + border-right: none; +} +.uni-grid-9-image { + width: 100upx; + height: 100upx; +} +.uni-grid-9-text { + width: 250upx; + line-height: 4upx; + height: 40upx; + text-align: center; + font-size: 30upx; +} +.uni-grid-9-item-hover { + background: rgba(0, 0, 0, 0.1); +} + +/* 上传 */ +.uni-uploader { + flex: 1; + flex-direction: column; +} +.uni-uploader-head { + display: flex; + flex-direction: row; + justify-content: space-between; +} +.uni-uploader-info { + color: #B2B2B2; +} +.uni-uploader-body { + margin-top: 16upx; +} +.uni-uploader__files { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} +.uni-uploader__file { + margin: 10upx; + width: 210upx; + height: 210upx; +} +.uni-uploader__img { + display: block; + width: 210upx; + height: 210upx; +} +.uni-uploader__input-box { + position: relative; + margin:10upx; + width: 208upx; + height: 208upx; + border: 2upx solid #D9D9D9; +} +.uni-uploader__input-box:before, +.uni-uploader__input-box:after { + content: " "; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + background-color: #D9D9D9; +} +.uni-uploader__input-box:before { + width: 4upx; + height: 79upx; +} +.uni-uploader__input-box:after { + width: 79upx; + height: 4upx; +} +.uni-uploader__input-box:active { + border-color: #999999; +} +.uni-uploader__input-box:active:before, +.uni-uploader__input-box:active:after { + background-color: #999999; +} +.uni-uploader__input { + position: absolute; + z-index: 1; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0; +} + +/*问题反馈*/ +.feedback-title { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 20upx; + color: #8f8f94; + font-size: 28upx; +} +.feedback-star-view.feedback-title { + justify-content: flex-start; + margin: 0; +} +.feedback-quick { + position: relative; + padding-right: 40upx; +} +.feedback-quick:after { + font-family: uniicons; + font-size: 40upx; + content: '\e581'; + position: absolute; + right: 0; + top: 50%; + color: #bbb; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} +.feedback-body { + background: #fff; +} +.feedback-textare { + height: 200upx; + font-size: 34upx; + line-height: 50upx; + width: 100%; + box-sizing: border-box; + padding: 20upx 30upx 0; +} +.feedback-input { + font-size: 34upx; + height: 50upx; + min-height: 50upx; + padding: 15upx 20upx; + line-height: 50upx; +} +.feedback-uploader { + padding: 22upx 20upx; +} +.feedback-star { + font-family: uniicons; + font-size: 40upx; + margin-left: 6upx; +} +.feedback-star-view { + margin-left: 20upx; +} +.feedback-star:after { + content: '\e408'; +} +.feedback-star.active { + color: #FFB400; +} +.feedback-star.active:after { + content: '\e438'; +} +.feedback-submit { + background: #007AFF; + color: #FFFFFF; + margin: 20upx; +} + +/* input group */ +.uni-input-group { + position: relative; + padding: 0; + border: 0; + background-color: #fff; +} + +.uni-input-group:before { + position: absolute; + top: 0; + right: 0; + left: 0; + height: 2upx; + content: ''; + transform: scaleY(.5); + background-color: #c8c7cc; +} + +.uni-input-group:after { + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 2upx; + content: ''; + transform: scaleY(.5); + background-color: #c8c7cc; +} + +.uni-input-row { + position: relative; + display: flex; + flex-direction: row; + font-size:28upx; + padding: 22upx 30upx; + justify-content: space-between; +} + +.uni-input-group .uni-input-row:after { + position: absolute; + right: 0; + bottom: 0; + left: 30upx; + height: 2upx; + content: ''; + transform: scaleY(.5); + background-color: #c8c7cc; +} + +.uni-input-row label { + line-height: 70upx; +} + +/* textarea */ +.uni-textarea{ + width:100%; + background:#FFF; +} +.uni-textarea textarea{ + width:96%; + padding:18upx 2%; + line-height:1.6; + font-size:28upx; + height:150upx; +} + +/* tab bar */ +.uni-tab-bar { + display: flex; + flex: 1; + flex-direction: column; + overflow: hidden; + height: 100%; +} + +.uni-tab-bar .list { + width: 750upx; + height: 100%; +} + +.uni-swiper-tab { + width: 100%; + white-space: nowrap; + line-height: 100upx; + height: 100upx; + border-bottom: 1px solid #c8c7cc; +} + +.swiper-tab-list { + font-size: 30upx; + width: 150upx; + display: inline-block; + text-align: center; + color: #555; +} + +.uni-tab-bar .active { + color: #007AFF; +} + +.uni-tab-bar .swiper-box { + flex: 1; + width: 100%; + height: calc(100% - 100upx); +} + +.uni-tab-bar-loading{ + padding:20upx 0; +} + +/* comment */ +.uni-comment{padding:5rpx 0; display: flex; flex-grow:1; flex-direction: column;} +.uni-comment-list{flex-wrap:nowrap; padding:10rpx 0; margin:10rpx 0; width:100%; display: flex;} +.uni-comment-face{width:70upx; height:70upx; border-radius:100%; margin-right:20upx; flex-shrink:0; overflow:hidden;} +.uni-comment-face image{width:100%; border-radius:100%;} +.uni-comment-body{width:100%;} +.uni-comment-top{line-height:1.5em; justify-content:space-between;} +.uni-comment-top text{color:#0A98D5; font-size:24upx;} +.uni-comment-date{line-height:38upx; flex-direction:row; justify-content:space-between; display:flex !important; flex-grow:1;} +.uni-comment-date view{color:#666666; font-size:24upx; line-height:38upx;} +.uni-comment-content{line-height:1.6em; font-size:28upx; padding:8rpx 0;} +.uni-comment-replay-btn{background:#FFF; font-size:24upx; line-height:28upx; padding:5rpx 20upx; border-radius:30upx; color:#333 !important; margin:0 10upx;} + +/* swiper msg */ +.uni-swiper-msg{width:100%; padding:12rpx 0; flex-wrap:nowrap; display:flex;} +.uni-swiper-msg-icon{width:50upx; margin-right:20upx;} +.uni-swiper-msg-icon image{width:100%; flex-shrink:0;} +.uni-swiper-msg swiper{width:100%; height:50upx;} +.uni-swiper-msg swiper-item{line-height:50upx;} + +/* product */ +.uni-product-list { + display: flex; + width: 100%; + flex-wrap: wrap; + flex-direction: row; +} + +.uni-product { + padding: 20upx; + display: flex; + flex-direction: column; +} + +.image-view { + height: 330upx; + width: 330upx; + margin:12upx 0; +} + +.uni-product-image { + height: 330upx; + width: 330upx; +} + +.uni-product-title { + width: 300upx; + word-break: break-all; + display: -webkit-box; + overflow: hidden; + line-height:1.5; + text-overflow: ellipsis; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; +} + +.uni-product-price { + margin-top:10upx; + font-size: 28upx; + line-height:1.5; + position: relative; +} + +.uni-product-price-original { + color: #e80080; +} + +.uni-product-price-favour { + color: #888888; + text-decoration: line-through; + margin-left: 10upx; +} + +.uni-product-tip { + position: absolute; + right: 10upx; + background-color: #ff3333; + color: #ffffff; + padding: 0 10upx; + border-radius: 5upx; +} + +/* timeline */ +.uni-timeline { + margin: 35upx 0; + display: flex; + flex-direction: column; + position: relative; + } + + + .uni-timeline-item { + display: flex; + flex-direction: row; + position: relative; + padding-bottom: 20upx; + box-sizing: border-box; + overflow: hidden; + + } + + .uni-timeline-item .uni-timeline-item-keynode { + width: 160upx; + flex-shrink: 0; + box-sizing: border-box; + padding-right: 20upx; + text-align: right; + line-height: 65upx; + } + + .uni-timeline-item .uni-timeline-item-divider { + flex-shrink: 0; + position: relative; + width: 30upx; + height: 30upx; + top: 15upx; + border-radius: 50%; + background-color: #bbb; + } + + + + .uni-timeline-item-divider::before, + .uni-timeline-item-divider::after { + position: absolute; + left: 15upx; + width: 1upx; + height: 100vh; + content: ''; + background: inherit; + } + + .uni-timeline-item-divider::before { + bottom: 100%; + } + + .uni-timeline-item-divider::after { + top: 100%; + } + + + .uni-timeline-last-item .uni-timeline-item-divider:after { + display: none; + } + + .uni-timeline-first-item .uni-timeline-item-divider:before { + display: none; + } + + .uni-timeline-item .uni-timeline-item-content { + padding-left: 20upx; + } + + .uni-timeline-last-item .bottom-border::after{ + display: none; + } + + .uni-timeline-item-content .datetime{ + color: #CCCCCC; + } + + /* 自定义节点颜色 */ + .uni-timeline-last-item .uni-timeline-item-divider{ + background-color: #1AAD19; + } + + +/* uni-icon */ + +.uni-icon { + font-family: uniicons; + font-size: 24px; + font-weight: normal; + font-style: normal; + line-height: 1; + display: inline-block; + text-decoration: none; + -webkit-font-smoothing: antialiased; +} + +.uni-icon.uni-active { + color: #007aff; +} + +.uni-icon-contact:before { + content: '\e100'; +} + +.uni-icon-person:before { + content: '\e101'; +} + +.uni-icon-personadd:before { + content: '\e102'; +} + +.uni-icon-contact-filled:before { + content: '\e130'; +} + +.uni-icon-person-filled:before { + content: '\e131'; +} + +.uni-icon-personadd-filled:before { + content: '\e132'; +} + +.uni-icon-phone:before { + content: '\e200'; +} + +.uni-icon-email:before { + content: '\e201'; +} + +.uni-icon-chatbubble:before { + content: '\e202'; +} + +.uni-icon-chatboxes:before { + content: '\e203'; +} + +.uni-icon-phone-filled:before { + content: '\e230'; +} + +.uni-icon-email-filled:before { + content: '\e231'; +} + +.uni-icon-chatbubble-filled:before { + content: '\e232'; +} + +.uni-icon-chatboxes-filled:before { + content: '\e233'; +} + +.uni-icon-weibo:before { + content: '\e260'; +} + +.uni-icon-weixin:before { + content: '\e261'; +} + +.uni-icon-pengyouquan:before { + content: '\e262'; +} + +.uni-icon-chat:before { + content: '\e263'; +} + +.uni-icon-qq:before { + content: '\e264'; +} + +.uni-icon-videocam:before { + content: '\e300'; +} + +.uni-icon-camera:before { + content: '\e301'; +} + +.uni-icon-mic:before { + content: '\e302'; +} + +.uni-icon-location:before { + content: '\e303'; +} + +.uni-icon-mic-filled:before, +.uni-icon-speech:before { + content: '\e332'; +} + +.uni-icon-location-filled:before { + content: '\e333'; +} + +.uni-icon-micoff:before { + content: '\e360'; +} + +.uni-icon-image:before { + content: '\e363'; +} + +.uni-icon-map:before { + content: '\e364'; +} + +.uni-icon-compose:before { + content: '\e400'; +} + +.uni-icon-trash:before { + content: '\e401'; +} + +.uni-icon-upload:before { + content: '\e402'; +} + +.uni-icon-download:before { + content: '\e403'; +} + +.uni-icon-close:before { + content: '\e404'; +} + +.uni-icon-redo:before { + content: '\e405'; +} + +.uni-icon-undo:before { + content: '\e406'; +} + +.uni-icon-refresh:before { + content: '\e407'; +} + +.uni-icon-star:before { + content: '\e408'; +} + +.uni-icon-plus:before { + content: '\e409'; +} + +.uni-icon-minus:before { + content: '\e410'; +} + +.uni-icon-circle:before, +.uni-icon-checkbox:before { + content: '\e411'; +} + +.uni-icon-close-filled:before, +.uni-icon-clear:before { + content: '\e434'; +} + +.uni-icon-refresh-filled:before { + content: '\e437'; +} + +.uni-icon-star-filled:before { + content: '\e438'; +} + +.uni-icon-plus-filled:before { + content: '\e439'; +} + +.uni-icon-minus-filled:before { + content: '\e440'; +} + +.uni-icon-circle-filled:before { + content: '\e441'; +} + +.uni-icon-checkbox-filled:before { + content: '\e442'; +} + +.uni-icon-closeempty:before { + content: '\e460'; +} + +.uni-icon-refreshempty:before { + content: '\e461'; +} + +.uni-icon-reload:before { + content: '\e462'; +} + +.uni-icon-starhalf:before { + content: '\e463'; +} + +.uni-icon-spinner:before { + content: '\e464'; +} + +.uni-icon-spinner-cycle:before { + content: '\e465'; +} + +.uni-icon-search:before { + content: '\e466'; +} + +.uni-icon-plusempty:before { + content: '\e468'; +} + +.uni-icon-forward:before { + content: '\e470'; +} + +.uni-icon-back:before, +.uni-icon-left-nav:before { + content: '\e471'; +} + +.uni-icon-checkmarkempty:before { + content: '\e472'; +} + +.uni-icon-home:before { + content: '\e500'; +} + +.uni-icon-navigate:before { + content: '\e501'; +} + +.uni-icon-gear:before { + content: '\e502'; +} + +.uni-icon-paperplane:before { + content: '\e503'; +} + +.uni-icon-info:before { + content: '\e504'; +} + +.uni-icon-help:before { + content: '\e505'; +} + +.uni-icon-locked:before { + content: '\e506'; +} + +.uni-icon-more:before { + content: '\e507'; +} + +.uni-icon-flag:before { + content: '\e508'; +} + +.uni-icon-home-filled:before { + content: '\e530'; +} + +.uni-icon-gear-filled:before { + content: '\e532'; +} + +.uni-icon-info-filled:before { + content: '\e534'; +} + +.uni-icon-help-filled:before { + content: '\e535'; +} + +.uni-icon-more-filled:before { + content: '\e537'; +} + +.uni-icon-settings:before { + content: '\e560'; +} + +.uni-icon-list:before { + content: '\e562'; +} + +.uni-icon-bars:before { + content: '\e563'; +} + +.uni-icon-loop:before { + content: '\e565'; +} + +.uni-icon-paperclip:before { + content: '\e567'; +} + +.uni-icon-eye:before { + content: '\e568'; +} + +.uni-icon-arrowup:before { + content: '\e580'; +} + +.uni-icon-arrowdown:before { + content: '\e581'; +} + +.uni-icon-arrowleft:before { + content: '\e582'; +} + +.uni-icon-arrowright:before { + content: '\e583'; +} + +.uni-icon-arrowthinup:before { + content: '\e584'; +} + +.uni-icon-arrowthindown:before { + content: '\e585'; +} + +.uni-icon-arrowthinleft:before { + content: '\e586'; +} + +.uni-icon-arrowthinright:before { + content: '\e587'; +} + +.uni-icon-pulldown:before { + content: '\e588'; +} + +.uni-icon-scan:before { + content: "\e612"; +} + +/* 分界线 */ +.uni-divider{ + height: 110upx; + display: flex; + align-items:center; + justify-content: center; + position: relative; +} +.uni-divider__content{ + font-size: 28upx; + color: #999; + padding: 0 20upx; + position: relative; + z-index: 101; + background: #F4F5F6; +} +.uni-divider__line{ + background-color: #CCCCCC; + height: 1px; + width: 100%; + position: absolute; + z-index: 100; + top: 50%; + left: 0; + transform: translateY(50%); +} \ No newline at end of file diff --git a/components/mehaotian-search/.DS_Store b/components/mehaotian-search/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + + + + + + + + + 搜索 + + + {{ !show ? searchName : '搜索' }} + + + + + + + diff --git a/components/refresh/refresh.vue b/components/refresh/refresh.vue new file mode 100644 index 0000000..b3fca5e --- /dev/null +++ b/components/refresh/refresh.vue @@ -0,0 +1,174 @@ + + + + + diff --git a/components/uni-badge/readme.md b/components/uni-badge/readme.md new file mode 100644 index 0000000..fe38729 --- /dev/null +++ b/components/uni-badge/readme.md @@ -0,0 +1,34 @@ +### Badge 数字角标 + +数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,组件名:``uni-badge``,代码块: uBadge。 + +**使用方式:** + +在 ``script`` 中引用组件 + +```javascript +import uniBadge from "@/components/uni-badge/uni-badge.vue" +export default { + components: {uniBadge} +} +``` + +在 ``template`` 中使用组件 + +```html + + + +``` + +实际效果参考:[https://github.com/dcloudio/uni-ui](https://github.com/dcloudio/uni-ui) + +**Badge 属性说明:** + +|属性名 |类型 |默认值 |说明 | +|--- |---- |--- |--- | +|text |String |- |角标内容 | +|type |String |default|颜色类型,可选值:default(灰色)、primary(蓝色)、success(绿色)、warning(黄色)、error(红色) | +|size |String |normal|Badge 大小,可取值:normal、small| +|inverted |Boolean |false |是否无需背景颜色,为 true 时,背景颜色将变为文字的字体颜色 | +|@click |EventHandle| - |点击 Badge 触发事件 | diff --git a/components/uni-badge/uni-badge.vue b/components/uni-badge/uni-badge.vue new file mode 100644 index 0000000..4930668 --- /dev/null +++ b/components/uni-badge/uni-badge.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/components/uni-fab/uni-fab.vue b/components/uni-fab/uni-fab.vue new file mode 100644 index 0000000..b266885 --- /dev/null +++ b/components/uni-fab/uni-fab.vue @@ -0,0 +1,368 @@ + + + + + diff --git a/components/uni-icon/readme.md b/components/uni-icon/readme.md new file mode 100644 index 0000000..782d3a5 --- /dev/null +++ b/components/uni-icon/readme.md @@ -0,0 +1,35 @@ +### Icon 图标 + +用于展示 icon,组件名:``uni-icon``,代码块: uIcon。 + +**使用方式:** + +在 ``script`` 中引用组件 + +```javascript +import uniIcon from "@/components/uni-icon/uni-icon.vue" +export default { + components: {uniIcon} +} +``` + +在 ``template`` 中使用组件 + +```html + +``` + +实际效果参考:[https://github.com/dcloudio/uni-ui](https://github.com/dcloudio/uni-ui) + +**Icon 属性说明:** + +|属性名 |类型|默认值 |说明| +|---|----|---|---| +|type |String |-|图标图案,参考下表| +|color |String |-|图标颜色 | +|size |Number |24|图标大小| +|@click |EventHandle|-|点击 Icon 触发事件| + +**type 类型:** + +![icon](https://img-cdn-qiniu.dcloud.net.cn/img/icon.png) \ No newline at end of file diff --git a/components/uni-icon/uni-icon.vue b/components/uni-icon/uni-icon.vue new file mode 100644 index 0000000..53883c4 --- /dev/null +++ b/components/uni-icon/uni-icon.vue @@ -0,0 +1,421 @@ + + + + + diff --git a/components/uni-list-item/uni-list-item.vue b/components/uni-list-item/uni-list-item.vue new file mode 100644 index 0000000..4999ec6 --- /dev/null +++ b/components/uni-list-item/uni-list-item.vue @@ -0,0 +1,196 @@ + + + + + \ No newline at end of file diff --git a/components/uni-list/readme.md b/components/uni-list/readme.md new file mode 100644 index 0000000..93982b0 --- /dev/null +++ b/components/uni-list/readme.md @@ -0,0 +1,88 @@ +### List 列表 + +列表组件,组件名:``uni-list``、``uni-list-item``,代码块: uList。 + +**使用方式:** + +在 ``script`` 中引用组件 + +```javascript +import uniList from '@/components/uni-list/uni-list.vue' +import uniListItem from '@/components/uni-list-item/uni-list-item.vue' +export default { + components: {uniList,uniListItem} +} +``` + +List 一般用法 + +```html + + + + + + +``` + +带描述信息 + +```html + + + + +``` + +包含图片 + +```html + + + +``` + +包含图标 + +```html + + + + +``` + +显示Switch + +```html + + + +``` + +实际效果参考:[https://github.com/dcloudio/uni-ui](https://github.com/dcloudio/uni-ui) + +**uniListItem 属性说明:** + +|属性名|类型|默认值 |说明| +|---|----|---|---| +|title|String|-|标题| +|note|String|-|描述| +|disabled|Boolean|false|是否禁用| +|show-arrow|Boolean|true|是否显示箭头图标| +|show-badge|Boolean|false|是否显示数字角标| +|badge-text|String|-|数字角标内容| +|badge-type|String|-|数字角标类型,参考[Badge 数字角标](https://ext.dcloud.net.cn/plugin?id=21)| +|show-switch|Boolean|false|是否显示Switch| +|switch-checked|Boolean|false|Switch是否被选中| +|show-extra-icon|Boolean|false|左侧是否显示扩展图标| +|extra-icon|Object|-|扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [Iocn 图标](https://ext.dcloud.net.cn/plugin?id=28)| +|thumb|String|-|左侧缩略图,若thumb有值,则不会显示扩展图标| + +**uniListItem 事件说明:** + +|事件称名|说明|返回参数| +|---|----|---| +|click|点击 uniListItem 触发事件|-| +|switchChange|点击切换 Switch 时触发|{value:checked}| diff --git a/components/uni-list/uni-list.vue b/components/uni-list/uni-list.vue new file mode 100644 index 0000000..ff23db2 --- /dev/null +++ b/components/uni-list/uni-list.vue @@ -0,0 +1,45 @@ + + + diff --git a/components/uni-nav-bar/uni-nav-bar.vue b/components/uni-nav-bar/uni-nav-bar.vue new file mode 100644 index 0000000..e5b367e --- /dev/null +++ b/components/uni-nav-bar/uni-nav-bar.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/components/uni-segmented-control/uni-segmented-control.vue b/components/uni-segmented-control/uni-segmented-control.vue new file mode 100644 index 0000000..0ccd91f --- /dev/null +++ b/components/uni-segmented-control/uni-segmented-control.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/components/uni-status-bar/uni-status-bar.vue b/components/uni-status-bar/uni-status-bar.vue new file mode 100644 index 0000000..ebda226 --- /dev/null +++ b/components/uni-status-bar/uni-status-bar.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/components/wuc-tab/wuc-tab.vue b/components/wuc-tab/wuc-tab.vue new file mode 100644 index 0000000..ac3a8fe --- /dev/null +++ b/components/wuc-tab/wuc-tab.vue @@ -0,0 +1,133 @@ + + + diff --git a/js_sdk/luch-request/index.js b/js_sdk/luch-request/index.js new file mode 100644 index 0000000..b137fa1 --- /dev/null +++ b/js_sdk/luch-request/index.js @@ -0,0 +1,57 @@ +import Request from './request' +const test = new Request(); +test.setConfig((config) => { /* 设置全局配置 */ + config.baseUrl = 'http://www.aaa.cn'; + config.header = { + a: 1, + b: 2 + } + return config +}) +test.interceptor.request((config, cancel) => { /* 请求之前拦截器 */ + config.header = { + ...config.header, + a: 1 + } + /* + if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行 + cancel('token 不存在') // 接收一个参数,会传给catch((err) => {}) err.errMsg === 'token 不存在' + } + */ + return config; +}) +test.interceptor.response((response) => { /* 请求之后拦截器 */ + return response; +}) + +const http = new Request(); +http.setConfig((config) => { /* 设置全局配置 */ + config.baseUrl = 'http://www.bbb.cn'; /* 根域名不同 */ + config.header = { + a: 1, + b: 2 + } + return config +}) +http.interceptor.request((config, cancel) => { /* 请求之前拦截器 */ + config.header = { + ...config.header, + b: 1 + } + /* + if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行 + cancel('token 不存在') // 接收一个参数,会传给catch((err) => {}) err.errMsg === 'token 不存在' + } + */ + return config; +}) +http.interceptor.response((response) => { /* 请求之后拦截器 */ + console.log(response); + return response; +}) +export { + http, + test +}; + + diff --git a/js_sdk/luch-request/readme.md b/js_sdk/luch-request/readme.md new file mode 100644 index 0000000..0d2b72c --- /dev/null +++ b/js_sdk/luch-request/readme.md @@ -0,0 +1,148 @@ +**插件使用说明** + +- 基于 Promise 对象实现更简单的 request 使用方式,支持请求和响应拦截 +- 支持全局挂载 +- 支持多个全局配置实例 +- 支持typescript、javascript 版本(如果不使用ts版本,则可以把luch-request-ts 文件夹删除) +- 下载后把 http-request 文件夹放到项目 utils/ 目录下 + + +**Example** +--- +创建实例 + +``` javascript +const http = new Request(); +``` + +执行` GET `请求 + +``` javascript +http.get('/user/login', {userName: 'name', password: '123456'}).then(res => { + +}).catch(err => { + +}) +// 局部修改配置,局部配置优先级高于全局配置 +http.get('/user/login', {userName: 'name', password: '123456'}, { + header: {}, /* 会覆盖全局header */ + dataType: 'json', + responseType: 'text' +}).then(res => { + +}).catch(err => { + +}) +``` +执行` POST `请求 + +``` javascript +http.post('/user/login', {userName: 'name', password: '123456'} ).then(res => { + +}).catch(err => { + +}) +// 局部修改配置,局部配置优先级高于全局配置 +http.post('/user/login', {userName: 'name', password: '123456'}, { + header: {}, /* 会覆盖全局header */ + dataType: 'json', + responseType: 'text' +}).then(res => { + +}).catch(err => { + +}) +``` + +**全局请求配置** +-- +``` javascript +{ + baseUrl: '', /* 全局根路径,需要注意,如果请求的路径为绝对路径,则不会应用baseUrl */ + header: { + 'Content-Type': 'application/json;charset=UTF-8' + }, + method: 'GET', + dataType: 'json', + responseType: 'text' +} +``` + + +全局配置修改` setConfig ` + +``` javascript +/** + * @description 修改全局默认配置 + * @param {Function} +*/ +http.setConfig((config) => { /* config 为默认全局配置*/ + config.baseUrl = 'http://www.bbb.cn'; /* 根域名 */ + config.header = { + a: 1, + b: 2 + } + return config +}) +``` + +**拦截器** +-- + +在请求之前拦截 + +``` javascript +/** + * @param { Function} cancel - 取消请求,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行 + * + * @param {String} text ['handle cancel'| any] - catch((err) => {}) err.errMsg === 'handle cancel'。非必传,默认'handle cancel' + * @cancel {Object} config - catch((err) => {}) err.config === config; 非必传,默认为request拦截器修改之前的config + * function cancel(text, config) {} + */ +http.interceptor.request((config, cancel) => { /* cancel 为函数,如果调用会取消本次请求。需要注意:调用cancel,本次请求的catch仍会执行。必须return config */ + config.header = { + ...config.header, + a: 1 + } + /* + if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行 + cancel('token 不存在', config) // 把修改后的config传入,之后响应就可以拿到修改后的config。 如果调用了cancel但是不传修改后的config,则catch((err) => {}) err.config 为request拦截器修改之前的config + } + */ + return config; +}) +``` + +在请求之后拦截 + +``` javascript +http.interceptor.response((response) => { /* 必须return response*/ + console.log(response); + return response; +}) +``` + +**typescript使用** +-- +在` request.ts `里还暴露了五个接口 +```javascript +{ + options, // request 方法配置参数 + handleOptions, // get/post 方法配置参数 + config, // init 全局config接口(setConfig 参数接口) + requestConfig, // 请求之前参数配置项 + response // 响应体 +} +``` + + +**issue** +-- +有任何问题或者建议可以=> issue提交,先给个五星好评QAQ!! + + +**作者想说** +-- +- 主体代码3kb +- 目前该插件已经上项目,遇到任何问题请先检查自己的代码(排除新版本发布的情况)。最近新上了` typescript ` 版本,因为本人没使用过ts,所以写的不好的地方,还请见谅~ +####创作不易,五星好评你懂得! diff --git a/js_sdk/luch-request/request.js b/js_sdk/luch-request/request.js new file mode 100644 index 0000000..e498a9e --- /dev/null +++ b/js_sdk/luch-request/request.js @@ -0,0 +1,111 @@ +/** + * Request 0.0.8 + * @Class uni-app request网络请求库 + * @Author lu-ch + * @Date 2019-07-25 + * @Email webwork.s@qq.com + * http://ext.dcloud.net.cn/plugin?id=392 + * **/ +export default class Request { + config = { + baseUrl: '', + header: { + 'Content-Type': 'application/json;charset=UTF-8' + }, + method: 'GET', + dataType: 'json', + responseType: 'text' + } + + static posUrl (url) { /* 判断url是否为绝对路径 */ + return /(http|https):\/\/([\w.]+\/?)\S*/.test(url) + } + + interceptor = { + request: (f) => { + if (f) { + this.requestBeforeFun = f + } + }, + response: (f) => { + if (f) { + this.requestComFun = f + } + } + } + + static requestBeforeFun (config) { + return config + } + + static requestComFun (response) { + return response + } + + setConfig (f) { + this.config = f(this.config) + } + + request (options = {}) { + options.baseUrl = this.config.baseUrl + options.dataType = options.dataType || this.config.dataType + options.responseType = options.responseType || this.config.responseType + options.url = Request.posUrl(options.url) ? options.url : (options.baseUrl + options.url) + options.data = options.data || {} + options.header = options.header || this.config.header + options.method = options.method || this.config.method + return new Promise((resolve, reject) => { + let next = true + let _config = null + options.complete = (response) => { + let statusCode = response.statusCode + response.config = _config + response = this.requestComFun(response) + if (statusCode === 200) { // 成功 + resolve(response) + } else { + reject(response) + } + } + let cancel = (t = 'handle cancel', config = options) => { + let err = { + errMsg: t, + config: config + } + reject(err) + next = false + } + + _config = { ...this.requestBeforeFun(options, cancel) } + if (!next) return + uni.request(_config) + }) + } + + get (url, data, options = {}) { + return this.request({ + url, + data, + method: 'GET', + ...options + }) + } + + post (url, data, options = {}) { + return this.request({ + url, + data, + method: 'POST', + ...options + }) + } + + del (url, data, options = {}) { + return this.request({ + url, + data, + method: 'DELETE', + ...options + }) + } +} diff --git a/js_sdk/u-charts/u-charts/component.vue b/js_sdk/u-charts/u-charts/component.vue new file mode 100644 index 0000000..413c360 --- /dev/null +++ b/js_sdk/u-charts/u-charts/component.vue @@ -0,0 +1,165 @@ + + + + + diff --git a/js_sdk/u-charts/u-charts/u-charts.js b/js_sdk/u-charts/u-charts/u-charts.js new file mode 100644 index 0000000..f620383 --- /dev/null +++ b/js_sdk/u-charts/u-charts/u-charts.js @@ -0,0 +1,4383 @@ +/* + * uCharts v1.8.1.20190727 + * uni-app平台高性能跨全端图表,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360) + * Copyright (c) 2019 QIUN秋云 https://www.ucharts.cn All rights reserved. + * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) + * + * uCharts官方网站 + * https://www.uCharts.cn + * + * 开源地址: + * https://gitee.com/uCharts/uCharts + * + * uni-app插件市场地址: + * http://ext.dcloud.net.cn/plugin?id=271 + * + */ + +'use strict'; + +var config = { + yAxisWidth: 15, + yAxisSplit: 5, + xAxisHeight: 15, + xAxisLineHeight: 15, + legendHeight: 15, + yAxisTitleWidth: 15, + padding: [10, 10, 10, 10], + pixelRatio: 1, + rotate: false, + columePadding: 3, + fontSize: 13, + //dataPointShape: ['diamond', 'circle', 'triangle', 'rect'], + dataPointShape: ['circle', 'circle', 'circle', 'circle'], + colors: ['#1890ff', '#2fc25b', '#facc14', '#f04864', '#8543e0', '#90ed7d'], + pieChartLinePadding: 15, + pieChartTextPadding: 5, + xAxisTextPadding: 3, + titleColor: '#333333', + titleFontSize: 20, + subtitleColor: '#999999', + subtitleFontSize: 15, + toolTipPadding: 3, + toolTipBackground: '#000000', + toolTipOpacity: 0.7, + toolTipLineHeight: 20, + radarGridCount: 3, + radarLabelTextMargin: 15, + gaugeLabelTextMargin: 15 +}; + +let assign; +if (Object.assign) { + assign = Object.assign; +} else { + // 使用polyfill + assign = function(target, varArgs) { + if (target == null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + var to = Object(target); + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + if (nextSource != null) { + for (var nextKey in nextSource) { + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + } +} + +var util = { + toFixed: function toFixed(num, limit) { + limit = limit || 2; + if (this.isFloat(num)) { + num = num.toFixed(limit); + } + return num; + }, + isFloat: function isFloat(num) { + return num % 1 !== 0; + }, + approximatelyEqual: function approximatelyEqual(num1, num2) { + return Math.abs(num1 - num2) < 1e-10; + }, + isSameSign: function isSameSign(num1, num2) { + return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2; + }, + isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) { + return this.isSameSign(p1.x, p2.x); + }, + isCollision: function isCollision(obj1, obj2) { + obj1.end = {}; + obj1.end.x = obj1.start.x + obj1.width; + obj1.end.y = obj1.start.y - obj1.height; + obj2.end = {}; + obj2.end.x = obj2.start.x + obj2.width; + obj2.end.y = obj2.start.y - obj2.height; + var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y; + return !flag; + } +}; + +//兼容H5点击事件 +function getH5Offset(e) { + e.mp = { + changedTouches: [] + }; + e.mp.changedTouches.push({ + x: e.offsetX, + y: e.offsetY + }); + return e; +} + +// hex 转 rgba +function hexToRgb(hexValue, opc) { + var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + var hex = hexValue.replace(rgx, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + var r = parseInt(rgb[1], 16); + var g = parseInt(rgb[2], 16); + var b = parseInt(rgb[3], 16); + return 'rgba(' + r + ',' + g + ',' + b + ',' + opc + ')'; +} + +function findRange(num, type, limit) { + if (isNaN(num)) { + throw new Error('[uCharts] unvalid series data!'); + } + limit = limit || 10; + type = type ? type : 'upper'; + var multiple = 1; + while (limit < 1) { + limit *= 10; + multiple *= 10; + } + if (type === 'upper') { + num = Math.ceil(num * multiple); + } else { + num = Math.floor(num * multiple); + } + while (num % limit !== 0) { + if (type === 'upper') { + num++; + } else { + num--; + } + } + return num / multiple; +} + +function calCandleMA(dayArr, nameArr, colorArr, kdata) { + let seriesTemp = []; + for (let k = 0; k < dayArr.length; k++) { + let seriesItem = { + data: [], + name: nameArr[k], + color: colorArr[k] + }; + for (let i = 0, len = kdata.length; i < len; i++) { + if (i < dayArr[k]) { + seriesItem.data.push(null); + continue; + } + let sum = 0; + for (let j = 0; j < dayArr[k]; j++) { + sum += kdata[i - j][1]; + } + seriesItem.data.push(+(sum / dayArr[k]).toFixed(3)); + } + seriesTemp.push(seriesItem); + } + return seriesTemp; +} + +function calValidDistance(distance, chartData, config, opts) { + var dataChartAreaWidth = opts.width - opts.area[1] - opts.area[3]; + var dataChartWidth = chartData.eachSpacing * opts.categories.length; + var validDistance = distance; + if (distance >= 0) { + validDistance = 0; + } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) { + validDistance = dataChartAreaWidth - dataChartWidth; + } + return validDistance; +} + +function isInAngleRange(angle, startAngle, endAngle) { + function adjust(angle) { + while (angle < 0) { + angle += 2 * Math.PI; + } + while (angle > 2 * Math.PI) { + angle -= 2 * Math.PI; + } + return angle; + } + angle = adjust(angle); + startAngle = adjust(startAngle); + endAngle = adjust(endAngle); + if (startAngle > endAngle) { + endAngle += 2 * Math.PI; + if (angle < startAngle) { + angle += 2 * Math.PI; + } + } + return angle >= startAngle && angle <= endAngle; +} + +function calRotateTranslate(x, y, h) { + var xv = x; + var yv = h - y; + var transX = xv + (h - yv - xv) / Math.sqrt(2); + transX *= -1; + var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2); + return { + transX: transX, + transY: transY + }; +} + +function createCurveControlPoints(points, i) { + + function isNotMiddlePoint(points, i) { + if (points[i - 1] && points[i + 1]) { + return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y, + points[ + i + 1].y); + } else { + return false; + } + } + var a = 0.2; + var b = 0.2; + var pAx = null; + var pAy = null; + var pBx = null; + var pBy = null; + if (i < 1) { + pAx = points[0].x + (points[1].x - points[0].x) * a; + pAy = points[0].y + (points[1].y - points[0].y) * a; + } else { + pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a; + pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a; + } + + if (i > points.length - 3) { + var last = points.length - 1; + pBx = points[last].x - (points[last].x - points[last - 1].x) * b; + pBy = points[last].y - (points[last].y - points[last - 1].y) * b; + } else { + pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b; + pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b; + } + if (isNotMiddlePoint(points, i + 1)) { + pBy = points[i + 1].y; + } + if (isNotMiddlePoint(points, i)) { + pAy = points[i].y; + } + return { + ctrA: { + x: pAx, + y: pAy + }, + ctrB: { + x: pBx, + y: pBy + } + }; +} + +function convertCoordinateOrigin(x, y, center) { + return { + x: center.x + x, + y: center.y - y + }; +} + +function avoidCollision(obj, target) { + if (target) { + // is collision test + while (util.isCollision(obj, target)) { + if (obj.start.x > 0) { + obj.start.y--; + } else if (obj.start.x < 0) { + obj.start.y++; + } else { + if (obj.start.y > 0) { + obj.start.y++; + } else { + obj.start.y--; + } + } + } + } + return obj; +} + +function fillSeries(series, opts, config) { + var index = 0; + return series.map(function(item) { + if (!item.color) { + item.color = config.colors[index]; + index = (index + 1) % config.colors.length; + } + if (!item.type) { + item.type = opts.type; + } + if (typeof item.show == "undefined") { + item.show = true; + } + if (!item.type) { + item.type = opts.type; + } + if (!item.pointShape) { + item.pointShape = "circle"; + } + if (!item.legendShape) { + switch (item.type) { + case 'line': + item.legendShape = "line"; + break; + case 'column': + item.legendShape = "rect"; + break; + case 'area': + item.legendShape = "triangle"; + break; + default: + item.legendShape = "circle"; + } + } + return item; + }); +} + +function getDataRange(minData, maxData) { + var limit = 0; + var range = maxData - minData; + if (range >= 10000) { + limit = 1000; + } else if (range >= 1000) { + limit = 100; + } else if (range >= 100) { + limit = 10; + } else if (range >= 10) { + limit = 5; + } else if (range >= 1) { + limit = 1; + } else if (range >= 0.1) { + limit = 0.1; + } else if (range >= 0.01) { + limit = 0.01; + } else if (range >= 0.001) { + limit = 0.001; + } else if (range >= 0.0001) { + limit = 0.0001; + } else if (range >= 0.00001) { + limit = 0.00001; + } else { + limit = 0.000001; + } + return { + minRange: findRange(minData, 'lower', limit), + maxRange: findRange(maxData, 'upper', limit) + }; +} + +function measureText(text) { + var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : config.fontSize; + text = String(text); + var text = text.split(''); + var width = 0; + for (let i = 0; i < text.length; i++) { + let item = text[i]; + if (/[a-zA-Z]/.test(item)) { + width += 7; + } else if (/[0-9]/.test(item)) { + width += 5.5; + } else if (/\./.test(item)) { + width += 2.7; + } else if (/-/.test(item)) { + width += 3.25; + } else if (/[\u4e00-\u9fa5]/.test(item)) { + width += 10; + } else if (/\(|\)/.test(item)) { + width += 3.73; + } else if (/\s/.test(item)) { + width += 2.5; + } else if (/%/.test(item)) { + width += 8; + } else { + width += 10; + } + } + return width * fontSize / 10; +} + +function dataCombine(series) { + return series.reduce(function(a, b) { + return (a.data ? a.data : a).concat(b.data); + }, []); +} + +function dataCombineStack(series, len) { + var sum = new Array(len); + for (var j = 0; j < sum.length; j++) { + sum[j] = 0; + } + for (var i = 0; i < series.length; i++) { + for (var j = 0; j < sum.length; j++) { + sum[j] += series[i].data[j]; + } + } + return series.reduce(function(a, b) { + return (a.data ? a.data : a).concat(b.data).concat(sum); + }, []); +} + +function getTouches(touches, opts, e) { + let x, y; + if (touches.clientX) { + if (opts.rotate) { + y = opts.height - touches.clientX * opts.pixelRatio; + x = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) * + opts.pixelRatio; + } else { + x = touches.clientX * opts.pixelRatio; + y = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) * + opts.pixelRatio; + } + } else { + if (opts.rotate) { + y = opts.height - touches.x * opts.pixelRatio; + x = touches.y * opts.pixelRatio; + } else { + x = touches.x * opts.pixelRatio; + y = touches.y * opts.pixelRatio; + } + } + return { + x: x, + y: y + } +} + +function getSeriesDataItem(series, index) { + var data = []; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + if (item.data[index] !== null && typeof item.data[index] !== 'undefined' && item.show) { + let seriesItem = {}; + seriesItem.color = item.color; + seriesItem.type = item.type; + seriesItem.style = item.style; + seriesItem.pointShape = item.pointShape; + seriesItem.disableLegend = item.disableLegend; + seriesItem.name = item.name; + seriesItem.show = item.show; + seriesItem.data = item.format ? item.format(item.data[index]) : item.data[index]; + data.push(seriesItem); + } + } + return data; +} + +function getMaxTextListLength(list) { + var lengthList = list.map(function(item) { + return measureText(item); + }); + return Math.max.apply(null, lengthList); +} + +function getRadarCoordinateSeries(length) { + var eachAngle = 2 * Math.PI / length; + var CoordinateSeries = []; + for (var i = 0; i < length; i++) { + CoordinateSeries.push(eachAngle * i); + } + + return CoordinateSeries.map(function(item) { + return -1 * item + Math.PI / 2; + }); +} + +function getToolTipData(seriesData, calPoints, index, categories) { + var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; + + var textList = seriesData.map(function(item) { + return { + text: option.format ? option.format(item, categories[index]) : item.name + ': ' + item.data, + color: item.color + }; + }); + var validCalPoints = []; + var offset = { + x: 0, + y: 0 + }; + for (let i = 0; i < calPoints.length; i++) { + let points = calPoints[i]; + if (typeof points[index] !== 'undefined' && points[index] !== null) { + validCalPoints.push(points[index]); + } + } + for (let i = 0; i < validCalPoints.length; i++) { + let item = validCalPoints[i]; + offset.x = Math.round(item.x); + offset.y += item.y; + } + offset.y /= validCalPoints.length; + return { + textList: textList, + offset: offset + }; +} + +function getMixToolTipData(seriesData, calPoints, index, categories) { + var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; + var textList = seriesData.map(function(item) { + return { + text: option.format ? option.format(item, categories[index]) : item.name + ': ' + item.data, + color: item.color, + disableLegend: item.disableLegend ? true : false + }; + }); + textList = textList.filter(function(item) { + if (item.disableLegend !== true) { + return item; + } + }); + var validCalPoints = []; + var offset = { + x: 0, + y: 0 + }; + for (let i = 0; i < calPoints.length; i++) { + let points = calPoints[i]; + if (typeof points[index] !== 'undefined' && points[index] !== null) { + validCalPoints.push(points[index]); + } + } + for (let i = 0; i < validCalPoints.length; i++) { + let item = validCalPoints[i]; + offset.x = Math.round(item.x); + offset.y += item.y; + } + offset.y /= validCalPoints.length; + return { + textList: textList, + offset: offset + }; +} + +function getCandleToolTipData(series, seriesData, calPoints, index, categories, extra) { + var option = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {}; + let upColor = extra.color.upFill; + let downColor = extra.color.downFill; + //颜色顺序为开盘,收盘,最低,最高 + let color = [upColor, upColor, downColor, upColor]; + var textList = []; + let text0 = { + text: categories[index], + color: null + }; + textList.push(text0); + seriesData.map(function(item) { + if (index == 0 && item.data[1] - item.data[0] < 0) { + color[1] = downColor; + } else { + if (item.data[0] < series[index - 1][1]) { + color[0] = downColor; + } + if (item.data[1] < item.data[0]) { + color[1] = downColor; + } + if (item.data[2] > series[index - 1][1]) { + color[2] = upColor; + } + if (item.data[3] < series[index - 1][1]) { + color[3] = downColor; + } + } + let text1 = { + text: '开盘:' + item.data[0], + color: color[0] + }; + let text2 = { + text: '收盘:' + item.data[1], + color: color[1] + }; + let text3 = { + text: '最低:' + item.data[2], + color: color[2] + }; + let text4 = { + text: '最高:' + item.data[3], + color: color[3] + }; + textList.push(text1, text2, text3, text4); + }); + var validCalPoints = []; + var offset = { + x: 0, + y: 0 + }; + for (let i = 0; i < calPoints.length; i++) { + let points = calPoints[i]; + if (typeof points[index] !== 'undefined' && points[index] !== null) { + validCalPoints.push(points[index]); + } + } + offset.x = Math.round(validCalPoints[0][0].x); + return { + textList: textList, + offset: offset + }; +} + +function filterSeries(series) { + let tempSeries = []; + for (let i = 0; i < series.length; i++) { + if (series[i].show == true) { + tempSeries.push(series[i]) + } + } + return tempSeries; +} + +function findCurrentIndex(currentPoints, xAxisPoints, opts, config) { + var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; + var currentIndex = -1; + if (isInExactChartArea(currentPoints, opts, config)) { + xAxisPoints.forEach(function(item, index) { + if (currentPoints.x + offset > item) { + currentIndex = index; + } + }); + } + return currentIndex; +} + +function findLegendIndex(currentPoints, legendData, opts) { + let currentIndex = -1; + if (isInExactLegendArea(currentPoints, legendData.area)) { + let points = legendData.points; + let index = -1; + for (let i = 0, len = points.length; i < len; i++) { + let item = points[i]; + for (let j = 0; j < item.length; j++) { + index += 1; + let area = item[j]['area']; + if (currentPoints.x > area[0] && currentPoints.x < area[2] && currentPoints.y > area[1] && currentPoints.y < area[3]) { + currentIndex = index; + break; + } + } + } + return currentIndex; + } + return currentIndex; +} + +function isInExactLegendArea(currentPoints, area) { + return currentPoints.x > area.start.x && currentPoints.x < area.end.x && currentPoints.y > area.start.y && + currentPoints.y < area.end.y; +} + +function isInExactChartArea(currentPoints, opts, config) { + return currentPoints.x < opts.width - opts.area[1] && currentPoints.x > opts.area[3] && currentPoints.y > opts.area[0] && + currentPoints.y < opts.height - opts.area[2]; +} + +function findRadarChartCurrentIndex(currentPoints, radarData, count) { + var eachAngleArea = 2 * Math.PI / count; + var currentIndex = -1; + if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) { + var fixAngle = function fixAngle(angle) { + if (angle < 0) { + angle += 2 * Math.PI; + } + if (angle > 2 * Math.PI) { + angle -= 2 * Math.PI; + } + return angle; + }; + + var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x); + angle = -1 * angle; + if (angle < 0) { + angle += 2 * Math.PI; + } + + var angleList = radarData.angleList.map(function(item) { + item = fixAngle(-1 * item); + + return item; + }); + + angleList.forEach(function(item, index) { + var rangeStart = fixAngle(item - eachAngleArea / 2); + var rangeEnd = fixAngle(item + eachAngleArea / 2); + if (rangeEnd < rangeStart) { + rangeEnd += 2 * Math.PI; + } + if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <= + rangeEnd) { + currentIndex = index; + } + }); + } + + return currentIndex; +} + +function findPieChartCurrentIndex(currentPoints, pieData) { + var currentIndex = -1; + if (isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) { + var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x); + angle = -angle; + for (var i = 0, len = pieData.series.length; i < len; i++) { + var item = pieData.series[i]; + if (isInAngleRange(angle, item._start_, item._start_ + item._proportion_ * 2 * Math.PI)) { + currentIndex = i; + break; + } + } + } + + return currentIndex; +} + +function isInExactPieChartArea(currentPoints, center, radius) { + return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2); +} + +function splitPoints(points) { + var newPoints = []; + var items = []; + points.forEach(function(item, index) { + if (item !== null) { + items.push(item); + } else { + if (items.length) { + newPoints.push(items); + } + items = []; + } + }); + if (items.length) { + newPoints.push(items); + } + + return newPoints; +} + +function calLegendData(series, opts, config, chartData) { + let legendData = { + area: { + start: { + x: 0, + y: 0 + }, + end: { + x: 0, + y: 0 + }, + width: 0, + height: 0, + wholeWidth: 0, + wholeHeight: 0 + }, + points: [], + widthArr: [], + heightArr: [] + }; + if (opts.legend.show === false) { + chartData.legendData = legendData; + return legendData; + } + + let padding = opts.legend.padding; + let margin = opts.legend.margin; + let fontSize = opts.legend.fontSize; + let shapeWidth = 15 * opts.pixelRatio; + let shapeRight = 5 * opts.pixelRatio; + let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize); + if (opts.legend.position == 'top' || opts.legend.position == 'bottom') { + let legendList = []; + let widthCount = 0; + let widthCountArr = []; + let currentRow = []; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + let itemWidth = shapeWidth + shapeRight + measureText(item.name || 'undefined', fontSize) + opts.legend.itemGap; + if (widthCount + itemWidth > opts.width - opts.padding[1] - opts.padding[3]) { + legendList.push(currentRow); + widthCountArr.push(widthCount - opts.legend.itemGap); + widthCount = itemWidth; + currentRow = [item]; + } else { + widthCount += itemWidth; + currentRow.push(item); + } + } + if (currentRow.length) { + legendList.push(currentRow); + widthCountArr.push(widthCount - opts.legend.itemGap); + legendData.widthArr = widthCountArr; + let legendWidth = Math.max.apply(null, widthCountArr); + switch (opts.legend.float) { + case 'left': + legendData.area.start.x = opts.padding[3]; + legendData.area.end.x = opts.padding[3] + 2 * padding; + break; + case 'right': + legendData.area.start.x = opts.width - opts.padding[1] - legendWidth - 2 * padding; + legendData.area.end.x = opts.width - opts.padding[1]; + break; + default: + legendData.area.start.x = (opts.width - legendWidth) / 2 - padding; + legendData.area.end.x = (opts.width + legendWidth) / 2 + padding; + } + legendData.area.width = legendWidth + 2 * padding; + legendData.area.wholeWidth = legendWidth + 2 * padding; + legendData.area.height = legendList.length * lineHeight + 2 * padding; + legendData.area.wholeHeight = legendList.length * lineHeight + 2 * padding + 2 * margin; + legendData.points = legendList; + } + } else { + let len = series.length; + let maxHeight = opts.height - opts.padding[0] - opts.padding[2] - 2 * margin - 2 * padding; + let maxLength = Math.min(Math.floor(maxHeight / lineHeight), len); + legendData.area.height = maxLength * lineHeight + padding * 2; + legendData.area.wholeHeight = maxLength * lineHeight + padding * 2; + switch (opts.legend.float) { + case 'top': + legendData.area.start.y = opts.padding[0] + margin; + legendData.area.end.y = opts.padding[0] + margin + legendData.area.height; + break; + case 'bottom': + legendData.area.start.y = opts.height - opts.padding[2] - margin - legendData.area.height; + legendData.area.end.y = opts.height - opts.padding[2] - margin; + break; + default: + legendData.area.start.y = (opts.height - legendData.area.height) / 2; + legendData.area.end.y = (opts.height + legendData.area.height) / 2; + } + let lineNum = len % maxLength === 0 ? len / maxLength : Math.floor((len / maxLength) + 1); + let currentRow = []; + for (let i = 0; i < lineNum; i++) { + let temp = series.slice(i * maxLength, i * maxLength + maxLength); + currentRow.push(temp); + } + + legendData.points = currentRow; + + if (currentRow.length) { + for (let i = 0; i < currentRow.length; i++) { + let item = currentRow[i]; + let maxWidth = 0; + for (let j = 0; j < item.length; j++) { + let itemWidth = shapeWidth + shapeRight + measureText(item[j].name || 'undefined', fontSize) + opts.legend.itemGap; + if (itemWidth > maxWidth) { + maxWidth = itemWidth; + } + } + legendData.widthArr.push(maxWidth); + legendData.heightArr.push(item.length * lineHeight + padding * 2); + } + let legendWidth = 0 + for (let i = 0; i < legendData.widthArr.length; i++) { + legendWidth += legendData.widthArr[i]; + } + legendData.area.width = legendWidth - opts.legend.itemGap + 2 * padding; + legendData.area.wholeWidth = legendData.area.width + padding; + } + } + + switch (opts.legend.position) { + case 'top': + legendData.area.start.y = opts.padding[0] + margin; + legendData.area.end.y = opts.padding[0] + margin + legendData.area.height; + break; + case 'bottom': + legendData.area.start.y = opts.height - opts.padding[2] - legendData.area.height - margin; + legendData.area.end.y = opts.height - opts.padding[2] - margin; + break; + case 'left': + legendData.area.start.x = opts.padding[3]; + legendData.area.end.x = opts.padding[3] + legendData.area.width; + break; + case 'right': + legendData.area.start.x = opts.width - opts.padding[1] - legendData.area.width; + legendData.area.end.x = opts.width - opts.padding[1]; + break; + } + chartData.legendData = legendData; + return legendData; +} + +function calCategoriesData(categories, opts, config, eachSpacing) { + var result = { + angle: 0, + xAxisHeight: config.xAxisHeight + }; + var categoriesTextLenth = categories.map(function(item) { + return measureText(item); + }); + var maxTextLength = Math.max.apply(this, categoriesTextLenth); + + if (opts.xAxis.rotateLabel == true && maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) { + result.angle = 45 * Math.PI / 180; + result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle); + } + return result; +} + +function getRadarDataPoints(angleList, center, radius, series, opts) { + var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; + + var radarOption = opts.extra.radar || {}; + radarOption.max = radarOption.max || 0; + var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series))); + + var data = []; + for (let i = 0; i < series.length; i++) { + let each = series[i]; + let listItem = {}; + listItem.color = each.color; + listItem.data = []; + each.data.forEach(function(item, index) { + let tmp = {}; + tmp.angle = angleList[index]; + + tmp.proportion = item / maxData; + tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion * + process * Math.sin(tmp.angle), center); + listItem.data.push(tmp); + }); + + data.push(listItem); + } + + return data; +} + +function getPieDataPoints(series, radius) { + var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + + var count = 0; + var _start_ = 0; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + count += item.data; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + if (count === 0) { + item._proportion_ = 1 / series.length * process; + } else { + item._proportion_ = item.data / count * process; + } + item._radius_ = radius; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item._start_ = _start_; + _start_ += 2 * item._proportion_ * Math.PI; + } + + return series; +} + +function getRoseDataPoints(series, type, minRadius, radius) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var count = 0; + var _start_ = 0; + + var dataArr = []; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + count += item.data; + dataArr.push(item.data); + } + var minData = dataArr.pop(); + var maxData = dataArr.shift(); + var radiusLength = radius - minRadius; + + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + if (count === 0 || type == 'area') { + item._proportion_ = 1 / series.length * process; + } else { + item._proportion_ = item.data / count * process; + } + item._radius_ = minRadius + radiusLength * ((item.data - minData) / (maxData - minData)); + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item._start_ = _start_; + _start_ += 2 * item._proportion_ * Math.PI; + } + + return series; +} + +function getArcbarDataPoints(series, arcbarOption) { + var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + if (process == 1) { + process = 0.999999; + } + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + let totalAngle; + if (arcbarOption.type == 'default') { + totalAngle = arcbarOption.startAngle - arcbarOption.endAngle + 1; + } else { + totalAngle = 2; + } + item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle; + if (item._proportion_ >= 2) { + item._proportion_ = item._proportion_ % 2; + } + } + return series; +} + +function getGaugeAxisPoints(categories, startAngle, endAngle) { + let totalAngle = startAngle - endAngle + 1; + let tempStartAngle = startAngle; + for (let i = 0; i < categories.length; i++) { + categories[i].value = categories[i].value === null ? 0 : categories[i].value; + categories[i]._startAngle_ = tempStartAngle; + categories[i]._endAngle_ = totalAngle * categories[i].value + startAngle; + if (categories[i]._endAngle_ >= 2) { + categories[i]._endAngle_ = categories[i]._endAngle_ % 2; + } + tempStartAngle = categories[i]._endAngle_; + } + return categories; +} + +function getGaugeDataPoints(series, categories, gaugeOption) { + let process = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + item.data = item.data === null ? 0 : item.data; + if (gaugeOption.pointer.color == 'auto') { + for (let i = 0; i < categories.length; i++) { + if (item.data <= categories[i].value) { + item.color = categories[i].color; + break; + } + } + } else { + item.color = gaugeOption.pointer.color; + } + let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1; + item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle; + item._oldAngle_ = gaugeOption.oldAngle; + if (gaugeOption.oldAngle < gaugeOption.endAngle) { + item._oldAngle_ += 2; + } + if (item.data >= gaugeOption.oldData) { + item._proportion_ = (item._endAngle_ - item._oldAngle_) * process + gaugeOption.oldAngle; + } else { + item._proportion_ = item._oldAngle_ - (item._oldAngle_ - item._endAngle_) * process; + } + if (item._proportion_ >= 2) { + item._proportion_ = item._proportion_ % 2; + } + } + return series; +} + +function getPieTextMaxLength(series) { + series = getPieDataPoints(series); + let maxLength = 0; + for (let i = 0; i < series.length; i++) { + let item = series[i]; + let text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%'; + maxLength = Math.max(maxLength, measureText(text)); + } + + return maxLength; +} + +function fixColumeData(points, eachSpacing, columnLen, index, config, opts) { + return points.map(function(item) { + if (item === null) { + return null; + } + item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / columnLen); + + if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) { + item.width = Math.min(item.width, +opts.extra.column.width); + } + if (item.width <= 0) { + item.width = 1; + } + item.x += (index + 0.5 - columnLen / 2) * item.width; + return item; + }); +} + +function fixColumeMeterData(points, eachSpacing, columnLen, index, config, opts, border) { + return points.map(function(item) { + if (item === null) { + return null; + } + item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2); + + if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) { + item.width = Math.min(item.width, +opts.extra.column.width); + } + + if (index > 0) { + item.width -= 2 * border; + } + return item; + }); +} + +function fixColumeStackData(points, eachSpacing, columnLen, index, config, opts, series) { + + return points.map(function(item, indexn) { + + if (item === null) { + return null; + } + item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2); + + if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) { + item.width = Math.min(item.width, +opts.extra.column.width); + } + return item; + }); +} + +function getXAxisPoints(categories, opts, config) { + var yAxisTotalWidth = config.yAxisWidth + config.yAxisTitleWidth; + var spacingValid = opts.width - opts.area[1] - opts.area[3]; + var dataCount = opts.enableScroll ? Math.min(opts.xAxis.itemCount, categories.length) : categories.length; + var eachSpacing = spacingValid / dataCount; + + var xAxisPoints = []; + var startX = opts.area[3]; + var endX = opts.width - opts.area[1]; + categories.forEach(function(item, index) { + xAxisPoints.push(startX + index * eachSpacing); + }); + if (opts.enableScroll === true) { + xAxisPoints.push(startX + categories.length * eachSpacing); + } else { + xAxisPoints.push(endX); + } + + return { + xAxisPoints: xAxisPoints, + startX: startX, + endX: endX, + eachSpacing: eachSpacing + }; +} + +function getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) { + var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var cPoints = []; + item.forEach(function(items, indexs) { + var point = {}; + point.x = xAxisPoints[index] + Math.round(eachSpacing / 2); + var value = items.value || items; + var height = validHeight * (value - minRange) / (maxRange - minRange); + height *= process; + point.y = opts.height - Math.round(height) - opts.area[2]; + cPoints.push(point); + }); + points.push(cPoints); + } + }); + + return points; +} + +function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) { + var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1; + + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.x = xAxisPoints[index] + Math.round(eachSpacing / 2); + var value = item; + if (typeof item === 'object' && item !== null) { + value = item.value + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + height *= process; + point.y = opts.height - Math.round(height) - opts.area[2]; + points.push(point); + } + }); + + return points; +} + +function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) { + var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.x = xAxisPoints[index] + Math.round(eachSpacing / 2); + + if (seriesIndex > 0) { + var value = 0; + for (let i = 0; i <= seriesIndex; i++) { + value += stackSeries[i].data[index]; + } + var value0 = value - item; + var height = validHeight * (value - minRange) / (maxRange - minRange); + var height0 = validHeight * (value0 - minRange) / (maxRange - minRange); + } else { + var value = item; + var height = validHeight * (value - minRange) / (maxRange - minRange); + var height0 = 0; + } + var heightc = height0; + height *= process; + heightc *= process; + point.y = opts.height - Math.round(height) - opts.area[2]; + point.y0 = opts.height - Math.round(heightc) - opts.area[2]; + points.push(point); + } + }); + + return points; +} + +function getYAxisTextList(series, opts, config, stack) { + var data; + if (stack == 'stack') { + data = dataCombineStack(series, opts.categories.length); + } else { + data = dataCombine(series); + } + var sorted = []; + // remove null from data + data = data.filter(function(item) { + //return item !== null; + if (typeof item === 'object' && item !== null) { + if (item.constructor == Array) { + return item !== null; + } else { + return item.value !== null; + } + } else { + return item !== null; + } + }); + data.map(function(item) { + if (typeof item === 'object') { + if (item.constructor == Array) { + item.map(function(subitem) { + sorted.push(subitem); + }) + } else { + sorted.push(item.value); + } + } else { + sorted.push(item); + } + }) + var minData = 0; + var maxData = 0; + if (sorted.length > 0) { + minData = Math.min.apply(this, sorted); + maxData = Math.max.apply(this, sorted); + } + if (typeof opts.yAxis.min === 'number') { + minData = Math.min(opts.yAxis.min, minData); + } + if (typeof opts.yAxis.max === 'number') { + maxData = Math.max(opts.yAxis.max, maxData); + } + + if (minData === maxData) { + var rangeSpan = maxData || 10; + maxData += rangeSpan; + } + + var dataRange = getDataRange(minData, maxData); + var minRange = dataRange.minRange; + var maxRange = dataRange.maxRange; + + var range = []; + var eachRange = (maxRange - minRange) / config.yAxisSplit; + + for (var i = 0; i <= config.yAxisSplit; i++) { + range.push(minRange + eachRange * i); + } + return range.reverse(); +} + +function calYAxisData(series, opts, config) { + //堆叠图重算Y轴 + var columnstyle = assign({}, { + type: "" + }, opts.extra.column); + var ranges = getYAxisTextList(series, opts, config, columnstyle.type); + var yAxisWidth = config.yAxisWidth; + var yAxisFontSize = opts.yAxis.fontSize || config.fontSize; + var rangesFormat = ranges.map(function(item) { + item = util.toFixed(item, 6); + item = opts.yAxis.format ? opts.yAxis.format(Number(item)) : item; + yAxisWidth = Math.max(yAxisWidth, measureText(item, yAxisFontSize) + 5); + return item; + }); + if (opts.yAxis.disabled === true) { + yAxisWidth = 0; + } + + return { + rangesFormat: rangesFormat, + ranges: ranges, + yAxisWidth: yAxisWidth + }; +} + +function calTooltipYAxisData(point, series, opts, config, eachSpacing) { + var ranges = getYAxisTextList(series, opts, config); + var spacingValid = opts.height - opts.area[0] - opts.area[2]; + let maxVal = ranges[0]; + let minVal = ranges[ranges.length - 1]; + let minAxis = opts.padding[3]; + let maxAxis = opts.padding[1] + spacingValid; + let item = maxVal - (maxVal - minVal) * (point - minAxis) / (maxAxis - minAxis); + item = opts.yAxis.format ? opts.yAxis.format(Number(item)) : item; + return item; +} + +function calMarkLineData(minRange, maxRange, points, opts) { + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + for (let i = 0; i < points.length; i++) { + let height = spacingValid * (points[i].value - minRange) / (maxRange - minRange); + points[i].y = opts.height - Math.round(height) - opts.area[2]; + } + return points; +} + +function contextRotate(context, opts) { + if (opts.rotateLock !== true) { + context.translate(opts.height, 0); + context.rotate(90 * Math.PI / 180); + } else if (opts._rotate_ !== true) { + context.translate(opts.height, 0); + context.rotate(90 * Math.PI / 180); + opts._rotate_ = true; + } +} + +function drawPointShape(points, color, shape, context, opts) { + context.beginPath(); + context.setStrokeStyle("#ffffff"); + context.setLineWidth(1 * opts.pixelRatio); + context.setFillStyle(color); + if (shape === 'diamond') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y); + context.lineTo(item.x, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'circle') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x + 3.5 * opts.pixelRatio, item.y); + context.arc(item.x, item.y, 4 * opts.pixelRatio, 0, 2 * Math.PI, false); + } + }); + } else if (shape === 'rect') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x - 3.5, item.y - 3.5); + context.rect(item.x - 3.5, item.y - 3.5, 7, 7); + } + }); + } else if (shape === 'triangle') { + points.forEach(function(item, index) { + if (item !== null) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y + 4.5); + context.lineTo(item.x, item.y - 4.5); + } + }); + } + context.closePath(); + context.fill(); + context.stroke(); +} + +function drawRingTitle(opts, config, context, center) { + var titlefontSize = opts.title.fontSize || config.titleFontSize; + var subtitlefontSize = opts.subtitle.fontSize || config.subtitleFontSize; + var title = opts.title.name || ''; + var subtitle = opts.subtitle.name || ''; + var titleFontColor = opts.title.color || config.titleColor; + var subtitleFontColor = opts.subtitle.color || config.subtitleColor; + var titleHeight = title ? titlefontSize : 0; + var subtitleHeight = subtitle ? subtitlefontSize : 0; + var margin = 5; + + if (subtitle) { + var textWidth = measureText(subtitle, subtitlefontSize); + var startX = center.x - textWidth / 2 + (opts.subtitle.offsetX || 0); + var startY = center.y + subtitlefontSize / 2 + (opts.subtitle.offsetY || 0); + if (title) { + startY += (titleHeight + margin) / 2; + } + context.beginPath(); + context.setFontSize(subtitlefontSize); + context.setFillStyle(subtitleFontColor); + context.fillText(subtitle, startX, startY); + context.closePath(); + context.stroke(); + } + if (title) { + var _textWidth = measureText(title, titlefontSize); + var _startX = center.x - _textWidth / 2 + (opts.title.offsetX || 0); + var _startY = center.y + titlefontSize / 2 + (opts.title.offsetY || 0); + if (subtitle) { + _startY -= (subtitleHeight + margin) / 2; + } + context.beginPath(); + context.setFontSize(titlefontSize); + context.setFillStyle(titleFontColor); + context.fillText(title, _startX, _startY); + context.closePath(); + context.stroke(); + } +} + +function drawPointText(points, series, config, context) { + // 绘制数据文案 + var data = series.data; + points.forEach(function(item, index) { + if (item !== null) { + //var formatVal = series.format ? series.format(data[index]) : data[index]; + context.beginPath(); + context.setFontSize(series.textSize || config.fontSize); + context.setFillStyle(series.textColor || '#666666'); + var value = data[index] + if (typeof data[index] === 'object' && data[index] !== null) { + value = data[index].value + } + var formatVal = series.format ? series.format(value) : value; + context.fillText(formatVal, item.x - measureText(formatVal, series.textSize || config.fontSize) / 2, item.y - + 2); + context.closePath(); + context.stroke(); + } + }); + +} + +function drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context) { + radius -= gaugeOption.width / 2 + config.gaugeLabelTextMargin; + + let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1; + let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; + let totalNumber = gaugeOption.endNumber - gaugeOption.startNumber; + let splitNumber = totalNumber / gaugeOption.splitLine.splitNumber; + let nowAngle = gaugeOption.startAngle; + let nowNumber = gaugeOption.startNumber; + for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) { + var pos = { + x: radius * Math.cos(nowAngle * Math.PI), + y: radius * Math.sin(nowAngle * Math.PI) + }; + var labelText = gaugeOption.labelFormat ? gaugeOption.labelFormat(nowNumber) : nowNumber; + pos.x += centerPosition.x - measureText(labelText) / 2; + pos.y += centerPosition.y; + var startX = pos.x; + var startY = pos.y; + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(gaugeOption.labelColor || '#666666'); + context.fillText(labelText, startX, startY + config.fontSize / 2); + context.closePath(); + context.stroke(); + + nowAngle += splitAngle; + if (nowAngle >= 2) { + nowAngle = nowAngle % 2; + } + nowNumber += splitNumber; + } + +} + +function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) { + var radarOption = opts.extra.radar || {}; + radius += config.radarLabelTextMargin; + + angleList.forEach(function(angle, index) { + var pos = { + x: radius * Math.cos(angle), + y: radius * Math.sin(angle) + }; + var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition); + var startX = posRelativeCanvas.x; + var startY = posRelativeCanvas.y; + if (util.approximatelyEqual(pos.x, 0)) { + startX -= measureText(opts.categories[index] || '') / 2; + } else if (pos.x < 0) { + startX -= measureText(opts.categories[index] || ''); + } + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(radarOption.labelColor || '#666666'); + context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2); + context.closePath(); + context.stroke(); + }); + +} + +function drawPieText(series, opts, config, context, radius, center) { + var lineRadius = config.pieChartLinePadding; + var textObjectCollection = []; + var lastTextObject = null; + + var seriesConvert = series.map(function(item) { + var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2); + var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + + '%'; + var color = item.color; + var radius = item._radius_; + return { + arc: arc, + text: text, + color: color, + radius: radius, + textColor: item.textColor, + textSize: item.textSize, + }; + }); + for (let i = 0; i < seriesConvert.length; i++) { + let item = seriesConvert[i]; + // line end + let orginX1 = Math.cos(item.arc) * (item.radius + lineRadius); + let orginY1 = Math.sin(item.arc) * (item.radius + lineRadius); + + // line start + let orginX2 = Math.cos(item.arc) * item.radius; + let orginY2 = Math.sin(item.arc) * item.radius; + + // text start + let orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding; + let orginY3 = orginY1; + let textWidth = measureText(item.text); + let startY = orginY3; + + if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, { + x: orginX3 + })) { + if (orginX3 > 0) { + startY = Math.min(orginY3, lastTextObject.start.y); + } else if (orginX1 < 0) { + startY = Math.max(orginY3, lastTextObject.start.y); + } else { + if (orginY3 > 0) { + startY = Math.max(orginY3, lastTextObject.start.y); + } else { + startY = Math.min(orginY3, lastTextObject.start.y); + } + } + } + if (orginX3 < 0) { + orginX3 -= textWidth; + } + + let textObject = { + lineStart: { + x: orginX2, + y: orginY2 + }, + lineEnd: { + x: orginX1, + y: orginY1 + }, + start: { + x: orginX3, + y: startY + }, + width: textWidth, + height: config.fontSize, + text: item.text, + color: item.color, + textColor: item.textColor, + textSize: item.textSize + }; + lastTextObject = avoidCollision(textObject, lastTextObject); + textObjectCollection.push(lastTextObject); + } + + for (let i = 0; i < textObjectCollection.length; i++) { + let item = textObjectCollection[i]; + let lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center); + let lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center); + let textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center); + context.setLineWidth(1 * opts.pixelRatio); + context.setFontSize(config.fontSize); + context.beginPath(); + context.setStrokeStyle(item.color); + context.setFillStyle(item.color); + context.moveTo(lineStartPoistion.x, lineStartPoistion.y); + let curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x; + let textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5; + context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y); + context.moveTo(lineStartPoistion.x, lineStartPoistion.y); + context.stroke(); + context.closePath(); + context.beginPath(); + context.moveTo(textPosition.x + item.width, textPosition.y); + context.arc(curveStartX, textPosition.y, 2, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + context.beginPath(); + context.setFontSize(item.textSize || config.fontSize); + context.setFillStyle(item.textColor || '#666666'); + context.fillText(item.text, textStartX, textPosition.y + 3); + context.closePath(); + context.stroke(); + context.closePath(); + } +} + +function drawToolTipSplitLine(offsetX, opts, config, context) { + var toolTipOption = opts.extra.tooltip || {}; + toolTipOption.gridType = toolTipOption.gridType == undefined ? 'solid' : toolTipOption.gridType; + toolTipOption.dashLength = toolTipOption.dashLength == undefined ? 4 : toolTipOption.dashLength; + var startY = opts.area[0]; + var endY = opts.height - opts.area[2]; + + if (toolTipOption.gridType == 'dash') { + context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]); + } + context.setStrokeStyle(toolTipOption.gridColor || '#cccccc'); + context.setLineWidth(1 * opts.pixelRatio); + context.beginPath(); + context.moveTo(offsetX, startY); + context.lineTo(offsetX, endY); + context.stroke(); + context.setLineDash([]); + + if (toolTipOption.xAxisLabel) { + let labelText = opts.categories[opts.tooltip.index]; + context.setFontSize(config.fontSize); + let textWidth = measureText(labelText, config.fontSize); + + let textX = offsetX - 0.5 * textWidth; + let textY = endY; + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity)); + context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground); + context.setLineWidth(1 * opts.pixelRatio); + context.rect(textX - config.toolTipPadding, textY, textWidth + 2 * config.toolTipPadding, config.fontSize + 2 * config.toolTipPadding); + context.closePath(); + context.stroke(); + context.fill(); + + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(toolTipOption.labelFontColor || config.fontColor); + context.fillText(labelText, textX, textY + config.toolTipPadding + config.fontSize); + context.closePath(); + context.stroke(); + } +} + +function drawMarkLine(minRange, maxRange, opts, config, context) { + let markLineOption = assign({}, { + type: 'solid', + dashLength: 4, + data: [] + }, opts.extra.markLine); + let startX = opts.area[3]; + let endX = opts.width - opts.padding[1]; + let points = calMarkLineData(minRange, maxRange, markLineOption.data, opts); + + for (let i = 0; i < points.length; i++) { + let item = assign({}, { + lineColor: '#DE4A42', + showLabel: false, + labelFontColor: '#666666', + labelBgColor: '#DFE8FF', + labelBgOpacity: 0.8, + yAxisIndex: 0 + }, points[i]); + + if (markLineOption.type == 'dash') { + context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]); + } + context.setStrokeStyle(item.lineColor); + context.setLineWidth(1 * opts.pixelRatio); + context.beginPath(); + context.moveTo(startX, item.y); + context.lineTo(endX, item.y); + context.stroke(); + context.setLineDash([]); + if (item.showLabel) { + let labelText = opts.yAxis.format ? opts.yAxis.format(Number(item.value)) : item.value; + context.setFontSize(config.fontSize); + let textWidth = measureText(labelText, config.fontSize); + let bgStartX = opts.padding[3] + config.yAxisTitleWidth - config.toolTipPadding; + let bgEndX = Math.max(opts.area[3], textWidth + config.toolTipPadding * 2); + let bgWidth = bgEndX - bgStartX; + + let textX = bgStartX + (bgWidth - textWidth) / 2; + let textY = item.y; + context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity)); + context.setStrokeStyle(item.labelBgColor); + context.setLineWidth(1 * opts.pixelRatio); + context.beginPath(); + context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding); + context.closePath(); + context.stroke(); + context.fill(); + + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(item.labelFontColor); + context.fillText(labelText, textX, textY + 0.5 * config.fontSize); + context.stroke(); + } + } +} + +function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) { + var toolTipOption = assign({}, { + gridType: 'solid', + dashLength: 4 + }, opts.extra.tooltip); + + var startX = opts.area[3]; + var endX = opts.width - opts.padding[1]; + + if (toolTipOption.gridType == 'dash') { + context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]); + } + context.setStrokeStyle(toolTipOption.gridColor || '#cccccc'); + context.setLineWidth(1 * opts.pixelRatio); + context.beginPath(); + context.moveTo(startX, opts.tooltip.offset.y); + context.lineTo(endX, opts.tooltip.offset.y); + context.stroke(); + context.setLineDash([]); + + if (toolTipOption.yAxisLabel) { + let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing); + context.setFontSize(config.fontSize); + let textWidth = measureText(labelText, config.fontSize); + let bgStartX = opts.padding[3] + config.yAxisTitleWidth - config.toolTipPadding; + let bgEndX = Math.max(opts.area[3], textWidth + config.toolTipPadding * 2); + let bgWidth = bgEndX - bgStartX; + + let textX = bgStartX + (bgWidth - textWidth) / 2; + let textY = opts.tooltip.offset.y; + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity)); + context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground); + context.setLineWidth(1 * opts.pixelRatio); + context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding); + context.closePath(); + context.stroke(); + context.fill(); + + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(toolTipOption.labelFontColor || config.fontColor); + context.fillText(labelText, textX, textY + 0.5 * config.fontSize); + context.closePath(); + context.stroke(); + } +} + +function drawToolTipSplitArea(offsetX, opts, config, context, eachSpacing) { + var toolTipOption = assign({}, { + activeBgColor: '#000000', + activeBgOpacity: 0.08 + }, opts.extra.tooltip); + var startY = opts.area[0]; + var endY = opts.height - opts.area[2]; + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity)); + context.rect(offsetX - eachSpacing / 2, startY, eachSpacing, endY - startY); + context.closePath(); + context.fill(); +} + +function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxisPoints) { + var toolTipOption = assign({}, { + bgColor: '#000000', + bgOpacity: 0.7, + fontColor: '#FFFFFF' + }, opts.extra.tooltip); + var legendWidth = 4 * opts.pixelRatio; + var legendMarginRight = 5 * opts.pixelRatio; + var arrowWidth = 8 * opts.pixelRatio; + var isOverRightBorder = false; + if (opts.type == 'line' || opts.type == 'area' || opts.type == 'candle' || opts.type == 'mix') { + drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context); + } + + offset = assign({ + x: 0, + y: 0 + }, offset); + offset.y -= 8 * opts.pixelRatio; + var textWidth = textList.map(function(item) { + return measureText(item.text, config.fontSize); + }); + var toolTipWidth = legendWidth + legendMarginRight + 4 * config.toolTipPadding + Math.max.apply(null, textWidth); + var toolTipHeight = 2 * config.toolTipPadding + textList.length * config.toolTipLineHeight; + + // if beyond the right border + if (offset.x - Math.abs(opts._scrollDistance_) + arrowWidth + toolTipWidth > opts.width) { + isOverRightBorder = true; + } + if (toolTipHeight + offset.y > opts.height) { + offset.y = opts.height - toolTipHeight; + } + // draw background rect + context.beginPath(); + context.setFillStyle(hexToRgb(toolTipOption.bgColor || config.toolTipBackground, toolTipOption.bgOpacity || config.toolTipOpacity)); + if (isOverRightBorder) { + context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio); + context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio); + context.lineTo(offset.x - arrowWidth, offset.y); + context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y); + context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y + toolTipHeight); + context.lineTo(offset.x - arrowWidth, offset.y + toolTipHeight); + context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio); + context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio); + } else { + context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio); + context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio); + context.lineTo(offset.x + arrowWidth, offset.y); + context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y); + context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y + toolTipHeight); + context.lineTo(offset.x + arrowWidth, offset.y + toolTipHeight); + context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio); + context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio); + } + + context.closePath(); + context.fill(); + + // draw legend + textList.forEach(function(item, index) { + if (item.color !== null) { + context.beginPath(); + context.setFillStyle(item.color); + var startX = offset.x + arrowWidth + 2 * config.toolTipPadding; + var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + + config.toolTipPadding + 1; + if (isOverRightBorder) { + startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding; + } + context.fillRect(startX, startY, legendWidth, config.fontSize); + context.closePath(); + } + }); + + // draw text list + + textList.forEach(function(item, index) { + var startX = offset.x + arrowWidth + 2 * config.toolTipPadding + legendWidth + legendMarginRight; + if (isOverRightBorder) { + startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding + +legendWidth + legendMarginRight; + } + var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + + config.toolTipPadding; + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(toolTipOption.fontColor); + context.fillText(item.text, startX, startY + config.fontSize); + context.closePath(); + context.stroke(); + }); +} + +function drawYAxisTitle(title, opts, config, context) { + var startX = config.xAxisHeight + (opts.height - config.xAxisHeight - measureText(title)) / 2; + context.save(); + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(opts.yAxis.titleFontColor || '#333333'); + context.translate(0, opts.height); + context.rotate(-90 * Math.PI / 180); + context.fillText(title, startX, opts.padding[3] + 0.5 * config.fontSize); + context.closePath(); + context.stroke(); + context.restore(); +} + +function drawColumnDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let ranges = [].concat(opts.chartData.yAxisData.ranges); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + let columnOption = assign({}, { + type: 'group', + width: eachSpacing / 2, + meter: { + border: 4, + fillColor: '#FFFFFF' + } + }, opts.extra.column); + let minRange = ranges.pop(); + let maxRange = ranges.shift(); + let calPoints = []; + + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + } + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawToolTipSplitArea(opts.tooltip.offset.x, opts, config, context, eachSpacing); + } + + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + switch (columnOption.type) { + case 'group': + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + var tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); + calPoints.push(tooltipPoints); + points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts); + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + context.setFillStyle(item.color || eachSeries.color); + var startX = item.x - item.width / 2 + 1; + var height = opts.height - item.y - opts.area[2]; + context.moveTo(startX, item.y); + context.fillRect(startX, item.y, item.width - 2, height); + context.closePath(); + context.fill(); + } + }); + break; + case 'stack': + // 绘制堆叠数据图 + var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, + seriesIndex, + series, process); + calPoints.push(points); + points = fixColumeStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series); + + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + context.setFillStyle(item.color || eachSeries.color); + var startX = item.x - item.width / 2 + 1; + var height = opts.height - item.y - opts.area[2]; + var height0 = opts.height - item.y0 - opts.area[2]; + if (seriesIndex > 0) { + height -= height0; + } + context.moveTo(startX, item.y); + context.fillRect(startX, item.y, item.width - 2, height); + context.closePath(); + context.fill(); + } + }); + break; + case 'meter': + // 绘制温度计数据图 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meter + .border); + if (seriesIndex == 0) { + points.forEach(function(item, index) { + if (item !== null) { + //画背景颜色 + context.beginPath(); + context.setFillStyle(columnOption.meter.fillColor); + var startX = item.x - item.width / 2; + var height = opts.height - item.y - opts.area[2]; + context.moveTo(startX, item.y); + context.fillRect(startX, item.y, item.width, height); + context.closePath(); + context.fill(); + //画边框线 + if (columnOption.meter.border > 0) { + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(columnOption.meter.border * opts.pixelRatio); + context.moveTo(startX + columnOption.meter.border * 0.5, item.y + height); + context.lineTo(startX + columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5); + context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5); + context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + height); + context.stroke(); + } + } + }); + } else { + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + context.setFillStyle(item.color || eachSeries.color); + var startX = item.x - item.width / 2; + var height = opts.height - item.y - opts.area[2]; + context.moveTo(startX, item.y); + context.fillRect(startX, item.y, item.width, height); + context.closePath(); + context.fill(); + } + }); + } + break; + } + }); + + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + switch (columnOption.type) { + case 'group': + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts); + + drawPointText(points, eachSeries, config, context); + break; + case 'stack': + var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, + seriesIndex, + series, process); + drawPointText(points, eachSeries, config, context); + break; + case 'meter': + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + drawPointText(points, eachSeries, config, context); + break; + } + }); + } + + context.restore(); + + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing, + minRange: minRange, + maxRange: maxRange + }; +} + +function drawCandleDataPoints(series, seriesMA, opts, config, context) { + var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; + var candleOption = assign({}, { + color: {}, + average: {} + }, opts.extra.candle); + candleOption.color = assign({}, { + upLine: '#f04864', + upFill: '#f04864', + downLine: '#2fc25b', + downFill: '#2fc25b' + }, candleOption.color); + candleOption.average = assign({}, { + show: false, + name: [], + day: [], + color: config.colors + }, candleOption.average); + opts.extra.candle = candleOption; + + let ranges = [].concat(opts.chartData.yAxisData.ranges); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + + let minRange = ranges.pop(); + let maxRange = ranges.shift(); + let calPoints = []; + + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + } + //画均线 + if (candleOption.average.show) { + seriesMA.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + //calPoints.push(points); + var splitPointList = splitPoints(points); + + splitPointList.forEach(function(points, index) { + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(1); + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + points.forEach(function(item, index) { + if (index > 0) { + var ctrlPoint = createCurveControlPoints(points, index - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, + item.x, item + .y); + } + }); + context.moveTo(points[0].x, points[0].y); + } + context.closePath(); + context.stroke(); + }); + }); + } + //画K线 + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + var points = getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + var splitPointList = splitPoints(points); + splitPointList = splitPointList[0]; + + splitPointList.forEach(function(points, index) { + context.beginPath(); + //如果上涨 + if (data[index][1] - data[index][0] > 0) { + context.setStrokeStyle(candleOption.color.upLine); + context.setFillStyle(candleOption.color.upFill); + context.setLineWidth(1 * opts.pixelRatio); + context.moveTo(points[3].x, points[3].y); //顶点 + context.lineTo(points[1].x, points[1].y); //收盘中间点 + context.lineTo(points[1].x - eachSpacing / 4, points[1].y); //收盘左侧点 + context.lineTo(points[0].x - eachSpacing / 4, points[0].y); //开盘左侧点 + context.lineTo(points[0].x, points[0].y); //开盘中间点 + context.lineTo(points[2].x, points[2].y); //底点 + context.lineTo(points[0].x, points[0].y); //开盘中间点 + context.lineTo(points[0].x + eachSpacing / 4, points[0].y); //开盘右侧点 + context.lineTo(points[1].x + eachSpacing / 4, points[1].y); //收盘右侧点 + context.lineTo(points[1].x, points[1].y); //收盘中间点 + context.moveTo(points[3].x, points[3].y); //顶点 + } else { + context.setStrokeStyle(candleOption.color.downLine); + context.setFillStyle(candleOption.color.downFill); + context.setLineWidth(1 * opts.pixelRatio); + context.moveTo(points[3].x, points[3].y); //顶点 + context.lineTo(points[0].x, points[0].y); //开盘中间点 + context.lineTo(points[0].x - eachSpacing / 4, points[0].y); //开盘左侧点 + context.lineTo(points[1].x - eachSpacing / 4, points[1].y); //收盘左侧点 + context.lineTo(points[1].x, points[1].y); //收盘中间点 + context.lineTo(points[2].x, points[2].y); //底点 + context.lineTo(points[1].x, points[1].y); //收盘中间点 + context.lineTo(points[1].x + eachSpacing / 4, points[1].y); //收盘右侧点 + context.lineTo(points[0].x + eachSpacing / 4, points[0].y); //开盘右侧点 + context.lineTo(points[0].x, points[0].y); //开盘中间点 + context.moveTo(points[3].x, points[3].y); //顶点 + } + context.closePath(); + context.fill(); + context.stroke(); + }); + }); + + context.restore(); + + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing, + minRange: minRange, + maxRange: maxRange + }; +} + +function drawAreaDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var areaOption = assign({},{ + type: 'straight', + opacity: 0.2, + addLine: false, + width: 2 + },opts.extra.area); + + let ranges = [].concat(opts.chartData.yAxisData.ranges); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + + let minRange = ranges.pop(); + let maxRange = ranges.shift(); + let endY = opts.height - opts.area[2]; + let calPoints = []; + + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + } + + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context); + } + + series.forEach(function(eachSeries, seriesIndex) { + let data = eachSeries.data; + let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + + let splitPointList = splitPoints(points); + + for (let i = 0; i < splitPointList.length; i++) { + let points = splitPointList[i]; + // 绘制区域数 + context.beginPath(); + context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity)); + context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity)); + context.setLineWidth(areaOption.width * opts.pixelRatio); + if (points.length > 1) { + let firstPoint = points[0]; + let lastPoint = points[points.length - 1]; + + context.moveTo(firstPoint.x, firstPoint.y); + if (areaOption.type === 'curve') { + points.forEach(function(item, index) { + if (index > 0) { + let ctrlPoint = createCurveControlPoints(points, index - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, + item.x, item + .y); + } + }); + } else { + points.forEach(function(item, index) { + if (index > 0) { + context.lineTo(item.x, item.y); + } + }); + } + + context.lineTo(lastPoint.x, endY); + context.lineTo(firstPoint.x, endY); + context.lineTo(firstPoint.x, firstPoint.y); + } else { + let item = points[0]; + context.moveTo(item.x - eachSpacing / 2, item.y); + context.lineTo(item.x + eachSpacing / 2, item.y); + context.lineTo(item.x + eachSpacing / 2, endY); + context.lineTo(item.x - eachSpacing / 2, endY); + context.moveTo(item.x - eachSpacing / 2, item.y); + } + context.closePath(); + context.fill(); + + //画连线 + if (areaOption.addLine) { + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(areaOption.width * opts.pixelRatio); + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + if (areaOption.type === 'curve') { + points.forEach(function(item, index) { + if (index > 0) { + let ctrlPoint = createCurveControlPoints(points, index - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, + item.x, + item.y); + } + }); + } else { + points.forEach(function(item, index) { + if (index > 0) { + context.lineTo(item.x, item.y); + } + }); + } + context.moveTo(points[0].x, points[0].y); + } + context.closePath(); + context.stroke(); + } + } + + //画点 + if (opts.dataPointShape !== false) { + var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length]; + drawPointShape(points, eachSeries.color, shape, context, opts); + } + + }); + + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + drawPointText(points, eachSeries, config, context); + }); + } + + context.restore(); + + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing, + minRange: minRange, + maxRange: maxRange + }; +} + +function drawLineDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var lineOption = opts.extra.line || { + type: 'straight', + width: 2 + }; + lineOption.type = lineOption.type ? lineOption.type : 'straight'; + lineOption.width = lineOption.width ? lineOption.width : 2; + + let ranges = [].concat(opts.chartData.yAxisData.ranges); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + + var minRange = ranges.pop(); + var maxRange = ranges.shift(); + var calPoints = []; + + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + } + + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context); + } + + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + var splitPointList = splitPoints(points); + + splitPointList.forEach(function(points, index) { + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(lineOption.width * opts.pixelRatio); + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + if (lineOption.type === 'curve') { + points.forEach(function(item, index) { + if (index > 0) { + var ctrlPoint = createCurveControlPoints(points, index - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, + item.x, item + .y); + } + }); + } else { + points.forEach(function(item, index) { + if (index > 0) { + context.lineTo(item.x, item.y); + } + }); + } + context.moveTo(points[0].x, points[0].y); + } + context.closePath(); + context.stroke(); + }); + + if (opts.dataPointShape !== false) { + var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length]; + drawPointShape(points, eachSeries.color, shape, context, opts); + } + }); + + if (opts.dataLabel !== false && process === 1) { + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + drawPointText(points, eachSeries, config, context); + }); + } + + context.restore(); + + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing, + minRange: minRange, + maxRange: maxRange + }; +} + +function drawMixDataPoints(series, opts, config, context) { + let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + let ranges = [].concat(opts.chartData.yAxisData.ranges); + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; + + let minRange = ranges.pop(); + let maxRange = ranges.shift(); + let endY = opts.height - opts.area[2]; + let calPoints = []; + + var columnIndex = 0; + var columnLength = 0; + series.forEach(function(eachSeries, seriesIndex) { + if (eachSeries.type == 'column') { + columnLength += 1; + } + }); + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + } + + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context); + } + + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + calPoints.push(points); + + // 绘制柱状数据图 + if (eachSeries.type == 'column') { + points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts); + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + context.setFillStyle(item.color || eachSeries.color); + var startX = item.x - item.width / 2 + 1; + var height = opts.height - item.y - opts.area[2]; + context.moveTo(startX, item.y); + context.rect(startX, item.y, item.width - 2, height); + context.closePath(); + context.fill(); + } + }); + columnIndex += 1; + } + + //绘制区域图数据 + + if (eachSeries.type == 'area') { + let splitPointList = splitPoints(points); + for (let i = 0; i < splitPointList.length; i++) { + let points = splitPointList[i]; + // 绘制区域数据 + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setFillStyle(hexToRgb(eachSeries.color, 0.2)); + context.setLineWidth(2 * opts.pixelRatio); + if (points.length > 1) { + var firstPoint = points[0]; + let lastPoint = points[points.length - 1]; + context.moveTo(firstPoint.x, firstPoint.y); + if (eachSeries.style === 'curve') { + points.forEach(function(item, index) { + if (index > 0) { + var ctrlPoint = createCurveControlPoints(points, index - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y); + } + }); + } else { + points.forEach(function(item, index) { + if (index > 0) { + context.lineTo(item.x, item.y); + } + }); + } + context.lineTo(lastPoint.x, endY); + context.lineTo(firstPoint.x, endY); + context.lineTo(firstPoint.x, firstPoint.y); + } else { + let item = points[0]; + context.moveTo(item.x - eachSpacing / 2, item.y); + context.lineTo(item.x + eachSpacing / 2, item.y); + context.lineTo(item.x + eachSpacing / 2, endY); + context.lineTo(item.x - eachSpacing / 2, endY); + context.moveTo(item.x - eachSpacing / 2, item.y); + } + context.closePath(); + context.fill(); + } + } + + // 绘制折线数据图 + if (eachSeries.type == 'line') { + var splitPointList = splitPoints(points); + splitPointList.forEach(function(points, index) { + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(2 * opts.pixelRatio); + if (points.length === 1) { + context.moveTo(points[0].x, points[0].y); + context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + } else { + context.moveTo(points[0].x, points[0].y); + if (eachSeries.style == 'curve') { + points.forEach(function(item, index) { + if (index > 0) { + var ctrlPoint = createCurveControlPoints(points, index - 1); + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, + item.x, + item.y); + } + }); + } else { + points.forEach(function(item, index) { + if (index > 0) { + context.lineTo(item.x, item.y); + } + }); + } + context.moveTo(points[0].x, points[0].y); + } + context.closePath(); + context.stroke(); + }); + } + + // 绘制点数据图 + if (eachSeries.type == 'point') { + points.forEach(function(pointsa, index) { + if (pointsa) { + context.beginPath(); + context.setFillStyle(eachSeries.color); + context.setStrokeStyle('#FFFFFF'); + context.setLineWidth(1 * opts.pixelRatio); + context.moveTo(pointsa.x + 3.5 * opts.pixelRatio, pointsa.y); + context.arc(pointsa.x, pointsa.y, 4 * opts.pixelRatio, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + context.stroke(); + } + }); + } + + if (eachSeries.addPoint == true && eachSeries.type !== 'column') { + var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length]; + drawPointShape(points, eachSeries.color, shape, context, opts); + } + }); + if (opts.dataLabel !== false && process === 1) { + var columnIndex = 0; + series.forEach(function(eachSeries, seriesIndex) { + var data = eachSeries.data; + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + if (eachSeries.type !== 'column') { + drawPointText(points, eachSeries, config, context); + } else { + points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts); + drawPointText(points, eachSeries, config, context); + columnIndex += 1; + } + + }); + } + + context.restore(); + + return { + xAxisPoints: xAxisPoints, + calPoints: calPoints, + eachSpacing: eachSpacing, + minRange: minRange, + maxRange: maxRange + }; +} + +function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints) { + var toolTipOption = opts.extra.tooltip || {}; + if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'candle' || opts.type == + 'mix')) { + drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) + } + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) { + context.translate(opts._scrollDistance_, 0); + } + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) { + drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context, eachSpacing, xAxisPoints); + } + context.restore(); + +} + +function drawXAxis(categories, opts, config, context) { + + let xAxisData = opts.chartData.xAxisData, + xAxisPoints = xAxisData.xAxisPoints, + startX = xAxisData.startX, + endX = xAxisData.endX, + eachSpacing = xAxisData.eachSpacing; + + var startY = opts.height - opts.area[2]; + var endY = opts.area[0]; + + //绘制滚动条 + if (opts.enableScroll && opts.xAxis.scrollShow) { + var scrollY = opts.height - opts.area[2] + config.xAxisHeight; + var scrollScreenWidth = endX - startX; + var scrollTotalWidth = eachSpacing * (xAxisPoints.length - 1); + var scrollWidth = scrollScreenWidth * scrollScreenWidth / scrollTotalWidth; + var scrollLeft = 0; + if (opts._scrollDistance_) { + scrollLeft = -opts._scrollDistance_ * (scrollScreenWidth) / scrollTotalWidth; + } + context.beginPath(); + context.setLineCap('round'); + context.setLineWidth(6 * opts.pixelRatio); + context.setStrokeStyle(opts.xAxis.scrollBackgroundColor || "#EFEBEF"); + context.moveTo(startX, scrollY); + context.lineTo(endX, scrollY); + context.stroke(); + context.closePath(); + context.beginPath(); + context.setLineCap('round'); + context.setLineWidth(6 * opts.pixelRatio); + context.setStrokeStyle(opts.xAxis.scrollColor || "#A6A6A6"); + context.moveTo(startX + scrollLeft, scrollY); + context.lineTo(startX + scrollLeft + scrollWidth, scrollY); + context.stroke(); + context.setLineCap('butt'); + context.closePath(); + } + + context.save(); + + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) { + context.translate(opts._scrollDistance_, 0); + } + + context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc"); + context.setLineCap('butt'); + context.setLineWidth(1 * opts.pixelRatio); + if (opts.xAxis.gridType == 'dash') { + context.setLineDash([opts.xAxis.dashLength, opts.xAxis.dashLength]); + } + context.beginPath(); + if (opts.xAxis.disableGrid !== true) { + if (opts.xAxis.type === 'calibration') { + xAxisPoints.forEach(function(item, index) { + if (index > 0) { + context.moveTo(item - eachSpacing / 2, startY); + context.lineTo(item - eachSpacing / 2, startY + 4 * opts.pixelRatio); + } + }); + } else { + opts.xAxis.gridEval = opts.xAxis.gridEval || 1; + xAxisPoints.forEach(function(item, index) { + if (index % opts.xAxis.gridEval == 0) { + context.moveTo(item, startY); + context.lineTo(item, endY); + } + }); + } + } + context.stroke(); + context.setLineDash([]); + + //不绘制X轴 + if (opts.xAxis.disabled !== true) { + // 对X轴列表做抽稀处理 + let validWidth = opts.width - opts.padding[1] - opts.padding[3] - config.yAxisWidth - config.yAxisTitleWidth; + //默认全部显示X轴标签 + let maxXAxisListLength = categories.length; + //如果设置了X轴单屏数量 + if (opts.xAxis.labelCount) { + //如果设置X轴密度 + if (opts.xAxis.itemCount) { + maxXAxisListLength = Math.ceil(categories.length / opts.xAxis.itemCount * opts.xAxis.labelCount); + } else { + maxXAxisListLength = opts.xAxis.labelCount; + } + maxXAxisListLength -= 1; + } + + let ratio = Math.ceil(categories.length / maxXAxisListLength); + + let newCategories = []; + let cgLength = categories.length; + for (let i = 0; i < cgLength; i++) { + if (i % ratio !== 0) { + newCategories.push(""); + } else { + newCategories.push(categories[i]); + } + } + newCategories[cgLength - 1] = categories[cgLength - 1]; + + var xAxisFontSize = opts.xAxis.fontSize || config.fontSize; + if (config._xAxisTextAngle_ === 0) { + newCategories.forEach(function(item, index) { + var offset = eachSpacing / 2 - measureText(item, xAxisFontSize) / 2; + context.beginPath(); + context.setFontSize(xAxisFontSize); + context.setFillStyle(opts.xAxis.fontColor || '#666666'); + context.fillText(item, xAxisPoints[index] + offset, startY + xAxisFontSize + (config.xAxisHeight - + xAxisFontSize) / 2); + context.closePath(); + context.stroke(); + }); + + } else { + newCategories.forEach(function(item, index) { + context.save(); + context.beginPath(); + context.setFontSize(xAxisFontSize); + context.setFillStyle(opts.xAxis.fontColor || '#666666'); + var textWidth = measureText(item); + var offset = eachSpacing / 2 - textWidth; + + var _calRotateTranslate = calRotateTranslate(xAxisPoints[index] + eachSpacing / 2, startY + xAxisFontSize / + 2 + 5, opts.height), + transX = _calRotateTranslate.transX, + transY = _calRotateTranslate.transY; + + context.rotate(-1 * config._xAxisTextAngle_); + context.translate(transX, transY); + context.fillText(item, xAxisPoints[index] + offset, startY + xAxisFontSize + 5); + context.closePath(); + context.stroke(); + context.restore(); + }); + } + } + context.restore(); + +} + +function drawYAxisGrid(categories, opts, config, context) { + if (opts.yAxis.disableGrid === true) { + return; + } + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + let eachSpacing = spacingValid / config.yAxisSplit; + let startX = opts.area[3]; + let xAxisPoints = opts.chartData.xAxisData.xAxisPoints, + xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing; + let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1); + let endX = startX + TotalWidth; + + let points = []; + for (let i = 0; i < config.yAxisSplit + 1; i++) { + points.push(opts.height - opts.area[2] - eachSpacing * i); + } + + context.save(); + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) { + context.translate(opts._scrollDistance_, 0); + } + + if (opts.yAxis.gridType == 'dash') { + context.setLineDash([opts.yAxis.dashLength, opts.yAxis.dashLength]); + } + context.setStrokeStyle(opts.yAxis.gridColor || "#cccccc"); + context.setLineWidth(1 * opts.pixelRatio); + context.beginPath(); + points.forEach(function(item, index) { + context.moveTo(startX, item); + context.lineTo(endX, item); + }); + context.stroke(); + context.setLineDash([]); + + context.restore(); +} + +function drawYAxis(series, opts, config, context) { + if (opts.yAxis.disabled === true) { + return; + } + let rangesFormat = opts.chartData.yAxisData.rangesFormat; + var spacingValid = opts.height - opts.area[0] - opts.area[2]; + var eachSpacing = Math.floor(spacingValid / config.yAxisSplit); + var startX = opts.area[3]; + var endX = opts.width - opts.area[1]; + var endY = opts.height - opts.area[2]; + var fillEndY = endY + config.xAxisHeight; + if (opts.xAxis.scrollShow) { + fillEndY -= 3 * opts.pixelRatio; + } + // set YAxis background + context.beginPath(); + context.setFillStyle(opts.background || '#ffffff'); + if (opts._scrollDistance_ < 0) { + context.fillRect(0, 0, startX, fillEndY); + } + context.fillRect(endX, 0, opts.width, fillEndY); + context.closePath(); + context.stroke(); + + var points = []; + for (var i = 0; i <= config.yAxisSplit; i++) { + points.push(opts.area[0] + eachSpacing * i); + } + + var yAxisFontSize = opts.yAxis.fontSize || config.fontSize; + rangesFormat.forEach(function(item, index) { + var pos = points[index] ? points[index] : endY; + context.beginPath(); + context.setFontSize(yAxisFontSize); + context.setFillStyle(opts.yAxis.fontColor || '#666666'); + context.fillText(item, opts.area[3] - config.yAxisWidth, pos + yAxisFontSize / 2); + context.closePath(); + context.stroke(); + }); + + if (opts.yAxis.title) { + drawYAxisTitle(opts.yAxis.title, opts, config, context); + } +} + +function drawLegend(series, opts, config, context, chartData) { + if (opts.legend.show === false) { + return; + } + let legendData = chartData.legendData; + let legendList = legendData.points; + let legendArea = legendData.area; + let padding = opts.legend.padding; + let fontSize = opts.legend.fontSize; + let shapeWidth = 15 * opts.pixelRatio; + let shapeRight = 5 * opts.pixelRatio; + let itemGap = opts.legend.itemGap; + let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize); + + //画背景及边框 + context.beginPath(); + context.setLineWidth(opts.legend.borderWidth); + context.setStrokeStyle(opts.legend.borderColor); + context.setFillStyle(opts.legend.backgroundColor); + context.moveTo(legendArea.start.x, legendArea.start.y); + context.rect(legendArea.start.x, legendArea.start.y, legendArea.width, legendArea.height); + context.closePath(); + context.fill(); + context.stroke(); + + legendList.forEach(function(itemList, listIndex) { + let width = 0; + let height = 0; + width = legendData.widthArr[listIndex]; + height = legendData.heightArr[listIndex]; + let startX = 0; + let startY = 0; + if (opts.legend.position == 'top' || opts.legend.position == 'bottom') { + startX = legendArea.start.x + (legendArea.width - width) / 2; + startY = legendArea.start.y + padding + listIndex * lineHeight; + } else { + if (listIndex == 0) { + width = 0; + } else { + width = legendData.widthArr[listIndex - 1]; + } + startX = legendArea.start.x + padding + width; + startY = legendArea.start.y + padding + (legendArea.height - height) / 2; + } + + context.setFontSize(config.fontSize); + for (let i = 0; i < itemList.length; i++) { + let item = itemList[i]; + item.area = [0, 0, 0, 0]; + item.area[0] = startX; + item.area[1] = startY; + item.area[3] = startY + lineHeight; + context.beginPath(); + context.setLineWidth(1 * opts.pixelRatio); + context.setStrokeStyle(item.show ? item.color : opts.legend.hiddenColor); + context.setFillStyle(item.show ? item.color : opts.legend.hiddenColor); + switch (item.legendShape) { + case 'line': + context.moveTo(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio); + context.fillRect(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio, 15 * opts.pixelRatio, 4 * opts.pixelRatio); + break; + case 'triangle': + context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio); + context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio); + context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio); + context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio); + break; + case 'diamond': + context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio); + context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight); + context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio); + context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight); + context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio); + break; + case 'circle': + context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight); + context.arc(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight, 5 * opts.pixelRatio, 0, 2 * Math.PI); + break; + case 'rect': + context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio); + context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio); + break; + default: + context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio); + context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio); + } + context.closePath(); + context.fill(); + context.stroke(); + + startX += shapeWidth + shapeRight; + let fontTrans = 0.5 * lineHeight + 0.5 * fontSize - 2; + context.beginPath(); + context.setFontSize(fontSize); + context.setFillStyle(item.show ? opts.legend.fontColor : opts.legend.hiddenColor); + context.fillText(item.name, startX, startY + fontTrans); + context.closePath(); + context.stroke(); + if (opts.legend.position == 'top' || opts.legend.position == 'bottom') { + startX += measureText(item.name, fontSize) + itemGap; + item.area[2] = startX; + } else { + item.area[2] = startX + measureText(item.name, fontSize) + itemGap;; + startX -= shapeWidth + shapeRight; + startY += lineHeight; + } + } + }); +} + +function drawPieDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var pieOption = assign({}, { + activeOpacity: 0.5, + activeRadius: 10 * opts.pixelRatio, + offsetAngle: 0, + labelWidth: 15 * opts.pixelRatio, + ringWidth: 0 + }, opts.extra.pie); + var centerPosition = { + x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2, + y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2 + }; + if (config.pieChartLinePadding == 0) { + config.pieChartLinePadding = pieOption.activeRadius; + } + + var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[ + 0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding); + + series = getPieDataPoints(series, radius, process); + + var activeRadius = pieOption.activeRadius; + + series = series.map(function(eachSeries) { + eachSeries._start_ += (pieOption.offsetAngle) * Math.PI / 180; + return eachSeries; + }); + series.forEach(function(eachSeries, seriesIndex) { + if (opts.tooltip) { + if (opts.tooltip.index == seriesIndex) { + context.beginPath(); + context.setFillStyle(hexToRgb(eachSeries.color, opts.extra.pie.activeOpacity || 0.5)); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_ + activeRadius, eachSeries._start_, + eachSeries._start_ + 2 * + eachSeries._proportion_ * Math.PI); + context.closePath(); + context.fill(); + } + } + context.beginPath(); + context.setLineWidth(2 * opts.pixelRatio); + context.lineJoin = "round"; + context.setStrokeStyle('#ffffff'); + context.setFillStyle(eachSeries.color); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI); + context.closePath(); + context.fill(); + if (opts.disablePieStroke !== true) { + context.stroke(); + } + }); + + if (opts.type === 'ring') { + var innerPieWidth = radius * 0.6; + if (typeof opts.extra.pie.ringWidth === 'number' && opts.extra.pie.ringWidth > 0) { + innerPieWidth = Math.max(0, radius - opts.extra.pie.ringWidth); + } + context.beginPath(); + context.setFillStyle(opts.background || '#ffffff'); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + } + + if (opts.dataLabel !== false && process === 1) { + var valid = false; + for (var i = 0, len = series.length; i < len; i++) { + if (series[i].data > 0) { + valid = true; + break; + } + } + + if (valid) { + drawPieText(series, opts, config, context, radius, centerPosition); + } + } + + if (process === 1 && opts.type === 'ring') { + drawRingTitle(opts, config, context, centerPosition); + } + + return { + center: centerPosition, + radius: radius, + series: series + }; +} + +function drawRoseDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var roseOption = assign({}, { + type: 'area', + activeOpacity: 0.5, + activeRadius: 10 * opts.pixelRatio, + offsetAngle: 0, + labelWidth: 15 * opts.pixelRatio + }, opts.extra.rose); + if (config.pieChartLinePadding == 0) { + config.pieChartLinePadding = roseOption.activeRadius; + } + var centerPosition = { + x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2, + y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2 + }; + var radius = Math.min(centerPosition.x - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, + centerPosition.y - config.pieChartLinePadding - config.pieChartTextPadding); + if (opts.dataLabel) { + radius -= 10; + } else { + //TODO逻辑不对 + radius -= (opts.padding[1] + opts.padding[3]); + } + var minRadius = roseOption.minRadius || radius * 0.5; + + series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process); + + var activeRadius = roseOption.activeRadius; + + series = series.map(function(eachSeries) { + eachSeries._start_ += (roseOption.offsetAngle || 0) * Math.PI / 180; + return eachSeries; + }); + + series.forEach(function(eachSeries, seriesIndex) { + if (opts.tooltip) { + if (opts.tooltip.index == seriesIndex) { + context.beginPath(); + context.setFillStyle(hexToRgb(eachSeries.color, roseOption.activeOpacity || 0.5)); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, activeRadius + eachSeries._radius_, eachSeries._start_, + eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI); + context.closePath(); + context.fill(); + } + } + context.beginPath(); + context.setLineWidth(2 * opts.pixelRatio); + context.lineJoin = "round"; + context.setStrokeStyle('#ffffff'); + context.setFillStyle(eachSeries.color); + context.moveTo(centerPosition.x, centerPosition.y); + context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * + eachSeries._proportion_ * Math.PI); + context.closePath(); + context.fill(); + if (opts.disablePieStroke !== true) { + context.stroke(); + } + }); + + if (opts.dataLabel !== false && process === 1) { + var valid = false; + for (var i = 0, len = series.length; i < len; i++) { + if (series[i].data > 0) { + valid = true; + break; + } + } + + if (valid) { + drawPieText(series, opts, config, context, radius, centerPosition); + } + } + + return { + center: centerPosition, + radius: radius, + series: series + }; +} + +function drawArcbarDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var arcbarOption = assign({}, { + startAngle: 0.75, + endAngle: 0.25, + type: 'default', + width: 12 * opts.pixelRatio + }, opts.extra.arcbar); + + series = getArcbarDataPoints(series, arcbarOption, process); + var centerPosition = { + x: opts.width / 2, + y: opts.height / 2 + }; + var radius = Math.min(centerPosition.x, centerPosition.y); + radius -= 5 * opts.pixelRatio; + radius -= arcbarOption.width / 2; + + //背景颜色 + context.setLineWidth(arcbarOption.width); + context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9'); + context.setLineCap('round'); + context.beginPath(); + if (arcbarOption.type == 'default') { + context.arc(centerPosition.x, centerPosition.y, radius, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * + Math.PI, false); + } else { + context.arc(centerPosition.x, centerPosition.y, radius, 0, 2 * Math.PI, false); + } + context.stroke(); + + for (let i = 0; i < series.length; i++) { + let eachSeries = series[i]; + context.setLineWidth(arcbarOption.width); + context.setStrokeStyle(eachSeries.color); + context.setLineCap('round'); + context.beginPath(); + context.arc(centerPosition.x, centerPosition.y, radius, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * + Math.PI, false); + context.stroke(); + } + + drawRingTitle(opts, config, context, centerPosition); + + return { + center: centerPosition, + radius: radius, + series: series + }; +} + +function drawGaugeDataPoints(categories, series, opts, config, context) { + var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; + var gaugeOption = assign({}, { + startAngle: 0.75, + endAngle: 0.25, + width: 15, + splitLine: { + fixRadius: 0, + splitNumber: 10, + width: 15, + color: '#FFFFFF', + childNumber: 5, + childWidth: 5 + }, + pointer: { + width: 15, + color: 'auto' + } + }, opts.extra.gauge); + + if (gaugeOption.oldAngle == undefined) { + gaugeOption.oldAngle = gaugeOption.startAngle; + } + if (gaugeOption.oldData == undefined) { + gaugeOption.oldData = 0; + } + + categories = getGaugeAxisPoints(categories, gaugeOption.startAngle, gaugeOption.endAngle); + + var centerPosition = { + x: opts.width / 2, + y: opts.height / 2 + }; + var radius = Math.min(centerPosition.x, centerPosition.y); + radius -= 5 * opts.pixelRatio; + radius -= gaugeOption.width / 2; + var innerRadius = radius - gaugeOption.width; + + //画背景 + context.setLineWidth(gaugeOption.width); + context.setLineCap('butt'); + for (let i = 0; i < categories.length; i++) { + let eachCategories = categories[i]; + context.beginPath(); + context.setStrokeStyle(eachCategories.color); + context.arc(centerPosition.x, centerPosition.y, radius, eachCategories._startAngle_ * Math.PI, eachCategories._endAngle_ * + Math.PI, false); + context.stroke(); + } + context.save(); + + //画刻度线 + let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1; + let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; + let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber; + let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius; + let endX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width; + let childendX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.childWidth; + + context.translate(centerPosition.x, centerPosition.y); + context.rotate((gaugeOption.startAngle - 1) * Math.PI); + + for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) { + context.beginPath(); + context.setStrokeStyle(gaugeOption.splitLine.color); + context.setLineWidth(2 * opts.pixelRatio); + context.moveTo(startX, 0); + context.lineTo(endX, 0); + context.stroke(); + context.rotate(splitAngle * Math.PI); + } + context.restore(); + + context.save(); + context.translate(centerPosition.x, centerPosition.y); + context.rotate((gaugeOption.startAngle - 1) * Math.PI); + + for (let i = 0; i < gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; i++) { + context.beginPath(); + context.setStrokeStyle(gaugeOption.splitLine.color); + context.setLineWidth(1 * opts.pixelRatio); + context.moveTo(startX, 0); + context.lineTo(childendX, 0); + context.stroke(); + context.rotate(childAngle * Math.PI); + } + context.restore(); + + //画指针 + series = getGaugeDataPoints(series, categories, gaugeOption, process); + + for (let i = 0; i < series.length; i++) { + let eachSeries = series[i]; + context.save(); + context.translate(centerPosition.x, centerPosition.y); + context.rotate((eachSeries._proportion_ - 1) * Math.PI); + context.beginPath(); + context.setFillStyle(eachSeries.color); + context.moveTo(gaugeOption.pointer.width, 0); + context.lineTo(0, -gaugeOption.pointer.width / 2); + context.lineTo(-innerRadius, 0); + context.lineTo(0, gaugeOption.pointer.width / 2); + context.lineTo(gaugeOption.pointer.width, 0); + context.closePath(); + context.fill(); + context.beginPath(); + context.setFillStyle('#FFFFFF'); + context.arc(0, 0, gaugeOption.pointer.width / 6, 0, 2 * Math.PI, false); + context.fill(); + context.restore(); + } + + if (opts.dataLabel !== false) { + drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context); + } + + drawRingTitle(opts, config, context, centerPosition); + + if (process === 1 && opts.type === 'gauge') { + gaugeOption.oldAngle = series[0]._proportion_; + gaugeOption.oldData = series[0].data; + } + return { + center: centerPosition, + radius: radius, + innerRadius: innerRadius, + categories: categories, + totalAngle: totalAngle + }; +} + +function drawRadarDataPoints(series, opts, config, context) { + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; + var radarOption = assign({},{ + gridColor: '#cccccc', + labelColor: '#666666', + opacity: 0.2 + },opts.extra.radar); + + var coordinateAngle = getRadarCoordinateSeries(opts.categories.length); + + var centerPosition = { + x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2, + y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2 + }; + + var radius = Math.min(centerPosition.x - (getMaxTextListLength(opts.categories) + config.radarLabelTextMargin), + centerPosition.y - config.radarLabelTextMargin); + //TODO逻辑不对 + radius -= opts.padding[1]; + + // draw grid + context.beginPath(); + context.setLineWidth(1 * opts.pixelRatio); + context.setStrokeStyle(radarOption.gridColor); + coordinateAngle.forEach(function(angle) { + var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition); + context.moveTo(centerPosition.x, centerPosition.y); + context.lineTo(pos.x, pos.y); + }); + context.stroke(); + context.closePath(); + // draw split line grid + + var _loop = function _loop(i) { + var startPos = {}; + context.beginPath(); + context.setLineWidth(1 * opts.pixelRatio); + context.setStrokeStyle(radarOption.gridColor); + coordinateAngle.forEach(function(angle, index) { + var pos = convertCoordinateOrigin(radius / config.radarGridCount * i * Math.cos(angle), radius / config.radarGridCount * + i * Math.sin(angle), centerPosition); + if (index === 0) { + startPos = pos; + context.moveTo(pos.x, pos.y); + } else { + context.lineTo(pos.x, pos.y); + } + }); + context.lineTo(startPos.x, startPos.y); + context.stroke(); + context.closePath(); + }; + + for (var i = 1; i <= config.radarGridCount; i++) { + _loop(i); + } + + var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process); + + radarDataPoints.forEach(function(eachSeries, seriesIndex) { + // 绘制区域数据 + context.beginPath(); + context.setFillStyle(hexToRgb(eachSeries.color, radarOption.opacity)); + eachSeries.data.forEach(function(item, index) { + if (index === 0) { + context.moveTo(item.position.x, item.position.y); + } else { + context.lineTo(item.position.x, item.position.y); + } + }); + context.closePath(); + context.fill(); + + if (opts.dataPointShape !== false) { + var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length]; + var points = eachSeries.data.map(function(item) { + return item.position; + }); + drawPointShape(points, eachSeries.color, shape, context, opts); + } + }); + // draw label text + drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context); + + return { + center: centerPosition, + radius: radius, + angleList: coordinateAngle + }; +} + +function drawCanvas(opts, context) { + context.draw(); +} + +var Timing = { + easeIn: function easeIn(pos) { + return Math.pow(pos, 3); + }, + easeOut: function easeOut(pos) { + return Math.pow(pos - 1, 3) + 1; + }, + easeInOut: function easeInOut(pos) { + if ((pos /= 0.5) < 1) { + return 0.5 * Math.pow(pos, 3); + } else { + return 0.5 * (Math.pow(pos - 2, 3) + 2); + } + }, + linear: function linear(pos) { + return pos; + } +}; + +function Animation(opts) { + this.isStop = false; + opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration; + opts.timing = opts.timing || 'linear'; + var delay = 17; + + var createAnimationFrame = function createAnimationFrame() { + if (typeof requestAnimationFrame !== 'undefined') { + return requestAnimationFrame; + } else if (typeof setTimeout !== 'undefined') { + return function(step, delay) { + setTimeout(function() { + var timeStamp = +new Date(); + step(timeStamp); + }, delay); + }; + } else { + return function(step) { + step(null); + }; + } + }; + var animationFrame = createAnimationFrame(); + var startTimeStamp = null; + var _step = function step(timestamp) { + if (timestamp === null || this.isStop === true) { + opts.onProcess && opts.onProcess(1); + opts.onAnimationFinish && opts.onAnimationFinish(); + return; + } + if (startTimeStamp === null) { + startTimeStamp = timestamp; + } + if (timestamp - startTimeStamp < opts.duration) { + var process = (timestamp - startTimeStamp) / opts.duration; + var timingFunction = Timing[opts.timing]; + process = timingFunction(process); + + opts.onProcess && opts.onProcess(process); + animationFrame(_step, delay); + } else { + opts.onProcess && opts.onProcess(1); + opts.onAnimationFinish && opts.onAnimationFinish(); + } + }; + _step = _step.bind(this); + animationFrame(_step, delay); +} + +// stop animation immediately +// and tigger onAnimationFinish +Animation.prototype.stop = function() { + this.isStop = true; +}; + +function drawCharts(type, opts, config, context) { + var _this = this; + var series = opts.series; + var categories = opts.categories; + series = fillSeries(series, opts, config); + var duration = opts.animation ? opts.duration : 0; + this.animationInstance && this.animationInstance.stop(); + var seriesMA = null; + if (type == 'candle') { + let average = assign({}, opts.extra.candle.average); + if (average.show) { + seriesMA = calCandleMA(average.day, average.name, average.color, series[0].data); + seriesMA = fillSeries(seriesMA, opts, config); + opts.seriesMA = seriesMA; + } else if (opts.seriesMA) { + seriesMA = opts.seriesMA = fillSeries(opts.seriesMA, opts, config); + } else { + seriesMA = series; + } + } else { + seriesMA = series; + } + + /* 原始series数据 */ + var _series_ = series; + opts._series_ = _series_; + /* 过滤掉show=false的series */ + series = filterSeries(series); + + //重新计算图表区域 + + opts.area = new Array(4); + //复位绘图区域 + for (let j = 0; j < 4; j++) { + opts.area[j] = opts.padding[j]; + } + + //通过计算三大区域:图例、X轴、Y轴的大小,确定绘图区域 + var _calLegendData = calLegendData(seriesMA, opts, config, opts.chartData), + legendHeight = _calLegendData.area.wholeHeight, + legendWidth = _calLegendData.area.wholeWidth; + //TODO废弃config.legendHeight参数 + config.legendHeight = legendHeight; + switch (opts.legend.position) { + case 'top': + opts.area[0] += legendHeight; + break; + case 'bottom': + opts.area[2] += legendHeight; + break; + case 'left': + opts.area[3] += legendWidth; + break; + case 'right': + opts.area[1] += legendWidth; + break; + } + + let _calYAxisData = calYAxisData(series, opts, config), + yAxisWidth = _calYAxisData.yAxisWidth; + if (opts.type === 'line' || opts.type === 'column' || opts.type === 'area' || opts.type === 'mix' || opts.type === 'candle') { + config.yAxisWidth = yAxisWidth; + opts.area[3] += yAxisWidth; + } else { + config.yAxisWidth = yAxisWidth; + } + opts.chartData.yAxisData = _calYAxisData; + + if (opts.categories && opts.categories.length) { + opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config); + let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing), + xAxisHeight = _calCategoriesData.xAxisHeight, + angle = _calCategoriesData.angle; + config.xAxisHeight = xAxisHeight; + config._xAxisTextAngle_ = angle; + opts.area[2] += xAxisHeight; + opts.chartData.categoriesData = _calCategoriesData; + } + + //计算右对齐偏移距离 + if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) { + let offsetLeft = 0, + xAxisPoints = opts.chartData.xAxisData.xAxisPoints, + startX = opts.chartData.xAxisData.startX, + endX = opts.chartData.xAxisData.endX, + eachSpacing = opts.chartData.xAxisData.eachSpacing; + let totalWidth = eachSpacing * (xAxisPoints.length - 1); + let screenWidth = endX - startX; + offsetLeft = screenWidth - totalWidth; + _this.scrollOption = { + currentOffset: offsetLeft, + startTouchX: offsetLeft, + distance: 0, + lastMoveTime: 0 + }; + opts._scrollDistance_ = offsetLeft; + } + + if (type === 'pie' || type === 'ring' || type === 'rose') { + config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(_series_); + } + + switch (type) { + case 'line': + this.animationInstance = new Animation({ + timing: 'easeIn', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process), + xAxisPoints = _drawLineDataPoints.xAxisPoints, + calPoints = _drawLineDataPoints.calPoints, + eachSpacing = _drawLineDataPoints.eachSpacing, + minRange = _drawLineDataPoints.minRange, + maxRange = _drawLineDataPoints.maxRange; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(minRange, maxRange, opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'mix': + this.animationInstance = new Animation({ + timing: 'easeIn', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, process), + xAxisPoints = _drawMixDataPoints.xAxisPoints, + calPoints = _drawMixDataPoints.calPoints, + eachSpacing = _drawMixDataPoints.eachSpacing, + minRange = _drawMixDataPoints.minRange, + maxRange = _drawMixDataPoints.maxRange; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(minRange, maxRange, opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'column': + this.animationInstance = new Animation({ + timing: 'easeIn', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process), + xAxisPoints = _drawColumnDataPoints.xAxisPoints, + calPoints = _drawColumnDataPoints.calPoints, + eachSpacing = _drawColumnDataPoints.eachSpacing, + minRange = _drawColumnDataPoints.minRange, + maxRange = _drawColumnDataPoints.maxRange; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(minRange, maxRange, opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'area': + this.animationInstance = new Animation({ + timing: 'easeIn', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process), + xAxisPoints = _drawAreaDataPoints.xAxisPoints, + calPoints = _drawAreaDataPoints.calPoints, + eachSpacing = _drawAreaDataPoints.eachSpacing, + minRange = _drawAreaDataPoints.minRange, + maxRange = _drawAreaDataPoints.maxRange; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(minRange, maxRange, opts, config, context); + } + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'ring': + case 'pie': + this.animationInstance = new Animation({ + timing: 'easeInOut', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'rose': + this.animationInstance = new Animation({ + timing: 'easeInOut', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.pieData = drawRoseDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'radar': + this.animationInstance = new Animation({ + timing: 'easeInOut', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.radarData = drawRadarDataPoints(series, opts, config, context, process); + drawLegend(opts.series, opts, config, context, opts.chartData); + drawToolTipBridge(opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'arcbar': + this.animationInstance = new Animation({ + timing: 'easeInOut', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.arcbarData = drawArcbarDataPoints(series, opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'gauge': + this.animationInstance = new Animation({ + timing: 'easeInOut', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + opts.chartData.gaugeData = drawGaugeDataPoints(categories, series, opts, config, context, process); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + case 'candle': + this.animationInstance = new Animation({ + timing: 'easeIn', + duration: duration, + onProcess: function onProcess(process) { + context.clearRect(0, 0, opts.width, opts.height); + if (opts.rotate) { + contextRotate(context, opts); + } + drawYAxisGrid(categories, opts, config, context); + drawXAxis(categories, opts, config, context); + var _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, process), + xAxisPoints = _drawCandleDataPoints.xAxisPoints, + calPoints = _drawCandleDataPoints.calPoints, + eachSpacing = _drawCandleDataPoints.eachSpacing, + minRange = _drawCandleDataPoints.minRange, + maxRange = _drawCandleDataPoints.maxRange; + opts.chartData.xAxisPoints = xAxisPoints; + opts.chartData.calPoints = calPoints; + opts.chartData.eachSpacing = eachSpacing; + drawYAxis(series, opts, config, context); + if (opts.enableMarkLine !== false && process === 1) { + drawMarkLine(minRange, maxRange, opts, config, context); + } + if (seriesMA) { + drawLegend(seriesMA, opts, config, context, opts.chartData); + } else { + drawLegend(opts.series, opts, config, context, opts.chartData); + } + drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints); + drawCanvas(opts, context); + }, + onAnimationFinish: function onAnimationFinish() { + _this.event.trigger('renderComplete'); + } + }); + break; + } +} + +// simple event implement + +function Event() { + this.events = {}; +} + +Event.prototype.addEventListener = function(type, listener) { + this.events[type] = this.events[type] || []; + this.events[type].push(listener); +}; + +Event.prototype.trigger = function() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var type = args[0]; + var params = args.slice(1); + if (!!this.events[type]) { + this.events[type].forEach(function(listener) { + try { + listener.apply(null, params); + } catch (e) { + console.error(e); + } + }); + } +}; + +var Charts = function Charts(opts) { + opts.pixelRatio = opts.pixelRatio ? opts.pixelRatio : 1; + opts.fontSize = opts.fontSize ? opts.fontSize * opts.pixelRatio : 13 * opts.pixelRatio; + opts.title = assign({}, opts.title); + opts.subtitle = assign({}, opts.subtitle); + opts.duration = opts.duration ? opts.duration : 1000; + opts.yAxis = assign({}, { + gridType: 'solid', + dashLength: 4 * opts.pixelRatio + }, opts.yAxis); + opts.xAxis = assign({}, { + rotateLabel: false, + type: 'calibration', + gridType: 'solid', + dashLength: 4 * opts.pixelRatio, + scrollAlign: 'left' + }, opts.xAxis); + opts.legend = assign({}, { + show: true, + position: 'bottom', + float: 'center', + backgroundColor: 'rgba(0,0,0,0)', + borderColor: 'rgba(0,0,0,0)', + borderWidth: 0, + padding: 5, + margin: 5, + itemGap: 10, + fontSize: opts.fontSize, + lineHeight: opts.fontSize, + fontColor: '#333333', + format: {}, + hiddenColor: '#CECECE' + }, opts.legend); + opts.legend.borderWidth = opts.legend.borderWidth * opts.pixelRatio; + opts.legend.itemGap = opts.legend.itemGap * opts.pixelRatio; + opts.legend.padding = opts.legend.padding * opts.pixelRatio; + opts.legend.margin = opts.legend.margin * opts.pixelRatio; + opts.extra = assign({}, opts.extra); + opts.rotate = opts.rotate ? true : false; + opts.animation = opts.animation ? true : false; + + let config$$1 = assign({}, config); + config$$1.colors = opts.colors ? opts.colors : config$$1.colors; + config$$1.yAxisTitleWidth = opts.yAxis.disabled !== true && opts.yAxis.title ? config$$1.yAxisTitleWidth : 0; + if (opts.type == 'pie' || opts.type == 'ring') { + config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio; + } + if (opts.type == 'rose') { + config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.rose.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio; + } + config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding * opts.pixelRatio; + config$$1.yAxisSplit = opts.yAxis.splitNumber ? opts.yAxis.splitNumber : config.yAxisSplit; + + //屏幕旋转 + config$$1.rotate = opts.rotate; + if (opts.rotate) { + let tempWidth = opts.width; + let tempHeight = opts.height; + opts.width = tempHeight; + opts.height = tempWidth; + } + + //适配高分屏 + opts.padding = opts.padding ? opts.padding : config$$1.padding; + for (let i = 0; i < 4; i++) { + opts.padding[i] *= opts.pixelRatio; + } + config$$1.yAxisWidth = config.yAxisWidth * opts.pixelRatio; + config$$1.xAxisHeight = config.xAxisHeight * opts.pixelRatio; + if (opts.enableScroll && opts.xAxis.scrollShow) { + config$$1.xAxisHeight += 6 * opts.pixelRatio; + } + config$$1.xAxisLineHeight = config.xAxisLineHeight * opts.pixelRatio; + config$$1.legendHeight = config.legendHeight * opts.pixelRatio; + config$$1.fontSize = opts.fontSize; + config$$1.titleFontSize = config.titleFontSize * opts.pixelRatio; + config$$1.subtitleFontSize = config.subtitleFontSize * opts.pixelRatio; + config$$1.toolTipPadding = config.toolTipPadding * opts.pixelRatio; + config$$1.toolTipLineHeight = config.toolTipLineHeight * opts.pixelRatio; + config$$1.columePadding = config.columePadding * opts.pixelRatio; + opts.$this = opts.$this ? opts.$this : this; + this.context = uni.createCanvasContext(opts.canvasId, opts.$this); + /* 兼容原生H5 + this.context = document.getElementById(opts.canvasId).getContext("2d"); + this.context.setStrokeStyle = function(e){ return this.strokeStyle=e; } + this.context.setLineWidth = function(e){ return this.lineWidth=e; } + this.context.setLineCap = function(e){ return this.lineCap=e; } + this.context.setFontSize = function(e){ return this.font=e+"px sans-serif"; } + this.context.setFillStyle = function(e){ return this.fillStyle=e; } + this.context.draw = function(){ } + */ + opts.chartData = {}; + this.event = new Event(); + this.scrollOption = { + currentOffset: 0, + startTouchX: 0, + distance: 0, + lastMoveTime: 0 + }; + + this.opts = opts; + this.config = config$$1; + + drawCharts.call(this, opts.type, opts, config$$1, this.context); +}; + +Charts.prototype.updateData = function() { + let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.opts = assign({}, this.opts, data); + let scrollPosition = data.scrollPosition || 'current'; + switch (scrollPosition) { + case 'current': + this.opts._scrollDistance_ = this.scrollOption.currentOffset; + break; + case 'left': + this.opts._scrollDistance_ = 0; + this.scrollOption = { + currentOffset: 0, + startTouchX: 0, + distance: 0, + lastMoveTime: 0 + }; + break; + case 'right': + let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config), + yAxisWidth = _calYAxisData.yAxisWidth; + this.config.yAxisWidth = yAxisWidth; + let offsetLeft = 0; + let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), + xAxisPoints = _getXAxisPoints0.xAxisPoints, + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; + let totalWidth = eachSpacing * (xAxisPoints.length - 1); + let screenWidth = endX - startX; + offsetLeft = screenWidth - totalWidth; + this.scrollOption = { + currentOffset: offsetLeft, + startTouchX: offsetLeft, + distance: 0, + lastMoveTime: 0 + }; + this.opts._scrollDistance_ = offsetLeft; + break; + } + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context); +}; + +Charts.prototype.zoom = function() { + var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.opts.xAxis.itemCount; + if (this.opts.enableScroll !== true) { + console.log('请启用滚动条后使用!') + return; + } + //当前屏幕中间点 + let centerPoint = Math.round(Math.abs(this.scrollOption.currentOffset) / this.opts.chartData.eachSpacing) + Math.round( + this.opts.xAxis.itemCount / 2); + this.opts.animation = false; + this.opts.xAxis.itemCount = val.itemCount; + //重新计算x轴偏移距离 + let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config), + yAxisWidth = _calYAxisData.yAxisWidth; + this.config.yAxisWidth = yAxisWidth; + let offsetLeft = 0; + let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), + xAxisPoints = _getXAxisPoints0.xAxisPoints, + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; + let centerLeft = eachSpacing * centerPoint; + let screenWidth = endX - startX; + let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1); + offsetLeft = screenWidth / 2 - centerLeft; + if (offsetLeft > 0) { + offsetLeft = 0; + } + if (offsetLeft < MaxLeft) { + offsetLeft = MaxLeft; + } + this.scrollOption = { + currentOffset: offsetLeft, + startTouchX: offsetLeft, + distance: 0, + lastMoveTime: 0 + }; + this.opts._scrollDistance_ = offsetLeft; + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context); +}; + +Charts.prototype.stopAnimation = function() { + this.animationInstance && this.animationInstance.stop(); +}; + +Charts.prototype.addEventListener = function(type, listener) { + this.event.addEventListener(type, listener); +}; + +Charts.prototype.getCurrentDataIndex = function(e) { + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches) { + let _touches$ = getTouches(touches, this.opts, e); + if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose') { + return findPieChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.pieData); + } else if (this.opts.type === 'radar') { + return findRadarChartCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.radarData, this.opts.categories.length); + } else { + return findCurrentIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.xAxisPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset)); + } + } + return -1; +}; + +Charts.prototype.getLegendDataIndex = function(e) { + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches) { + let _touches$ = getTouches(touches, this.opts, e); + return findLegendIndex({ + x: _touches$.x, + y: _touches$.y + }, this.opts.chartData.legendData); + } + return -1; +}; + +Charts.prototype.touchLegend = function(e) { + var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches) { + var _touches$ = getTouches(touches, this.opts, e); + var index = this.getLegendDataIndex(e); + if (index >= 0) { + this.opts.series[index].show = !this.opts.series[index].show; + this.opts.animation = option.animation ? true : false; + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context); + } + } + +}; + +Charts.prototype.showToolTip = function(e) { + var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (!touches) { + console.log("touchError"); + } + var _touches$ = getTouches(touches, this.opts, e); + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + if (this.opts.type === 'line' || this.opts.type === 'area' || this.opts.type === 'column') { + var index = this.getCurrentDataIndex(e); + if (index > -1) { + var seriesData = getSeriesDataItem(this.opts.series, index); + if (seriesData.length !== 0) { + var _getToolTipData = getToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories, + option), + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; + offset.y = _touches$.y; + opts.tooltip = { + textList: textList, + offset: offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'mix') { + var index = this.getCurrentDataIndex(e); + if (index > -1) { + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + var seriesData = getSeriesDataItem(this.opts.series, index); + if (seriesData.length !== 0) { + var _getMixToolTipData = getMixToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories, + option), + textList = _getMixToolTipData.textList, + offset = _getMixToolTipData.offset; + offset.y = _touches$.y; + opts.tooltip = { + textList: textList, + offset: offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'candle') { + var index = this.getCurrentDataIndex(e); + if (index > -1) { + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + var seriesData = getSeriesDataItem(this.opts.series, index); + if (seriesData.length !== 0) { + var _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts.chartData.calPoints, + index, this.opts.categories, this.opts.extra.candle, option), + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; + offset.y = _touches$.y; + opts.tooltip = { + textList: textList, + offset: offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose') { + var index = this.getCurrentDataIndex(e); + if (index > -1) { + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + var seriesData = this.opts.series[index]; + var textList = [{ + text: option.format ? option.format(seriesData) : seriesData.name + ': ' + seriesData.data, + color: seriesData.color + }]; + var offset = { + x: _touches$.x, + y: _touches$.y + }; + opts.tooltip = { + textList: textList, + offset: offset, + option: option, + index: index + }; + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } + if (this.opts.type === 'radar') { + var index = this.getCurrentDataIndex(e); + if (index > -1) { + var currentOffset = this.scrollOption.currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset, + animation: false + }); + var seriesData = getSeriesDataItem(this.opts.series, index); + if (seriesData.length !== 0) { + var textList = seriesData.map(function(item) { + return { + text: option.format ? option.format(item) : item.name + ': ' + item.data, + color: item.color + }; + }); + var offset = { + x: _touches$.x, + y: _touches$.y + }; + opts.tooltip = { + textList: textList, + offset: offset, + option: option, + index: index + }; + } + } + drawCharts.call(this, opts.type, opts, this.config, this.context); + } +}; + +Charts.prototype.translate = function(distance) { + this.scrollOption = { + currentOffset: distance, + startTouchX: distance, + distance: 0, + lastMoveTime: 0 + }; + let opts = assign({}, this.opts, { + _scrollDistance_: distance, + animation: false + }); + drawCharts.call(this, this.opts.type, opts, this.config, this.context); +}; + +Charts.prototype.scrollStart = function(e) { + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + var _touches$ = getTouches(touches, this.opts, e); + if (touches && this.opts.enableScroll === true) { + this.scrollOption.startTouchX = _touches$.x; + } +}; + +Charts.prototype.scroll = function(e) { + if (this.scrollOption.lastMoveTime === 0) { + this.scrollOption.lastMoveTime = Date.now(); + } + let Limit = this.opts.extra.touchMoveLimit || 20; + let currMoveTime = Date.now(); + let duration = currMoveTime - this.scrollOption.lastMoveTime; + if (duration < Math.floor(1000 / Limit)) return; + this.scrollOption.lastMoveTime = currMoveTime; + var touches = null; + if (e.changedTouches) { + touches = e.changedTouches[0]; + } else { + touches = e.mp.changedTouches[0]; + } + if (touches && this.opts.enableScroll === true) { + var _touches$ = getTouches(touches, this.opts, e); + var _distance; + _distance = _touches$.x - this.scrollOption.startTouchX; + var currentOffset = this.scrollOption.currentOffset; + var validDistance = calValidDistance(currentOffset + _distance, this.opts.chartData, this.config, this.opts); + this.scrollOption.distance = _distance = validDistance - currentOffset; + var opts = assign({}, this.opts, { + _scrollDistance_: currentOffset + _distance, + animation: false + }); + drawCharts.call(this, opts.type, opts, this.config, this.context); + return currentOffset + _distance; + } +}; + +Charts.prototype.scrollEnd = function(e) { + if (this.opts.enableScroll === true) { + var _scrollOption = this.scrollOption, + currentOffset = _scrollOption.currentOffset, + distance = _scrollOption.distance; + this.scrollOption.currentOffset = currentOffset + distance; + this.scrollOption.distance = 0; + } +}; +if (typeof module === "object" && typeof module.exports === "object") { + module.exports = Charts; + //export default Charts;//建议使用nodejs的module导出方式,如报错请使用export方式导出 +} diff --git a/js_sdk/u-charts/u-charts/u-charts.min.js b/js_sdk/u-charts/u-charts/u-charts.min.js new file mode 100644 index 0000000..817caaf --- /dev/null +++ b/js_sdk/u-charts/u-charts/u-charts.min.js @@ -0,0 +1 @@ +'use strict';var config={yAxisWidth:15,yAxisSplit:5,xAxisHeight:15,xAxisLineHeight:15,legendHeight:15,yAxisTitleWidth:15,padding:[10,10,10,10],pixelRatio:1,rotate:!1,columePadding:3,fontSize:13,dataPointShape:["circle","circle","circle","circle"],colors:["#1890ff","#2fc25b","#facc14","#f04864","#8543e0","#90ed7d"],pieChartLinePadding:15,pieChartTextPadding:5,xAxisTextPadding:3,titleColor:"#333333",titleFontSize:20,subtitleColor:"#999999",subtitleFontSize:15,toolTipPadding:3,toolTipBackground:"#000000",toolTipOpacity:.7,toolTipLineHeight:20,radarGridCount:3,radarLabelTextMargin:15,gaugeLabelTextMargin:15};let assign=Object.assign?Object.assign:function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t,i=Object(e),a=1;aMath.abs(e-t)},isSameSign:function(e,t){var i=Math.abs;return i(e)===e&&i(t)===t||i(e)!==e&&i(t)!==t},isSameXCoordinateArea:function(e,t){return this.isSameSign(e.x,t.x)},isCollision:function(e,t){e.end={},e.end.x=e.start.x+e.width,e.end.y=e.start.y-e.height,t.end={},t.end.x=t.start.x+t.width,t.end.y=t.start.y-t.height;var i=t.start.x>e.end.x||t.end.xe.start.y||t.start.yi;)i*=10,a*=10;for(e="upper"===t?Math.ceil(e*a):Math.floor(e*a);0!=e%i;)"upper"===t?e++:e--;return e/a}function calCandleMA(e,t,i,a){let o=[];for(let n,l=0;l=n-o&&(l=o-n),l}function isInAngleRange(e,t,i){function a(e){for(;0>e;)e+=2*o;for(;e>2*o;)e-=2*o;return e}var o=Math.PI;return e=a(e),t=a(t),i=a(i),t>i&&(i+=2*o,e=t&&e<=i}function calRotateTranslate(e,t,i){var a=e,o=i-t,n=a+(i-o-a)/1.4142135623730951;n*=-1;return{transX:n,transY:(i-o)*(1.4142135623730951-1)-(i-o-a)/1.4142135623730951}}function createCurveControlPoints(e,t){function i(e,t){return!!(e[t-1]&&e[t+1])&&(e[t].y>=Math.max(e[t-1].y,e[t+1].y)||e[t].y<=Math.min(e[t-1].y,e[t+1].y))}var o=.2,a=.2,n=null,l=null,r=null,s=null;if(1>t?(n=e[0].x+(e[1].x-e[0].x)*o,l=e[0].y+(e[1].y-e[0].y)*o):(n=e[t].x+(e[t+1].x-e[t-1].x)*o,l=e[t].y+(e[t+1].y-e[t-1].y)*o),t>e.length-3){var d=e.length-1;r=e[d].x-(e[d].x-e[d-1].x)*a,s=e[d].y-(e[d].y-e[d-1].y)*a}else r=e[t+1].x-(e[t+2].x-e[t].x)*a,s=e[t+1].y-(e[t+2].y-e[t].y)*a;return i(e,t+1)&&(s=e[t+1].y),i(e,t)&&(l=e[t].y),{ctrA:{x:n,y:l},ctrB:{x:r,y:s}}}function convertCoordinateOrigin(e,t,i){return{x:i.x+e,y:i.y-t}}function avoidCollision(e,t){if(t)for(;util.isCollision(e,t);)0e.start.x?e.start.y++:0t.data[1]-t.data[0]?s[1]=r:(t.data[0]e[o-1][1]&&(s[2]=l),t.data[3]t&&(n=i)}),n}function findLegendIndex(e,t){let i=-1;if(isInExactLegendArea(e,t.area)){let a=t.points,o=-1;for(let t,n=0,l=a.length;nn[0]&&e.xn[1]&&e.yt.start.x&&e.xt.start.y&&e.yt.area[3]&&e.y>t.area[0]&&e.ye&&(e+=2*a),e>2*a&&(e-=2*a),e},r=Math.atan2(t.center.y-e.y,e.x-t.center.x);r=-1*r,0>r&&(r+=2*a);var s=t.angleList.map(function(e){return e=l(-1*e),e});s.forEach(function(e,t){var i=l(e-o/2),s=l(e+o/2);s=i&&r<=s||r+2*a>=i&&r+2*a<=s)&&(n=t)})}return n}function findPieChartCurrentIndex(e,t){var a=-1;if(isInExactPieChartArea(e,t.center,t.radius)){var o=Math.atan2(t.center.y-e.y,e.x-t.center.x);o=-o;for(var n,l=0,r=t.series.length;lt.width-t.padding[1]-t.padding[3]?(a.push(g),p.push(n-t.legend.itemGap),n=l,g=[i]):(n+=l,g.push(i))}if(g.length){a.push(g),p.push(n-t.legend.itemGap),l.widthArr=p;let e=o.apply(null,p);switch(t.legend.float){case"left":l.area.start.x=t.padding[3],l.area.end.x=t.padding[3]+2*r;break;case"right":l.area.start.x=t.width-t.padding[1]-e-2*r,l.area.end.x=t.width-t.padding[1];break;default:l.area.start.x=(t.width-e)/2-r,l.area.end.x=(t.width+e)/2+r;}l.area.width=e+2*r,l.area.wholeWidth=e+2*r,l.area.height=a.length*x+2*r,l.area.wholeHeight=a.length*x+2*r+2*s,l.points=a}}else{let i=e.length,a=t.height-t.padding[0]-t.padding[2]-2*s-2*r,o=Math.min(n(a/x),i);switch(l.area.height=o*x+2*r,l.area.wholeHeight=o*x+2*r,t.legend.float){case"top":l.area.start.y=t.padding[0]+s,l.area.end.y=t.padding[0]+s+l.area.height;break;case"bottom":l.area.start.y=t.height-t.padding[2]-s-l.area.height,l.area.end.y=t.height-t.padding[2]-s;break;default:l.area.start.y=(t.height-l.area.height)/2,l.area.end.y=(t.height+l.area.height)/2;}let p=0==i%o?i/o:n(i/o+1),g=[];for(let t,a=0;aa&&(a=e);l.widthArr.push(a),l.heightArr.push(i.length*x+2*r)}let e=0;for(let t=0;ta&&(o.angle=45*Math.PI/180,o.xAxisHeight=2*i.xAxisTextPadding+l*Math.sin(o.angle)),o}function getRadarDataPoints(e,t,i,a,o){var n=Math.max,l=5=a.oldData?(n._endAngle_-n._oldAngle_)*o+a.oldAngle:n._oldAngle_-(n._oldAngle_-n._endAngle_)*o,2<=n._proportion_&&(n._proportion_%=2)}return e}function getPieTextMaxLength(e){e=getPieDataPoints(e);let t=0;for(let a=0;a=e.width&&(e.width=1),e.x+=(a+.5-i/2)*e.width,e)})}function fixColumeMeterData(e,t,i,a,o,n,l){return e.map(function(e){return null===e?null:(e.width=Math.ceil((t-2*o.columePadding)/2),n.extra.column&&n.extra.column.width&&0<+n.extra.column.width&&(e.width=Math.min(e.width,+n.extra.column.width)),0s.x&&(h-=measureText(a.categories[r]||"")),n.beginPath(),n.setFontSize(o.fontSize),n.setFillStyle(l.labelColor||"#666666"),n.fillText(a.categories[r]||"",h,c+o.fontSize/2),n.closePath(),n.stroke()})}function drawPieText(e,t,a,o,i,n){var l=Math.cos,r=Math.sin,s=Math.min,d=Math.max,h=Math.PI,c=a.pieChartLinePadding,x=[],p=null,g=e.map(function(e){var t=2*h-(e._start_+2*h*e._proportion_/2),i=e.format?e.format(+e._proportion_.toFixed(2)):util.toFixed(100*e._proportion_)+"%",a=e.color,o=e._radius_;return{arc:t,text:i,color:a,radius:o,textColor:e.textColor,textSize:e.textSize}});for(let h=0;ht?m=d(f,p.start.y):0y&&(y-=u);let S={lineStart:{x:o,y:n},lineEnd:{x:t,y:i},start:{x:y,y:m},width:u,height:a.fontSize,text:e.text,color:e.color,textColor:e.textColor,textSize:e.textSize};p=avoidCollision(S,p),x.push(p)}for(let l=0;le.start.x?s.x+e.width:s.x,c=0>e.start.x?s.x-5:s.x+5;o.quadraticCurveTo(r.x,r.y,d,s.y),o.moveTo(i.x,i.y),o.stroke(),o.closePath(),o.beginPath(),o.moveTo(s.x+e.width,s.y),o.arc(d,s.y,2,0,2*h),o.closePath(),o.fill(),o.beginPath(),o.setFontSize(e.textSize||a.fontSize),o.setFillStyle(e.textColor||"#666666"),o.fillText(e.text,c,s.y+3),o.closePath(),o.stroke(),o.closePath()}}function drawToolTipSplitLine(e,t,i,a){var o=t.extra.tooltip||{};o.gridType=null==o.gridType?"solid":o.gridType,o.dashLength=null==o.dashLength?4:o.dashLength;var n=t.area[0],l=t.height-t.area[2];if("dash"==o.gridType&&a.setLineDash([o.dashLength,o.dashLength]),a.setStrokeStyle(o.gridColor||"#cccccc"),a.setLineWidth(1*t.pixelRatio),a.beginPath(),a.moveTo(e,n),a.lineTo(e,l),a.stroke(),a.setLineDash([]),o.xAxisLabel){let n=t.categories[t.tooltip.index];a.setFontSize(i.fontSize);let r=measureText(n,i.fontSize),s=e-i.toolTipPadding-.5*r,d=l;a.beginPath(),a.setFillStyle(hexToRgb(o.labelBgColor||i.toolTipBackground,o.labelBgOpacity||i.toolTipOpacity)),a.setStrokeStyle(o.labelBgColor||i.toolTipBackground),a.setLineWidth(1*t.pixelRatio),a.rect(s,d,r+2*i.toolTipPadding,i.fontSize+2*i.toolTipPadding),a.closePath(),a.stroke(),a.fill(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(o.labelFontColor||i.fontColor),a.fillText(n,s+2*i.toolTipPadding,d+i.toolTipPadding+i.fontSize),a.closePath(),a.stroke()}}function drawMarkLine(e,t,a,i,o){let n=assign({},{type:"solid",dashLength:4,data:[]},a.extra.markLine),l=a.area[3],r=a.width-a.padding[1],s=calMarkLineData(e,t,n.data,a);for(let d,h=0;hi.width&&(h=!0),p+t.y>i.height&&(t.y=i.height-p),o.beginPath(),o.setFillStyle(hexToRgb(l.bgColor||a.toolTipBackground,l.bgOpacity||a.toolTipOpacity)),h?(o.moveTo(t.x,t.y+10*i.pixelRatio),o.lineTo(t.x-d,t.y+10*i.pixelRatio-5*i.pixelRatio),o.lineTo(t.x-d,t.y),o.lineTo(t.x-d-n(x),t.y),o.lineTo(t.x-d-n(x),t.y+p),o.lineTo(t.x-d,t.y+p),o.lineTo(t.x-d,t.y+10*i.pixelRatio+5*i.pixelRatio),o.lineTo(t.x,t.y+10*i.pixelRatio)):(o.moveTo(t.x,t.y+10*i.pixelRatio),o.lineTo(t.x+d,t.y+10*i.pixelRatio-5*i.pixelRatio),o.lineTo(t.x+d,t.y),o.lineTo(t.x+d+n(x),t.y),o.lineTo(t.x+d+n(x),t.y+p),o.lineTo(t.x+d,t.y+p),o.lineTo(t.x+d,t.y+10*i.pixelRatio+5*i.pixelRatio),o.lineTo(t.x,t.y+10*i.pixelRatio)),o.closePath(),o.fill(),e.forEach(function(e,i){if(null!==e.color){o.beginPath(),o.setFillStyle(e.color);var n=t.x+d+2*a.toolTipPadding,l=t.y+(a.toolTipLineHeight-a.fontSize)/2+a.toolTipLineHeight*i+a.toolTipPadding+1;h&&(n=t.x-x-d+2*a.toolTipPadding),o.fillRect(n,l,r,a.fontSize),o.closePath()}}),e.forEach(function(e,i){var n=t.x+d+2*a.toolTipPadding+r+s;h&&(n=t.x-x-d+2*a.toolTipPadding+ +r+s);var c=t.y+(a.toolTipLineHeight-a.fontSize)/2+a.toolTipLineHeight*i+a.toolTipPadding;o.beginPath(),o.setFontSize(a.fontSize),o.setFillStyle(l.fontColor),o.fillText(e.text,n,c+a.fontSize),o.closePath(),o.stroke()})}function drawYAxisTitle(e,t,i,a){var o=i.xAxisHeight+(t.height-i.xAxisHeight-measureText(e))/2;a.save(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(t.yAxis.titleFontColor||"#333333"),a.translate(0,t.height),a.rotate(-90*Math.PI/180),a.fillText(e,o,t.padding[3]+.5*i.fontSize),a.closePath(),a.stroke(),a.restore()}function drawColumnDataPoints(e,t,i,a){let o=4t._scrollDistance_&&o.fillRect(0,0,r,h),o.fillRect(s,0,t.width,h),o.closePath(),o.stroke();for(var c=[],x=0;x<=a.yAxisSplit;x++)c.push(t.area[0]+l*x);var p=t.yAxis.fontSize||a.fontSize;e.forEach(function(e,i){var n=c[i]?c[i]:d;o.beginPath(),o.setFontSize(p),o.setFillStyle(t.yAxis.fontColor||"#666666"),o.fillText(e,t.area[3]-a.yAxisWidth,n+p/2),o.closePath(),o.stroke()}),t.yAxis.title&&drawYAxisTitle(t.yAxis.title,t,a,o)}}function drawLegend(e,t,i,a,o){if(!1===t.legend.show)return;let n=o.legendData,l=n.points,r=n.area,s=t.legend.padding,d=t.legend.fontSize,h=15*t.pixelRatio,c=5*t.pixelRatio,x=t.legend.itemGap,p=Math.max(t.legend.lineHeight*t.pixelRatio,d);a.beginPath(),a.setLineWidth(t.legend.borderWidth),a.setStrokeStyle(t.legend.borderColor),a.setFillStyle(t.legend.backgroundColor),a.moveTo(r.start.x,r.start.y),a.rect(r.start.x,r.start.y,r.width,r.height),a.closePath(),a.fill(),a.stroke(),l.forEach(function(e,o){let l=0,g=0;l=n.widthArr[o],g=n.heightArr[o];let y=0,f=0;"top"==t.legend.position||"bottom"==t.legend.position?(y=r.start.x+(r.width-l)/2,f=r.start.y+s+o*p):(l=0==o?0:n.widthArr[o-1],y=r.start.x+s+l,f=r.start.y+s+(r.height-g)/2),a.setFontSize(i.fontSize);for(let n,l=0;l(e/=.5)?.5*t(e,3):.5*(t(e-2,3)+2)},linear:function(e){return e}};function Animation(e){this.isStop=!1,e.duration="undefined"==typeof e.duration?1e3:e.duration,e.timing=e.timing||"linear";var t=function(){return"undefined"==typeof requestAnimationFrame?"undefined"==typeof setTimeout?function(e){e(null)}:function(e,t){setTimeout(function(){var t=+new Date;e(t)},t)}:requestAnimationFrame}(),i=null,a=function(o){if(null===o||!0===this.isStop)return e.onProcess&&e.onProcess(1),void(e.onAnimationFinish&&e.onAnimationFinish());if(null===i&&(i=o),o-io;o++)t.area[o]=t.padding[o];var h=calLegendData(s,t,i,t.chartData),c=h.area.wholeHeight,x=h.area.wholeWidth;switch(i.legendHeight=c,t.legend.position){case"top":t.area[0]+=c;break;case"bottom":t.area[2]+=c;break;case"left":t.area[3]+=x;break;case"right":t.area[1]+=x;}let p=calYAxisData(n,t,i),g=p.yAxisWidth;if("line"===t.type||"column"===t.type||"area"===t.type||"mix"===t.type||"candle"===t.type?(i.yAxisWidth=g,t.area[3]+=g):i.yAxisWidth=g,t.chartData.yAxisData=p,t.categories&&t.categories.length){t.chartData.xAxisData=getXAxisPoints(t.categories,t,i);let e=calCategoriesData(t.categories,t,i,t.chartData.xAxisData.eachSpacing),a=e.xAxisHeight,o=e.angle;i.xAxisHeight=a,i._xAxisTextAngle_=o,t.area[2]+=a,t.chartData.categoriesData=e}if(t.enableScroll&&"right"==t.xAxis.scrollAlign&&void 0===t._scrollDistance_){let e=0,i=t.chartData.xAxisData.xAxisPoints,a=t.chartData.xAxisData.startX,n=t.chartData.xAxisData.endX,l=t.chartData.xAxisData.eachSpacing,r=l*(i.length-1);e=n-a-r,o.scrollOption={currentOffset:e,startTouchX:e,distance:0,lastMoveTime:0},t._scrollDistance_=e}("pie"===e||"ring"===e||"rose"===e)&&(i._pieTextMaxLength_=!1===t.dataLabel?0:getPieTextMaxLength(d)),"line"===e?this.animationInstance=new Animation({timing:"easeIn",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),drawYAxisGrid(l,t,i,a),drawXAxis(l,t,i,a);var o=drawLineDataPoints(n,t,i,a,e),r=o.xAxisPoints,s=o.calPoints,d=o.eachSpacing;t.chartData.xAxisPoints=r,t.chartData.calPoints=s,t.chartData.eachSpacing=d,drawYAxis(n,t,i,a),drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e,d,r),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"mix"===e?this.animationInstance=new Animation({timing:"easeIn",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),drawYAxisGrid(l,t,i,a),drawXAxis(l,t,i,a);var o=drawMixDataPoints(n,t,i,a,e),r=o.xAxisPoints,s=o.calPoints,d=o.eachSpacing;t.chartData.xAxisPoints=r,t.chartData.calPoints=s,t.chartData.eachSpacing=d,drawYAxis(n,t,i,a),drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e,d,r),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"column"===e?this.animationInstance=new Animation({timing:"easeIn",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),drawYAxisGrid(l,t,i,a),drawYAxis(n,t,i,a),drawXAxis(l,t,i,a);var o=drawColumnDataPoints(n,t,i,a,e),r=o.xAxisPoints,s=o.calPoints,d=o.eachSpacing;t.chartData.xAxisPoints=r,t.chartData.calPoints=s,t.chartData.eachSpacing=d,drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e,d,r),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"area"===e?this.animationInstance=new Animation({timing:"easeIn",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),drawYAxisGrid(l,t,i,a),drawXAxis(l,t,i,a);var o=drawAreaDataPoints(n,t,i,a,e),r=o.xAxisPoints,s=o.calPoints,d=o.eachSpacing;t.chartData.xAxisPoints=r,t.chartData.calPoints=s,t.chartData.eachSpacing=d,drawYAxis(n,t,i,a),drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e,d,r),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"ring"===e||"pie"===e?this.animationInstance=new Animation({timing:"easeInOut",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),t.chartData.pieData=drawPieDataPoints(n,t,i,a,e),drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"rose"===e?this.animationInstance=new Animation({timing:"easeInOut",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),t.chartData.pieData=drawRoseDataPoints(n,t,i,a,e),drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"radar"===e?this.animationInstance=new Animation({timing:"easeInOut",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),t.chartData.radarData=drawRadarDataPoints(n,t,i,a,e),drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"arcbar"===e?this.animationInstance=new Animation({timing:"easeInOut",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),t.chartData.arcbarData=drawArcbarDataPoints(n,t,i,a,e),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"gauge"===e?this.animationInstance=new Animation({timing:"easeInOut",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),t.chartData.gaugeData=drawGaugeDataPoints(l,n,t,i,a,e),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):"candle"===e?this.animationInstance=new Animation({timing:"easeIn",duration:r,onProcess:function(e){a.clearRect(0,0,t.width,t.height),t.rotate&&contextRotate(a,t),drawYAxisGrid(l,t,i,a),drawXAxis(l,t,i,a);var o=drawCandleDataPoints(n,s,t,i,a,e),r=o.xAxisPoints,d=o.calPoints,h=o.eachSpacing;t.chartData.xAxisPoints=r,t.chartData.calPoints=d,t.chartData.eachSpacing=h,drawYAxis(n,t,i,a),s?drawLegend(s,t,i,a,t.chartData):drawLegend(t.series,t,i,a,t.chartData),drawToolTipBridge(t,i,a,e,h,r),drawCanvas(t,a)},onAnimationFinish:function(){o.event.trigger("renderComplete")}}):void 0}function Event(){this.events={}}Event.prototype.addEventListener=function(e,t){this.events[e]=this.events[e]||[],this.events[e].push(t)},Event.prototype.trigger=function(){for(var e=arguments.length,t=Array(e),i=0;it;t++)e.padding[t]*=e.pixelRatio;t.yAxisWidth=config.yAxisWidth*e.pixelRatio,t.xAxisHeight=config.xAxisHeight*e.pixelRatio,e.enableScroll&&e.xAxis.scrollShow&&(t.xAxisHeight+=6*e.pixelRatio),t.xAxisLineHeight=config.xAxisLineHeight*e.pixelRatio,t.legendHeight=config.legendHeight*e.pixelRatio,t.fontSize=e.fontSize,t.titleFontSize=config.titleFontSize*e.pixelRatio,t.subtitleFontSize=config.subtitleFontSize*e.pixelRatio,t.toolTipPadding=config.toolTipPadding*e.pixelRatio,t.toolTipLineHeight=config.toolTipLineHeight*e.pixelRatio,t.columePadding=config.columePadding*e.pixelRatio,e.$this=e.$this?e.$this:this,this.context=uni.createCanvasContext(e.canvasId,e.$this),e.chartData={},this.event=new Event,this.scrollOption={currentOffset:0,startTouchX:0,distance:0,lastMoveTime:0},this.opts=e,this.config=t,drawCharts.call(this,e.type,e,t,this.context)};Charts.prototype.updateData=function(){let e=0", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "wx7ee0db110b58b021", + "setting" : { + "urlCheck" : false, + "minified" : true, + "postcss" : true, + "es6" : true + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + } +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..b106ac8 --- /dev/null +++ b/pages.json @@ -0,0 +1,79 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/login/login", + "style": { + "backgroundColor": "#f5f6f8", + "navigationBarTitleText": "登录", + "app-plus": {} + } + }, + { + "path": "pages/home/home", + "style": { + "navigationBarTitleText": "首页" + } + }, + { + "path": "pages/device/device", + "style": { + "navigationBarTitleText": "设备" + } + }, + { + "path": "pages/location/location", + "style": { + "navigationBarTitleText": "定位" + } + }, + { + "path": "pages/user/user", + "style": { + "navigationBarTitleText": "我的" + } + }, + { + "path": "pages/device/detail/index", + "style": { + "navigationBarTitleText": " 设备详情" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "芯域物联", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "tabBar": { + "backgroundColor": "#ffffff", + "color": "#cdcdcd", + "selectedColor": "#50B7EA", + "borderStyle": "white", + "list": [{ + "pagePath": "pages/home/home", + "iconPath": "static/home.png", + "selectedIconPath": "static/home_active.png", + "text": "首页" + }, + { + "pagePath": "pages/device/device", + "iconPath": "static/device.png", + "selectedIconPath": "static/device_active.png", + "text": "设备" + }, + { + "pagePath": "pages/location/location", + "iconPath": "static/location.png", + "selectedIconPath": "static/location_active.png", + "text": "定位" + }, + { + "pagePath": "pages/user/user", + "iconPath": "static/user.png", + "selectedIconPath": "static/user_active.png", + "text": "我的" + } + ] + } +} diff --git a/pages/device/detail/device-info.vue b/pages/device/detail/device-info.vue new file mode 100644 index 0000000..1115aaa --- /dev/null +++ b/pages/device/detail/device-info.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/pages/device/detail/index.vue b/pages/device/detail/index.vue new file mode 100644 index 0000000..1920f87 --- /dev/null +++ b/pages/device/detail/index.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/pages/device/detail/real-data.vue b/pages/device/detail/real-data.vue new file mode 100644 index 0000000..f24a129 --- /dev/null +++ b/pages/device/detail/real-data.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/pages/device/device.vue b/pages/device/device.vue new file mode 100644 index 0000000..4144a0a --- /dev/null +++ b/pages/device/device.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/pages/home/home.vue b/pages/home/home.vue new file mode 100644 index 0000000..e31a8cc --- /dev/null +++ b/pages/home/home.vue @@ -0,0 +1,229 @@ + + + + + + diff --git a/pages/location/location.vue b/pages/location/location.vue new file mode 100644 index 0000000..4cd5700 --- /dev/null +++ b/pages/location/location.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/pages/login/login.vue b/pages/login/login.vue new file mode 100644 index 0000000..3301eb6 --- /dev/null +++ b/pages/login/login.vue @@ -0,0 +1,177 @@ + + + + diff --git a/pages/user/user.vue b/pages/user/user.vue new file mode 100644 index 0000000..7df78fb --- /dev/null +++ b/pages/user/user.vue @@ -0,0 +1,208 @@ + + + + + \ No newline at end of file diff --git a/static/banner1.png b/static/banner1.png new file mode 100644 index 0000000000000000000000000000000000000000..d277a302437e09201f7998d8d71705ee6c5eca34 GIT binary patch literal 143948 zcmZ6y1z3~e+cqvpjUL^M(VYTP5~Di>$&IcNA|Nd}n$buo4bt66wpcd(m+-5QSCItA^HWDqk^`=qel(N1b?8|=+^*GHM5tG9uW`zyJL)cRM1m=R7g-S!uVJ*E%SGmIgrmgjf>b0%O4E`~ z#-!}JyW2!ritqEZrch_w;)z-lE;qu%QI*RZa$lmIi+kkCZUz#Bk0+*P+#SIGXgeD_Bwt=l9Ph49zrpp>ax(mNTN`V&_M{fuFTtZf-!RPCmfs*v zMh$UeV+T$VE21n`5eIWO0AkOr*ob3vbhX@CX=Wafc0-tYT@!7<_Dl2_$ls;&`uxjeO`_1UBRD*7HMSPPFP2aTGEz$NVBA?rgY1A=(Jg1;Zgu8fN!CYdb zJTO3LCJNwOvrhB9xaRptSwMggM`;Uvahmz`cy@X#!GKc-ClUN|v`m9R3U_+f&$iiZ zGEvy#uZ-ua3JIG|LA-D!<7qsqSzxX8Xs9>H!>%+BxAIuADit}4nEHyNMYou=3dbv<)l3>kb66|bL>wwbvK9$ zjCWS0S<=a5mfXCPM&Ml(Va};iIQ@2O?0rvubqQ6W`k}kjI1{@8TLRN^q_FxY%LJF9 zrM6B`wk#DPm`QKjjYS+;ktr*nmQ<0soDT+?_hPJ=ujg4ee;*S0#tFY!T&~~DCAZrgdQFn7>wJ)OEYUaJu78m`0|OuUQKe@J7l#FN+lC6FFDW7zk$2QhFt@uIaeYc_x>=;Df!%p-Gu9Q)Rlftz<7&;wWOz*|-ZaVlT|!vMpN2`78O((rVG(GqqCB zO27Crvu!NHMDqL9d*iFY2>vKok9s*W6BN!;!s!EgiN$uN6a{|Ti=lqrNd8(xhyLU+ z2_NoS#_856&1O-PE3yqi0;h`2rm7oE$Wc*kj0i^Aq*GWxfx% z%W}d;9Y<+Ve`(h++tbp2y-eddUnY+D$k=v#J@gWa@K80#dv0wQ?Z;KQLo^OJrlDOd zVuMV)PKeTrXI$-eItrV8PFhb+r?jqgHwF+ifh9`2oe&>#NOreQ0;ZRVSjdk({w8AVZV2 z=1cq{@8i>0}D6T?ZgDW z+ZyLLBNMxwc*I2}!rKFA8g1rnYLpg&mteU9lMr|$MMd3+xI=j(yBI7FO?eorIfa9| z03~?PTmTPR=)Q21epIk23$CVwvLtHwSBz<9%OHn@{l_->(hfs_ZNf~zB&xNyGb={K+VPA!=#l46XH7ih2K3qV*XLcTz8nQf z>#6ItZ@{*D$wJVdrUW{84@WF74WI!6u~TA;JP7RYNZk)Ek{L5VRk^&crzo>_<*oOA z9dF8M$bL;JZMO>(^E&oER}j$25wL!1QlTtT>tnAxOWr+}^0)*+(`h#}7keK}?R$8j zZG{pMaVSy4+rHC5iNLo1xIrNh`=R~OsBGqUv5x(J!j|9FYMBgq)-q2zSBhH{P!U-^ z`}HlRoA(h-02cFW4ddIfANX(EO2)+iDFERq|7I}QBD@}J_iW5pQ_Yl+9KKD}_iRE> zU|`?{DU-mac`q-3TyekY&ASN2b}iB9(XqMjYOhx^FLjsOEvI)G$@T!B`I~6?IC7BV zFw!b6y8shW2fH>Oaw2OLr3d);c-ey+?6#xucK)Lw_nszbR#IiCE-3lnfn~?k3V?F zst)Vwx3lmk)*4ZY{npW)Ufz`hL8TWE&F?}ncn#Z#Q__Id7)P}!8e)sjOQN_~NHc%2K%L`~t)ntj8 za|jjtnQRUk(WUn* zs)hG@Vgto5G7wJ4R4zfq;#D9RtYQ|6@2m)eJZ>a24ekH1TewWhKYIaNZ~`LvfXP#I zT9Xwfz!?}_ZrIXOYvAF7#0gQ1zc1_~T!8BOsIBf_!gy^+Uw{5S*dYSq0gdM?*XG}J z8_J`WuuJO5b~qT}SH|*)+%VEAwIM6WtZXrKR9gyl)uP7A{cWusFnqfsz@W2MI+&E} zPb1JAwxqoKuHSvtcWvSD4QuYq^X#AXX>6e{7w*)w_k8#BR^q~@I@GB=XqX=7a4hbh z5wFQs={VcslvK7nw%s3xD{`cO6r4(Eh}Cz9ReeD2CDhK|j~kc}Wg*!_hwMj%hddoD zh&lm46AM0XnTY#R6CCd_6?yVg0hKyiBY;Sp5!d=Kr|!pc_)mv8sg4xgZ}GNz%& zD|tfr{#><@pPc>olE6ovg1K$wyTOOAdru=3MV=Uz2-gA{pnSeID)LsWH5zZL35w3{ z*%gyJ8Q_uQ-rvKNHHCqnOoD+i&5-E$u(6K!=@5vg)$?FvMGDT)_^o<6GhBq5GW#vY z6vL-X12FY+;tTcp4>Bw4JX9vZ$eW1O&9=Ji-?UVgKVt*R?^?d;+}L;3Zq^ba?%((jx^pL*vho7ynQU=19%Ve#;wVB3@PrN1qS zX=NHZx9>`T^D8StEEa5RDm#gPa8ga0-@l`7 z4!Ko=w6G{^u|FBFs-JQ&!sJc!8RO;MI}4{~NjaQ$ivfFoAwm-SjUS{ENaTR7QPCN< z2Xcu^xz71jPQyixBTBpl6UjOK&rgotw}C08zj4QN2Si+|HnmNZ>GmPT&)Kr`>}Ee|I|WZoBfz+E44Cj|MmuS+4>Sl_s4Jt2hXNs6JtlYE<$f zf1^oj2>4kYDbAt+iQIfDHC0Rt>P@ZCL#B|D>_8N`9E7(`2;K@IsT?5Tdk**qYy$7` z$AK+$31#*HLYi!lqX@hDrT8MpIyaZmRQW2ra!vd|<%f{(k)b!!H?@l+$^)I^+8iZE zFHQu;Wxde7qRk0Cb>7X=ay@nOwXbed!pgBk*b??gQl;mQk{kRA4tiLf=L&gw_7d+q zy3TPm&hhhC0;UERpHnC_X(gq73lE8&n|W@vZoJ-2ed;y9`D;U{Mq%ySQ{l;i{F6qg zP|oAP>n*pXEWbhb{DO8zU6jvcwjSRa!qH*qL#?n#YYn;CGb;vgVN(cV?4^MPu83-@ ztx@yP#n7CFrYi35mSS`QeQP%00khi}7< z!8BDgWnBsFGfFC0j&bu=e-!g{HHU5=JN)%(Di1wwzfZY{S$G&cj$S2cXKd@+B7`l> z`8=;86fsWO%CT;vNq zd^rvnY-8s$csIZw;U!LHyWZf)J}r)>3X|}w65g~es9M`HwuuA}dD`un@{9hXG{->~LT*Q^CnR*C^I%UJUftbY zW4F2PE6&}&xL*XO2;3fUgDfxl13>HhgWMpUTaeDV(8Ww{So@^vDW(Wd*+xvRO&*cN zEeJlaJ)|u#jVrP2Imk_|!$l0A+aNhXze&|@i7D40I7bgZvLsx)J|5DR%<}=L#aqi0 zhF~1RTB|3e2vEcU5Wa|)x!3W9v?)4kkgdT1ZOrKy0)7xuKkSI4(;+KR!0Q+y^tv7|Qge zPm<L+n|Gdd?@ z&@h>&?Q)zQS9o0=V<^+f6LXzTphPl$5H)o0;<>u#4hI@e7hdkPG8GzG;H{OQ;Zz$k z)`7JL+xpKZf!30CgG5RE4zJ)VC~DFOYxzzaSEAO5tt~4zS_)>f&E?x{)w{>S!QmD> z?dpBEo`u+uTmjL${>#$uQ)2e;FW;sL!R&E)hE#Kq$giy836-ZR2}suv7=CA*W00~~ z;zV@<4r5HT?d|{0#D`5%Qi;R*IckhUmwE4y3x&K{g`h_0i}H4gn)X;6FLHti^LjrR zbtDk^s+JA%Gb&n6RHn0mdM&v@+Hx`(;rt_tK#&s-hCz=iG(Cw9n4d5-Zbw_oTl`yp z6ideCQqBTJ&S&QKB~Kh9!GZnQ{Px(sn5bN=JQ8Xv`6X4g@-QdzO`J&8uPl7sbWor% zUK+CjyTLd81H1eKA;BW0ZUm7twd6Mg)+t00!)-ci%@3~0p)g?pRX>cw)Z_wfmwe2fbP@>+;R`5Mq#1FSzvPj3du%lM zCpSDe#u_*AzeMRsl0IpidA^Yx){f34$$!D+EspW}V|yI>RF%Zn&Ik|$As7vV#7)&O zngz`*5|?hdPj}cQf=(ojNxO}HaSkfmiE(btzqz)9fSG4{Bm-uSY|W4R6&y(^t;*|} zh*fzCvcCcwW9kiDLO@E6e0TzL#o$NzvZ?$m@V6xZT+S*6&gIrlWrn% zgV3iQ8~>(?%YqNR3pk~$+-38epyhF^VL=c&xl0oK(H1;EZr)PfpwxuA6&79xWOuNe=uhmzsnxpq1t1PE!;2;tAa?& z{b>ToN&mYv$%dKJczKc&bFM2FORPl|O9V`)ZekB5S<4Gxiq9M*YHG+Q1fk1te~cL} zTN81co#$5*1VYR?K6_?R7J-NCqgyQePaqjSn$AMkCFl)4hC6Jwc9bKf3s4u6 z_yI6ojr71rZr8bl_i$9ccZ~pxNf2&hvGWa{mOKYGoYUJFN;; z??2A3YceAi$S1)uY@DR(rw`(n@Creqc zpGjixyIoc5&XW5YhluB0c-G#YQg?~flko)dzJg`ph`(zI6;DWb7HW!R3s9^2h&Qr@ zj>RxBQ>9+VmOCuF>OYK2bR2vmRsUJ*z(=Rj%*Gh8#OYxy{cPHB7ZLGF#x#ST?6)kK zNOnw-PFhieAHt$73cU3zT|pAd$XYpNnE>tOQG4OVr90a0>5%-8Y|Pmw*XW7~I=N5? zz(f_hsGj~YliC7ivx6~q+3 z41bF^{c;nZpHj41lDdPVTYQgIC{vRyrfQKDax+7ff8?(xpx zzclm8z1iNTPTBAzPuxHk4m7U9y=SQN!o390Jwt4+sbnGBmH53PdZ9mtaiOVXR(P0@ z(D~)@GLx1Dd~pV;#3~z?ix*_tj(gU7sZW_wVFTiU;K834MLZoS!K!Y@NkG1rW}l2$ zRR%da#zPz$X+3)8!#R3%YU^;ckj{p78&hIjq6X4JO7Z4W@m5z-E+bb7Bhxp*XnumO zG)f*93bW)qNZL)7XHzW~yCEualO(Uw{{(XwLqGjCTYH_tU6gw=yDh-{eR3Hx^zh);9vefBUUciVy`63^ zWO8o`%_5`3w&xBtDK)z83{NHCAW2@&k}YxKVcV&6T95#kBFD%j(8Pj-;O5bWpWFvb zG9YmwBe2kloexrmJ$aMDe7|(&aJ=U>g$U51nXj&KgwxK=#6BN=oAcHzdHk>?J99_B zZ1Ty(Zx)oZG4g28$l+C2@3hK|>(63-P;f@FaP0RFf4zJ$#%a9hXa`v^$CHMCr0_gD z7-aX{6u+lv&14*y4mMAB?}~>gw%P_N1AI{es)rA<6_P>nOEEk5s|_zb8XDc7bH~Nq z*jz5$FQss%HeQ1=Ya|gJf{R-nj#Xy|N>n!+UN~)9HG@N_06Vq?D8*4cBtRMSEh(*0 z%vqSI_=g~&CYT7ng@9Cv!ghd{_x<@3sjFsX|58tthDB_anRL?Gr_Xp$%@%{@oeImI z5txeG^#qCI@3T<|2P+8ARN!56?-m8JX`2I#?)iq2ECm8`L*&}=W5}sH4$$}q>_>;Q zG`i;uCMSLUVxRo1X|=g=^;xS`TB!KpN~T$ z&P6#$O%@zu#Oh|l4#rvJdaFP?i>O!liASz}SVULI(&$#f$GKx8BvPoT=tcSzkw}Vc zfZ7c|_cG4hZluVn&~xo+DqKx}ULJWhf{yLmTeo%qg1pP_ic(@mk~t4El}mB!UxWS& z8-j%{E+^gA7&H4u@_UEz#Vz=RMhtC3&*)BYhdZ!`=w6nMb4C>wCgLGE^@t-?fw2j0 zN}gP#46}ubWVCA)^=`6HJ}}v;s`cr@2fw-@6RSDw-~OpNHX{)|Nw{2*qDHUu-#bjj zTmO%ku(!))#B~r2H(s5tnu*R_t{PLA(I@;beC~l8dzWKCgGcTnz@K? zA9yH$Oc8P8l?$tpzTq|ZMH#oAtZ~lS_oN2rGkjTew-3x^>V^N(EbKA#=Xx*>cE3K|$|+CY+Qv=ZK3V3>$VthW2WK7%~RXt4-C7)KLTE3^j@(_2J+DQujo=YhmkK;n&- zqFBJDWifgBT#UloKQpt(s$Oq0YG`GZkOn%SLtJL9UQ^B5lN^X{VRweKWj09Qn2OWv zpdqvr_CJd*xvw-l@WvH~E$wm1lMi82(=LN<0F`Q0A@(XpFa1ydyI7N6vnY0!nQcZy z#z^qIfRLYLI5SY_egjO!L9kwxPCn(b8W}U`IPJ;K+bCNGRt<{2SyWs32xm;`#X}&I zH?T@H<>&%3NCqBc4E9uWF8aYV3)s-%+0}A!Tf=RAx6KySWyNLE);I(O<#Q)tP5pB@ z3RKE1m^z)P(S8(eU&Yr{W0$2C$IipPk85n#nt?KDrOG<`e z%^k-J(ct;@B5t;)bcsE+@lFrhmswyD{LV7wx){|Ll71qM$ft~U>KEqe99CS$#`Ifh?ecx_@)id+e0)X^-$8R$ znSeoUf#2b|K}%0_!)Vs_A|$a(bbn!&aH5fwJOzg`Wp%bXE@4i^oKipb{}vo1Wr`kd zz9MV^K$3BMklgr3EhaX>rwdv{IuVDH>)H#^s{s;wG=HLVs>P6( z2OUVk(M^f~JDMtOQw9pQAQ4B4^r&OG)8~#F~$97vuKQuTi5TF5$o+Z+a_iW)tH$ zr>t?zn7f|Jv#8=t57$0*(;mze^X@VK^qPMEg?sAJ@_>=&JS<HgQv6Z(PIF0=9!B2M3-DLj~1I9z1#7N zr`)YLfI^~ncNbQClG7F-N?9sBt-=#YF-&(2;`o3+gA_Ma7cVl2jdjz571Ql!{M6esW{Vn9jo%x) zuGVNkWq-0%K@FW7?+xmNtEotUbAt#S%e{haB4t1Y1mzZau5$LakZQi~eF9W`R$jRq z|6~seqO4l_VcZ~#T21+pNkayG3}oLvbxQm&E+;6RWPx5^kuKOX-D<$( ziJQt(gOF^IJ*I+`m88m?rO{JO57F3hR5I2jX`m3&D_>RYG-C=9DlEeDbY29x09 zJ(k@c#KW^DXv_Mw7eRBo#cLmVN)SJ(*S;I}lc#=whg~rqYM0B`x@_hJvD*WQQ#15U z&lYPO!hzHa&niisxmQu-pa~r8h`J#=`F8$5lM;XGtW{3bygRLLde+fRkwuO@m&nw6 zJvSpbac0qexp$7^cQGN!?7BQ>`Ru4-ILkv%a?TqCfP4Zk9;1Z$8}u9mBjV$6$3Y%wP<`w~3u z=4z#)0Ufj8yhw?$U`NWw4ZVQ)5SXHJSdrZw@xM0BTL;hp7#mJcdHHG4-faguDnJdN z3)rGgDL`+GrTi~5Y)DMZ4Q#eTWjK|X71Ro*C9b7HGmy{%5*_*MTRfuur}fjNPnox& zM0g~%b5w--EQ|<35E|T?BTZCGuq(j)PJiCc6K!Wxx>KDtQ43gsm|;3bqF zj}h!m2D*vs>z6Wv3~&tTLygztoCAhASm59yksVS}X*6_2=UU{Ed?zE7uoxcvugxiu zPEV@6al@V~)AlMKC+Ce#vh!>XFU_S0O7X!yz8U@48CGA5C;aY{@X}}DqeN5MR0mg2 z89;*mZ?Q3E-CKnOxXQP&fCL@5LCzOKb*jCU!@lOP;?~xz-L*uhh72vF>zA0-o~=Gh z$vo4W%*&9kfsL0|vdkE?xnGx*<>2IQA-2T+LZH%+Q@J++G8cHhZ zYXk_DdGEFv$2g2@EKak9!QaFu7>j{V)QM`Mbs~^QX^wO}2}y?Xyh8xb2aUKrvmVdJMb#$MQ&AQ`wObWn)(H zA6I5aNE$88{H8d>HN$FDE@H`xoRkxuI>YG}K0|G>uVm9h@-a;EKb(B+Td+U6sX$9l zgR!qXo}Q}qa7v$|HEDE434*@A`L7NHP0-uXJ9%<3!w%w0f?AR$!xrKbky~Taby%#d zghoLgBo@qAmI`vBd;nL`<9=pXZj+X+DbC%oc5C%{c9S-5ypP^Hlv+_z>WS05@r*t96wA~@5u%! zKWwXl8xE_tH#jEMpXQ6Gx+rLX!su}wHcwhjv1%Bl;<8QJR=#~^kf&U{Euw|+U$Gr- zv>2B|*wWBQw|%5q&^FK9VX zEzb_4!dfUvyXhGWU3m;n0w1p75$>8COYOdB`cUA zivz4yhK=aPT40rmRH`)Rmy)cf6TSi34{a=tT{Yt{N`C(5@S?2N(8~YD^6h&tnET{L!_jNGsz;)ccl*;tNMGqIxDm%R(nAm9L*E7oK&0F2$85np%-jnBH%ZoJQ|o~GVEQk188&k zOzs)_JCM<2B&P&C;_lK|Aj$1AR@Dx{5dWpc>UlJqShE#WIB_;d89)L*do{?&G^A7V z!Jhfm@8TSWMV=cE$N0Bb#2w-_z}J?i*tq{(ugE z_$j-$dyj`V46gHx(Ut#IP=_-S10=o7nWS=G5C4P>W?jAJrEmMb-4b=Tck0dX=CSTr zuw~^ZBPGlaq(WK+DCxh`5w&%yTiO}^zZ>XKvUZd`LXR7L=5f|*=Lt>2dlAH?gJR?C zXn!PTE&+>F$M7jKm{k1E{t_zSIF6rn#8&{VdV5bfQL7Z#aC4@BlJ>^BOYY`n7%Yf5 zb%}oqhq2HsFZIS}xbZd*@V9+-OJKAnY0l5@77jF+3emgv7|r!C=GA|b@q)1UlaK8l zL*rj0TDyTXs3UR_6$z4igNc_&;D6705W;7nqk{${M=D>S9z!Twfw) zrVY2r>}GBj6c&F8Wnn)m(b$fy+9W3Lvqn8;_tF0!neIW@Lt~@2cxte#96102nXndq zEH^H+Od^{6u7fXYTyQNR9E^;b))~F4^NgNbWl2MUhD0Dn_C*{#~eP>S| z*}#ozv;Aa}r8l8{jDF)$1zx{^{qDD*>gAM(KjB~$pMY}5*zk;BQekZ`kkj?ZYtOE< z@n{QZ7W$ED(QTD|wN^5LkzJP2rCPq{aSW*?H5-A zNG|{{{f{Lu@c5!+jZY%}xm;7OFECsU;2==s+2Hw)V_93uqm5IxZ!%DF>jCDEUn5Nt z)KB{M#B5%ubXm+5OuObr>@~#J%}-_B$2qYt+6g)&{Lou!&eGB#2LL%rL{?{`&l?$N zd2iN-#5}%>)vcYn$Ne<7>EYZ}1`(3)-Ao8gtD2W1nn8wGQBLoeSzn~cbuY&l%4SRZv{+R}3PviH(C7sx15_$$**uXfk&CC$dTDwcF!9{vZHZp}!SERNW*78ZRhXNg z5*#Xb5f3qm95`0?-{1EmCHKaE^JbKk>*m!GX_X|ur2G);mSq&9KT+q2m_hU+>~N)c z`9lY#ffv14@oP@XBN;Ie@%!x1g`Y{2T1s@n;YVJ6)P%(y*cKvv_u16P`Pgj}e2X zc`3m!h9L}l$-BG1u*R@8GxtoD<=Qt2iiiDQS>=Le-+bK{M{)?!hA}_poP= zchFt9mHZ!NA?ol@ZH&VoSlYEUTLJg|4o8>|Huecl^LK%;IE3$nhF~3`@nA2AND$Gisj-FH&TCei6m;1Fm5s)p#46lf6 z|B9g=2bYIUale*wgTT_q)Dp0&!bIDT7JgV^+u1&dXArQ`eCr`+Wwr<@4%vuX`*gvx z=dqp;6`%BD%P+#CR#9&(5Dy>|m-2r11)(io)+6bw5xP%bx?9IS#5B~DScEst`^5xX z-;QCI)PN-Wa*yea@oSNS)UYsPSR8Hi;}N^*nZ9Ea`TE0NLgB%L z70f5;%@?ZFxF5ohwUGeuPHbHLRe1>J^k&WxcB_7Cv75^CVcVK+}Wft6(S}zPE{ymy4&;B50-cb6AYi(p>~jWTTa#|`vQpB)Qzk1 z`4lE}@D$r_t~LL~6*PlAjDn1Q!rGFh@Y(H=TLd0Q)3+bcYfqi z@lpR=#1M>*`u135YXAX~)0D*m3!-{<47p=LI#)j98l*t#RJ|e>*2}hi!vkj3bE^^Fo__6345 zM}agxG=+tCLVF|RYAKtg4Q8w7!-65ecfYS3DKy4B9?m$|3$8OeCtXxf985S}VfD#m z_+yiT1^S9Hh%-c3{dXIa)^B4yzH8{KXvAr~a#hfd%@zkZdV_7q{cXRtWI(YXIF)oz z>YwkA9>W7DX8%F2 z2$52sDi$g~j#zR?&^SBrAPqHCNp{H!?9`qKG}{{jl;;L+N|4p6;n1?CDyYO8B`~oJ zi00*xRt-3-DCVa!Ssx9WoqwGO^5IlZ5*02p*thkE$f`h$SzSys>hPj>pzp)>+$m$n zcntv1zGu|F0JC>pkE>oT@Emy)G`u$F7Kg8gf45$XUoA6ck^V{3XrMdcanB9lo7Wf% zbGdb|8$2TTpx5q-YZV#@UY};!cbW+SL0ajt1_UE>4bgs7^7oJv9Nksy#wg_FP`!r($sceXaxP) zWq!^D`ungf2%BF?^uMvoV1L>w#R;du*xn4EG-2TB*ZllWUlHdytI(O9V|<pt>K}IGTYoEDKyEFP1yV zsoEl=7Vug$+W$OKt&cIer}y4uVpqe8W~`u9v=4mI|Kuy(c9xTDe6|DIs2M*TPxbB- z-Lk+(R;%Hw$N+JbOFy-cQ8g-Q3vz`+{qyFRSLSorff{*H+#xeynp=$TkDO#Ue779p zY)*14;~4|5JMi)L-;lu|du}v9voq~K4a>@ znE*oi0DP7=8F&nO5nqv`=f%u_NV6<`b1n|2i?Z#j7Iu~@MLRbegH`_tGvq0jsKC82 z{4s*h1^VGQCaj<^rTfLJe-e%enz;<=SVR7E7ohJ^2MnYAdViXKw!Ni18Eik~KjVNK zbzzXmz+lV)t4H@WHUbprY%03v!mIXinLlbN z%Omqvp(Rbc$V{Da`c;j4eT=Cz1*wBPmkKL5*9aXHKQ~s7>R+BdFkz;4*>_?6!OS3K z1qbbmNnhVCh~zeSy%b*f=5FkbuK^LquZO-Y;QOd!nwW_F+SIxpP$gb7+R4vL>7dq* zivC33;IK}Wfr|r=!)CV&wt6#g6UpzshBc-Z+izsG?~BSXId)sIic@q@)$sLoP?>0` zX*SB;mwOlk61G2NlZjR6L$=x{M&G~T6!O_}X4HB1)SbTe*T&6xL&$x4$Us}~y(O|H zsQcxgX1rlJir6c(gWoRza*I;JcztrH5tT|Vq!r2eo(}rPcz~989KIS1 ziEajX7f?|3j0HW&a#3FnfDc4+pY_Qoxm191BuJ`)!zKW0e1~BdE^C4IbqEBvF zh^tJ<23&o9U2h}jX@JJNw*EdfROK|1?-6f1a8dt3MO&(vxSK|3n@d24qb=;UPsFR2oApaY<`wKnV86vsb1AfYPop(Jf-fU@3>~8ewmXY(?`$$;%AFy03SeP)H%j`z&!^> zA2FVkl9-;tIJ{&q!l&M#hF}M+PP9Vrqeayc>WpwU&II6{4iZoi0XB{``joZI3i&H4Vg{1J#K% zCp*VS)U>flC{N0$c;(Mq!6E1=%YhvZsw_;06j@G+#Etiey!bxoD_K067f1L<980uP z?Va(3j?E8>VSTVjmWU(I-In?GSKrhDVQxU!Pnr*>nmqLaj-r`07BNH}*kj}5K-07c z`KWF&Yc1@ahaSG1)8?JN6VFY%Vboa>)Rb}-}+_Toji?P7X9FP)SRZ4BpWBpDxD(d zA{}yZQM7_#gV`tdb>U3K2T2Mh^ula(vvCWU)107th{neA;T5Pw;3D-=YILz9s@b z6&~{*8jJ0b9OV?sr&T!4&t@!)n(&R}0`45(0n;l~*hPx0n27BQNNKs}?5&J`(L$n) zS;V`|nnE=EBL)cHTgoJKx2wlmD&|RIv$2#}n)eCKmCF|X#u_^MXWEo_V2W^j+C_Uc zacI;RgI_41N$9^>(Klor@gEiib>jwFE@95ITwbc2ia+#CO zPr!`ydrRu@8J**-q4Ca7V2)gfo76G{1A0z)6oKHYZ;w0$?`*3U^!41xR`6N(5Rd8>ATK+q*%_Ktup*RY+p?DXT8 zJ6OD{A%bWm*GUY1%S{MJPwkh@iA5M{5W-=K(L_}P z_5C8&Sdb$jAN(=*wmbt2=(oWF094+=#8z1c!vww-KL2{PQ$50v;#UEmRmNhXGVjaa zv&+=^TnNKOz1uNIR1O79?&U`6e8+`VEB76XFVakzmdwP%j$`Ea)D1=QtEq5={~m?g z^Ce#1$Il9lNPEjo>+Ok$BlL{gyCv#1>UqZUg zU*V7H7*+a^F5GQ(*f~VK(rD+0FXsHLw-o`cYQ(>K)ZO^F>pVHsi0kp+5Q@ijwWBHY zZ(Ba5vpm*;dj3tL@t+H%@w@~Orhc|N*y8z=iiM-6Vfwd1r3v)*7O%DeYe;7-P{aQ~ z9TI7R?-+p4fasOV;Kc>`Bt0c(uk$@b0D*@|W6B6TH6drkytT)|zc;IQWLYUa^G;GC<759X|G@sM ziSch7bq9(b)oa>LCsnd$W0Maz=+n!2HssPTY`U@OW0{CH9Ia-O$V%(mwV?7=8Rn6c zVCMJ*w*hl7>B~)vlihuZOz3oY>4avTV1Ilazsa}W2F$wd4zkNltD5dkPa-SxW-1T9 z^{^=3%X%O8H&p9-@P$1%(0QrMZETa}t_06i4HYj8FL-7u#Ho`D!o?f$v-gsx7CZw30Xx7Z&q8rgC=;cc_}0v z#C?yYi)!H6%QhwvX2b&tF|^6itLO=36N87^)&cHi>p0~}-t^G5JK~d`F8n5ss-fme zRbh@Uvct-9A@5%Rz!y$sQZ7KoiY?DkJYml{VKk9sV&VP%Y0w;Cn<9EGh;H!r>(R!(#P14qcAkN>FBVQmpUgHy9KEI zP_rswP&T$x5|BsZj}tn{3cb=ucF^D@G4AOtuq<>%O04RorHfHHsJ-~EA7#dAEH6on z&%GS@NP6#br5ns=krB~mQa#FmOyvB|*GK+xb11E@yHo~!ZPNbXEkW1$KzCI3}kIXX(`+k!S!2Kaa;eKfB2)zxAd;zxPxGkRvk? zC64j>?4a|>&$K2m0I;osyOH9JVf|^D`}Hn9N$?G-IRZ$uZlNFPp?qJ~M~_C|jMe_wXxpti{ay0v1ElTE4wY6OI1 z&SYL0D{JkH@Uc73NXV!C@Os3EmA80MQF##F#W9p*AWzI}W+=Z=a#(HkpH37o2r$S3 zs?4|6Q49|fg2+5~@&7bC|7}ynTXT@%@dbl?sq3q*$iyVmJQOt*F)Zd<%P4+pz(I{3 ze12_-{r~dW$IUD$U@NpKbg5|!kZvKSKQO5-p)BW}h)3v}=& zEstrlzL_`7w2R(({>?y~$bNmmgR1SykoM1MqsemQtsM%cS}Pn;iZ@Cj3aNZn9rcc0 z;pnIE;%a+)O+7K}IP5^(uRie`=4?H6y%<-v{KG@mBTE^{%bgR5p-%HHS4982Lzv-?sZM>ULu2pgfr}<1sah&tPoH-`!-s4o!-&=h z;mbg@ntBCNz8lM!LD}YzYaLeG3yDt)?#TQY=o|kFeDS(DlTLa1Wop**yOeaxA|A^? z<n$RuPDo#qYOc^zmX;PRZTbtOc!goDJZA;Y;#>QV?E}*;1tZRmS;`(2(whGcpo| zUKpl~h~A<|!AbnztHJ~1vnlnFZx9z&J#L*ZXR9jmTI@D3l)eIau?Cupd~I-xD@qoh z<@?MrW5%}+)Gi2<3ev6ZPwwAU8C3GTp2sPpW8(nzNY-;R(vZoisd>lAZES31au-ta zox=3uV&uUfUXF!>h((L}5I@{JF}I;|?L5g*6^m6>*y|2zZX=$4c(mL4&2Ax})yst6 zoLlzAz0#C2c@L=e8;cZ{aAqCZ_!jco?{Qx>=c@YRaJpdQ&yw>WLQNHNlttZvnEK%hvu zR(0RCN8(7Dcm_y7TwpRXr3l2?zwoF0rND)1LfAr)x3~v3W(>{sH(*K@18fZ)QkzJV zMTL&`m6e?xjq8NVK=s~5>+`A?vMpTGsq|%HNbVZ&!GSkVyMS!O%j4Sjq~H5LU%rt! zPzv@*C}sa*9AsSBSDC!m@W!f2qQ+O*7f^P)_hqyf^Nd(+1MwZKOuIeNR)fy9J0C9d z{I1tyJeJe#wp({VBsF`r>Oru>rpdA|_fWWOA}KXxsjY4}-J z3~Sx-45C7nXW>1SZR8n5Ql0sdZ5%yBG`KP+X%=igh(D_}f2L{_*>7P!e-jsl75G@O%+*Fu1Vs^_Zh_U&N!YeKUtvY;lajgxAlCofXnRL?@|;ZxAR z@819R0t`wyPbGk6696YL5_{wuAW+%NqCwDsSz!4Kr@_a5)2{#kNWB~gfWQLQAFwgd zY|geubA;@Z6p>6?TtA|w(pnPQ>pp#A0W6%j_GUxc@~yPC@oStC5>%M; zXF92MR|8I^(IBX#OUdUt*@>A~G^EUe=--L*_sHhdaXc>nIHC5ByyF}afI~~82Nec* zX?&?5rzC@8Ukd~ecq&T4$1U0VX$V`oINbTQs>Nmip;wg9xXk$E_qM){1WhUl+P~8e z&VFm&_Rwq^HP$qa|BV=`BDwJ=XprB2ECT3MMe4O3BY{D52$JK_!8jXP%AU!aRuv0Q z#ui&$jV-BiQSL6Z&<@HVUGe1gp#SUR5|k3p%~&zX#TW#)eMq9%?Tm_z#WWATSUdS) zptGK9U(ok^y5#hm5&;tml@A_Ld)#)d~X?xc5wvdPc;4@(P3(^a1`z zB&G~v?6JPLFK@;F9&rY5dr#UAzG8RT(4^v@={*$MRP-pa$-#}Ez37~M)8(%tP*l1g z#EZ^r-SFJJa04C(A8$UnO99YRQ}&TGyej_&I*k`@4l863wLPZwPw;kutS|u~&{7ql z0ukbJRMw{LtUoZb$v;NGLrdn}^1?H^c+TZ2vUTT#PJMaeV(NQjDB!mQl$or( zJ>nD?Td6XUZZqhRJ(yhMajK(yCP0Ehd0A9=yfeZAABal>V8L?5YCm=VfabC#A;pWWI*!Y zOcdh}zV*I8bPMeV*3&0b?{?1*y5iq%m;#_utmN)YQ<3iz9E8;_;;xbEVzs{2QUTZrUPijPe{sCOUDZ zcLNjMf@GO$feL2g(%^7o+S%nTvTE9(5gi2=w13P)#Mkl=`ulg$xGg@N`|WqH~cB0}u<|Fs8?`)TR88G#Qx%~VV9`{ZOAQASS_<7B|?FZwXvKY&*W z{xc^0|Fr4p1ZN=tw0HBHm@u~-S)UnMzZ%)|ScY9$eyh?jf@0nM?}424M0?YRz1H1= zj<23<+nZTtu6_46=VS(0B4T3m6hAmYI}eNQ8sRj%9i1Nmy7=6G8 zkj-gO{_Av@VK{9NhYUduL=C|0fAQ|amg_wTrjnWFs7hY_!&$7hN<7K{eYW=2~i>lZD2b6=p)a;IL(u!hjdEO zckPbAxG^RpG!p&DJJYwF_|LtPZv98snUziVk`2}MJ0JN!ei0DVapKKRdPv>>+gsl- zQYgv4!uga(jIWF-#(1;>m% zgHCl4A`m!yJ>e9)h+Tg->(zbDlb?BGr$g{peqPf~3@{*{us-(Po!|zXTwI#G`2$EA z*jcJYwqTugeh~clb8(YLB;0n+E#;UCV7*3Hl{kr9ru&SU$yLP@GERhw z#C1X9EBF;21*te8&9(N;&iqhl+zZ@%)$n>8yzS_HcexDoxo!U7EEg`GzM%=JI@e8d zm}z#hZIx%e-wk?amrZpXW>N2WsI`EFe=wv)k|&7uoIJJ@6BwGSN7-|d^O~{Fz(EWe zV{Fyusm8i-6Dr#psp@Dw>}JD&If5_{pH5$4G5A_o>tpErW7k43 zj5JwpF05DK)lWXm4kxja9ZymV@-Cp9kk!xf!j7HaA8h?=$HMBDdXMzqVTB~Jpp-%R z+e;)*%>bFB$(nhM&y`r!nDGa?|4Fov3A>^LBqi{2#8X*V9#FCo5hz)r4ggjdU<;LE zOluFYGHW9-3a8hv83KT05K`NBpX^VT8oEfGjof-~FC<1xrh4w%Z}V;(LEv>Y9< zRnNjpE zRAH*CNeyXQLDB!Cas$ZWE7@3pMkfZ&gQl{)ptLMfZsv5DR3nW~TdChoUy_sY|L=Ba zz5u)n{K$eQJjn3A^|_kSzIS*uz|^${A?5;RN9wfC{(X??{cwBnu`l0*=rVyzr#nK1 z8M?aEh>!aRJw3WEtFiRmN@X7J{3uWYdN0E7i(QG=*{Hi9mdQER8@`-$s?y^EaJDdA+ViR+67)o*h@4PUh`7r9TkK(GvjlI zW>mnXqRQ%Lz8(3`Yi@k=59sJCV`FTwbN_&5Hn1#EPG(?W_I0-%2!0#XMwR9HKP8zq zQnaYr*T|mmSMqb!wiwpLDPE#qFmnDA|_P_Z?ayWb*hEFpu7+FmN%H zE+!SL!{KihUj0~1pG(Y=@O8Ps_Y&f)3Ln52LhkHL$jsz&3jgFh#edTH8aMX!vwTV_ z{;@^YUeXD|#)RNNyVs4dVE?;-mk0YF-Yj0Z^}X@ASYIE2&C@K?Po)x(>`DlxH7MO7 zFIF$IG}uZ>ac~b>6O1+mSu-o5dk%UCy;f3g8i3A z@jpB3kup}sSFe!;OZCyV)?*|n>C`-%P^0?dkQ*Q}Wy}nDo`)(txU1vR;H@3ghfsbL zI26YYUv#^^dq8r_1-xl(JsGgLYRbwdhCw3+)^)|TqZZ<&nX4YY&Bt5F=xOuH_<3P^ zuf##fCIpO?24aU6b_!il*crqH(! zxZyI^R_^FFEmjkIs`%r99Z`hLcy>L$<7YtTh4f2k=^)Il&Tam^7sI9h<(oP_}N z&u7AO`D%_>REHdiH}ghuw8k^zkZyjW=W>3|n!0YP&PMq#?h9E`Lw z+3qI&A4K-+0x~;m$lD0(A#($GM%Ola_}m>kt~|Z%O>ON#FJIQojWUi8)KRjDxpis8 z8pr~CF%B!Eoy}|fr5=Yx4WPsDkv_dQ@8mzmtKRP=XNApM{gJ2(L8&0Q9PVq!cgciL z4uE(2WXo~PYU`}|$Tb~884oHV1sl7@=LKJMjM(>*J90E*#nGsO^F4o|XSc*BzQ#=8 z&+)hGrfYG0IevNlXP}!QL~J4|V?K0HY~I zX`|qmSuRxzDIrFzRBbLsHk6qktFa+Ico!qouPXYFZ-p5DF(uZ$-bqiM&b~B5WlhXX zL)d>W_1yW${?Ae3)(mM1S7Dg+*$C%h?05oNiB1WKk;aSCJ3ghyu@Th;-M?yBH_{PJ z3Btj-_){d>24I4PKts)Dt==9^v;(eV&#%&a?bXRNAh|O)xJI~e~Pr>)M z-ewe(+he#}4gQKcM!~0Wbc+Y>^31e@Vs2ZnylVn?`KnZ;fPpAMvX^_m@pc1VHoI^d zaxmg#*Yq~>bw#KZ`eWf3!@g(n14T4?R4ySj0LPXN<2z3l+4DtCN&&ir#k|oE_J*!&KT7I`%IeXJg{og`U4|nSDq7jV3$U1QA4w_feE~(} zU_Z|hU98P&j7y5Ay`I2RElxx8Z5$?!%+`&={hL@#3kO3C1 z{(|oPZea+fj$BBOd+pf|>$jWJ81|c^!$-Xa$!kd%$A#~P>AUfgWxcuS{oTpwLw=Dn z+>iSw%L&p`27~eO~&gxiE?0NwIzK#?NtJ^==a00RAPaJ$9Dx{iw>67 zuUL4<1H7j7$x`esL-6)l7Z@Zw(2w)K^sQT0cx?IEiisyiPMl`uSSXv=N7c<@MRsFt zNnfFX@bX$Ro!D&XI;1I#^lTQII!1={Q>mJTi=rss3oMccdM&oq#&vq1A)Moz3X^Ye zY;s>(1Y74K2wVCOsd9^i>mxX9-%(Z;Th;H??4d*rYZ4W;Qsyt_@U|P9+m;z6Nhq)L z`)D;E|BU?D;ak+IHJ}Utk+2IzyEXkp1+h71@z&L>2P-|TirDK0hK~z^j4+h64BZMt z5kphtw2$Ub;UfJPI3s18j6y=x{8A8?^#x`99Y)fH;Rz&`VPCL7e{UIq;XEAaVe{5qJptJihQt z8fe;cwM1i_mR?V{YaN_SOBb+j0KS|yMe^K(LH0#66Nc$FGNtdG6zn>|T z`0Bsuc)WQ3b0+&gc*ZSaqLdHqrU@?`=Ri571fQsC{*gmL;>ge!>e)ecXPkiwUBTW$ zN3_p}pRaN9YJ`+B|0E*XzL<5f`y~d%eO@SPJ!`^&55Bwe(uk_$8GAPQ%euS+GM9+u zre@K6JYHMM^@@bv z(Wh;OCV%Q%>rZj6k-rWrv^v3CGkn~Y>v>O8`$Y11X4wO`e7eRkznec^zwLR_@7{j` zN#2^?-_FY!%0AYIv>yHJS+8VgmZ>|Qh1@>IGWCTH$y~i0p6|YQ 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%0AT7xbzt-(lkD<|bG!OI3WdZM^ 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 z

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 SrG)Yelt)+75Lu&cANn7HjZF*y literal 0 HcmV?d00001 diff --git a/static/banner2.png b/static/banner2.png new file mode 100644 index 0000000000000000000000000000000000000000..058f9a62eceaa253814b03f9e14c6e29f1e432e2 GIT binary patch literal 111673 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 IPP0@3zVJ%rshzR=#W4^xJ>>X{}3l4Z?oEmA2O| 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 z z!U_u=d>>kAYQ^J1I5*y!|Hkj5q2_Q(hA1Q#7`A>I;f1urPOLG1Yr~&aBy>hx#AA0< z_r3ZhD0yhk=-bgIiKO#piTBPNsIWV_?bc*f?}dNE&m>OfHpK1I(vn0L7VrNO0K#!X z$b^}dB5de(4v7i$yqpP5{g2?CZ<-J)j@b5-dEuoou-yBv^$22&R~{g9+&qjZZBS%L z5@WjbXA@%i6!!2%7dI?i>S4}Kk(M%u`5?_=SFE^ptD!B1&cbU4$Gu`oY`g;lq8kc) z@#Jd5qnC%HhsTcgRWaXFMSQ@@&#m@>#t%TdiEt{b3OP9RSP; YgTT?Sc5zj=51 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ξkf0NR^^ch1G`NbHnaR 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�we1Yddc1X^857qI=3}^?N9d*uh+#WJ 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 literal 0 HcmV?d00001 diff --git a/static/device.png b/static/device.png new file mode 100644 index 0000000000000000000000000000000000000000..ef0f560cb6d38f05be4140db75815b6110230b62 GIT binary patch literal 3841 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 literal 0 HcmV?d00001 diff --git a/static/device_active.png b/static/device_active.png new file mode 100644 index 0000000000000000000000000000000000000000..185f71c8cb9685d4e86cc2b07a7b5b404536be6f GIT binary patch literal 3887 zcmZ{nXEfa3^T$7Wh!UbjR_}FJNU(ah%Icly-ReU0zJh2WIuR`dL6pQI`UXMNWd%{9 zMHh*vzs>jA|H1#BGxvSw&b(&kocrY7XL@jT3Nj`#001ap8Y%`jRrqIjh;jS*-?}24 z5V|PpC;~uZ+U-j_BAk!sZ=kLO)Q^F-aSoe~KzdVD1#vh)f1>|Q<&GqQYFX|-p$CWVk^qKvAsv^345ep`|QE+DK5tG?!h>!B1I zkw5|?352pvsX9@!@Kx5UJE~3wp!6ElGKpb%iQLP4V5V~a;I@xsP)YdM)pBS8YIZ5E zs(~s=c)S3_m}o;tbXf&gwSiY;OK40&K)lSq`E+4X%OJwG~*!B6V*5+50>9GFXGsjhxb zCA;HLl>5@;!|Fj^WZv(?6;?z}$|uRWH>jOj=TUo)uzq=Ai(iv3+gEPclM|ch(>GBu z$J9w?EWx#>t9%Vw!qBOq$-E_=ti}fRJJHv=0}-(y^&-I|^kHNS*M7gYuscU0mnpd< zRG(i=LL}st>{ABR%!gx$+9C?K7B<#aS91_KyR5bF(Ut=&UHDw;hLfWL5=2fD2mNV& zXYi|0CyN{7a55!Gfidi>tmwomHR+KPettSSfo!C@dET?ZEBOQly6&k%BJr}7>};j` z{cJ%KuQN#oEXLKfa_~#;X7I@!gk++tc{c)6)2ht%IDB{Kh=2Nu(;J}BX{Bfrm5K^| zVnokTzlxVpcoAwJYuvv1qVw_F{Urn>QhQ9snLciV9nLP_H}tIYLtSZSL4jR)?Je)$ zds?t>KnMXzYm!;BVfF zcg?GYaH0v2Vg&_w`jbZ)m59v2h+&hZEd!>ym_6|9hU;D(BG~pNOrm$MY}H z&5itgZyMLAFI1O$sttY9)?FLJJ~n`sG>U zBFcl_s%vMHcRe{getN3PqxH|H{jT76PZ8@Uel_xVwb7ikNUEGvzjZWwbhH}!`oqdQ zk`0~KCcl7YMkT|rFmeVrrt3;0gNN87>Ixcb6=AY0O*q3h*Jtm*r|U!={jO>rph79A8~h;!)E=+ql<=xNv!B-(}iv6KUax5$W zHTC<&=X1>+4g%RVxe`W08p_3DQcI<{XiNmbeJ&9SsnbjpyFst zw)9uUG*v+0^0AwI*{gn8Cngm%4tz8W*_!Ps4wBQ=ck4Mo1QxBeGkSEwYAk%%oMwa<63+p)7BGCnBKW(_ z+h*;ca7O2t$NQT`V+ZX-Y3ZP!B9M4_b?{BUnl`Cc2r1(0n}ccgK>sCD?|LbCm=ISJ0e|qEIG_a!x3x@^u+h`W@!k z-D46DgTP~nW${))?U&ZGRmmKnJIObjisgLneTWk4EI-EM;$7!!usu&g&mtOq*7gIf z@S@fOQ@nksdYMcT5^R_&COXzXm)9$9r_sj^ysRP1! zer#`k5*Yxd_~!n6MXhc34~;DDO5} zvV1Hew+>e@qK(qJ*(cei;LZx&AUCt!C@;@HK1uf<@?JJcA#ptRbx-T)DtM$%R@t|V z&9Ah(g`HlL>VEr(Xj)!(?ED9GliGA?)>Thc{j1}5g^BxZZ(oFmMJx=8iru}pd3gR? zGasKRg*RErJVQ^T&Uy5~K3s^laQ4lB^ueXcJ3FrqY8XKArD$md`^Xo{Jou`R*wi$+ zbc=hxsZlgrJ`-Rnv?)1kJzQf|p^oLZN~|04kIPY}iK=!(k7n4ndy8fQ+T<-RQU~dT zY<3)6c)3j8WIa!|DQvrf{SCRa@F6zPTdYlLG*N#iqY;FP|1^U~!!YWeGV?qcEED)b z->1*xMqxXc-gYOR5C&`{OC-+;kSg@5Xy8L0mOUPCkfLKD< z0ND~3X?NH*mr#!yj?v=niVgn9W=5`@;%erMH5)K;kal~rM~b9Z0{(+GW@+Bsc)7v} zx@TmOoH+8RqRve4UjnyHFVlbIc%#L?;mkF%M_&@!b_J{$f_QO>q_0^21?H9T!U|1c z_z-zbNJdBEAu($|2G@w#VO_W1_K{6fb2*F=R;Qf9TL;1tXXq-Pl~bW1TOH)Gh^ zgBLx>mOrKEfxjGq#gxR~Lzafp92*z=xMa?dTwgaQCZ9zFh*PowzuDPut-u)R=uK!q zkIJlnynhB_N(w5>@KfJAOYJAsF5v^-1KTscsDz~QM z`0MLcrcG(Bt&iv`4s}dT9}kfl?XSkba^wGcd5M#l-Z@x}p+8hkKuPyDG9E}uJIoeQ z1kZIyaU2m5C`gow+57o5FptFTQgdn|IEX_{_P@F9L||+hT#2BoB>L-A>By zdBS}{`SXB$3)Y|@u?L}*oU{{Gc*91K1AcXXmUClHbgcZM`=zjwOi9m|*Btv%5B$Xv_KZ<1}E+u2ZCJ7SJulBk!6jHH8% z+4BrOZtv$6ea_KrQCm(UYV`I8Dj?Qo{ELuohv;U`?B+N@iJ{Hp&!6F-pSkkhgXx=g zNY8asBOi{e=BstsnLpt>sV6CGM-;D{n#ezPnB1HntwsJ0Lpr|G3;KMaNc&UPP@TZ; z3skMdR{+%XUMg9xGOfizsER{i(tW@=gsKy1VkyeIQ-IOk*et->7%CsT2bvbmETYy^ z($1=QbhP)ro6=GsmyDqxk8}PVRsAX7hJ)`(9;^Okkpu9&V zv>Ur`)f@nWMbpC*Dak_YZX@m>n>{dk1NU6>^M)+)we&57c_z7bDrc}zS&)O&_g~xX z!%u|u+b$PgAHWJjkk#%e!7?N{H7YYo|LR;{Zu3>|FqzJFEu)^9hG}qf1B6$duOFB< zsr&u!74FggbZVM8<1G9VoHdr8QQsjFfcxWd2dJ6_INAj`K^^>@Z~{Dlh)M}VB!wXl zj6@+&hy+wrR1hKwg+P+3FFF4Yfbe#7bAI~&0~fzkN^k(|UkCpuE>L?re<$HUKR3YH z&C>}A27_I_5l&z`M}(Uf*v-M)OW4`lD*zmT@cGZP@p6`sa&_?yl5+6{`@1^XJGqJA Vs)UVlQ{##PFjcrpy^?Lr{{YZ8N?`y1 literal 0 HcmV?d00001 diff --git a/static/dtu.png b/static/dtu.png new file mode 100644 index 0000000000000000000000000000000000000000..08e5884f81452dfce288f62c08d07599f5e20e59 GIT binary patch literal 5847 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 X0uMGmfh40IOae4ibd+lp?IQmJqWnif literal 0 HcmV?d00001 diff --git a/static/gateway.png b/static/gateway.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3f4c75bb3120ab35d708f3dc8cc4011bc26454 GIT binary patch literal 2418 zcmV-&361uNP)sKqik}m|Go9zec?te_&+m~K zt`sTqJDIZoh9981slR7la4%(Zj%5FgJpzQT@ivy?EqTYCdwZ@i+>A zD;io%jGqFSNr1;mW0}zopoxha;@-g9PRVuz0CzYz2ZUD%G{q^ya>zLh;umApf&bXm zXA6LmXv24lSo^qYSa7`3iJc&-u%e{D zXc;&IR_3a{WnY-pX&L}mc=L}5${R!|H7k4|=oq*Kg%+uk>Ke`HHwAzz68x_+3+IQG8O}_PiHDCC4^{9mkh>5a%w-dU zRjr7=-!ai2&P1Cz0*-}7dOC3ggi*N^74&z;g;=S(8esD^-l+tnaFxVy3jUQby{)bn2*!fRKo1=h;p z>B1Y?{X#*6wFp9`9BchDF8g-;F};?WEX%v57%INSE7?}pWVC*(OBz^ZK9c0f1L4?np(O-Hnd1 z*U~vJ-{mh;LKGm@UpbBqhG?no142I0)E6*jzOH&(%0R0%Jp$ZELq8-9d+Z=9p?`AR z!qm7o8k#8~X3{5l;`#p_N`<=-*sl|DRGoO+fuX>&V%|Vg5`b{%H6r}N4gf|YKfZMl zvkjqY92TNO65`ft&4_f(1m4mzEGet(mH7IGyHSQCQ2_i!_4=RH0q}%FU)f#rpBlF? z)k%AWVJW$*UjG;>ITrF2CGeS@ z-j``l!oRzB$DT+Umu*;N(q{yrZ@3#lmSJFbTGW^(k|)xz9Nw$^4m{pEgL zoXqJPznv@?%Sm|7{<|OIYl zf4cRBRUepnEqNlLHvlZQ%50ZD8vu4?o91UUkUJ9mfIvSm&EybaAppR@P8k9b0;(PI z%e0t6007`m$sG4i}5F`l8c{#Zn7%O2S5gIl38F4fS0T~(RbNu zmETGFzSF2_*~Gt>9I%pz)|+PPBD@y>V8+j6C79RI*S!FMM*IYMqQNm>vRs3{7XXNr z6pv2U10uoW1R7^$7~JguFc4L}es4Db>j?B*e**Av+eJ(t+;d1GWpddemUm5!*Awwx zrE}RANF6a<%P$G?A7b9XOUZ&rH264}KI|_57M*Xxj_WP@Il%5QHF)oO3u@0d>FQ5a zE!06sH?>KXSayVcTRs4ED*R~Yq`)W1s<2)ZEx$%YL(PIpq#W~ymP5i__WTm&B3GJ3 z#rmr~H3HcR|8ewGoyK+qFmH?b0!w-U;Esmo62sKJ8ey~pfY~TBOP5Ck)Tq9|?p^@s zxgZ=m2tvInqCa-GlTry3P6IDDILCLsUq-g$K&pB z=zSv0%LT&S2mpisrFsKT7=6190N2qi)rzJ?aseQ_!Gn(^>vjX#B!Nyly(8ytP>#k? zLRIQ`|LLp%bmf9=ApP2V)+QiG>3blX9HW`q3NspFKEJ=Ot?4gGo!IhCkE(r|??Z=y z1SG9)#<>_{GA8@KHV1(04?f>iiH@SfL>N+V4p}p(m5UQo)d?%o-pt5)Q?xkRFr!H0 zCL$DB(^(kQ%-o?7&FJv@4`i|^=T%uxG*kyhs4!fzW`zb`9QOwPnT;za0K)9V@tHN# z?Nc-Gg6j3J%O%Ma09_y~B+yo;A4BCb(CT-&AI!{8#(m4*HN$Hf01>7irFZJj*hZTX z-tRPw3tEv<6Q8s!YF4);0Cb^8f+IW%HG=Rxvr77j?m*1ro}cMbblyoY{k*!j*d0B$ z5{y@fpzo^(u(dLHwOT!R1E@A()eh?sVAOExAH&`4YCVXbCXixPxgC0DBtX1TE!I|H z!iwJa@GJgg;HjQjlW2NeMz2O&1NNB{r;07*qoM6N<$f|#d(ivR!s literal 0 HcmV?d00001 diff --git a/static/head.png b/static/head.png new file mode 100644 index 0000000000000000000000000000000000000000..be6fa38ffd27a864c05d7b1667bf7acf60e3ad59 GIT binary patch literal 2749 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 literal 0 HcmV?d00001 diff --git a/static/icon_del.png b/static/icon_del.png new file mode 100644 index 0000000000000000000000000000000000000000..69991713c47c3d86750e0aefdcb3b589d8bb0b5e GIT binary patch literal 975 zcmV;=12FuFP)}sKE4|>vzhayN1_KaAda13LR_|qED zd+-&&Lj*R3u@&H7Kz??XFkSj2`#7j=AcD!i%sx%iCk6PDgdTM9W_luUsNpBK>`W|v zY|g9JQW8u(u!f=GEWiz_#lp#D0WQ9=w`H%ivujOoW>hy4{pSfD4hI}gTOdCaOHYnr z$0etkWpjcv=DJiuzXo7mIJl0rZ`md1bL=o*HLkFl;LNC=N(}t|7Rl8(-LgxM_cwZS z6+t6!U0Um~w(_$d?o4)cxqJn|YC`arjsw*VLsv$YCr+K9UrJ)}huzQCu&ialt&~5i zm7qF7V>Wkz#1YkUB6v-rSEbiN?j^xGm8}Ra7PpQc_4Is#iTp&rE6_j9gch&z>yKo25QDM4*ER90$It2$*%8l}N1iC@acLZ^RMm|>{ zFcg+xD^FGzZtvZoSOR&-R6h3t!1|y@Do=XyPBOg({!7n;4uN>51RFi+{SI4(T49Tz z;t?zn_#m7l1P^s;5R1oR#pQ~h6!;vwAXIc8dmf?BHB+4-fqJh8!TnUstxOZUW{(b?;lT5zchIy zQ-!Hvi2H7@ozzC`^tbhSP1G*#KNd6D6|$)qjQHGgYcA92B+cfQ6Rv)l|rIlxTLSzl-_rn^59kp+Oq?9BMpcAHlc zte2p;J}GW@M!*0ri|c&Xl@ajr-6iI%0p0zdLv#((rJ*hl(N~4Qdxn_Pc8VL@3(9r~ xKde7Pcmp4zD1xV;`~%^AYL(meP-o8&ZvbW2o>NJG2dV%7002ovPDHLkV1fo$$gKbX literal 0 HcmV?d00001 diff --git a/static/icon_pwd.png b/static/icon_pwd.png new file mode 100644 index 0000000000000000000000000000000000000000..d86afd67e1c878abec0ee575bc5f2890432d6e42 GIT binary patch literal 635 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 literal 0 HcmV?d00001 diff --git a/static/location_active.png b/static/location_active.png new file mode 100644 index 0000000000000000000000000000000000000000..1e573830542b1d7c5b2183d1d69d9ba376fe366b GIT binary patch literal 3860 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 R4yi!_#s&}cD|OwT{RdrrT7&=q literal 0 HcmV?d00001 diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b5771e209bb677e2ebd5ff766ad5ee11790f305a GIT binary patch literal 4023 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 SYs}WS&%*SCNx89m_iq1$#>YJ}Eu`00gY9 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 W1P2xPsfdAd0c#6;^IDAWjlTgW+^qlr literal 0 HcmV?d00001 diff --git a/static/user_active.png b/static/user_active.png new file mode 100644 index 0000000000000000000000000000000000000000..dfdabc35783ffb6d70fc8f69dc4197e8cf49a096 GIT binary patch literal 2621 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 E50b38mjD0& literal 0 HcmV?d00001 diff --git a/store/getters.js b/store/getters.js new file mode 100644 index 0000000..3b7c4a5 --- /dev/null +++ b/store/getters.js @@ -0,0 +1,7 @@ +const getters = { + token: state => state.user.token, + avatar: state => state.user.avatar, + name: state => state.user.name, + roles: state => state.user.roles +} +export default getters diff --git a/store/index.js b/store/index.js new file mode 100644 index 0000000..95a926a --- /dev/null +++ b/store/index.js @@ -0,0 +1,15 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import user from './user' +import getters from './getters' + +Vue.use(Vuex) + +const store = new Vuex.Store({ + modules: { + user + }, + getters +}) + +export default store diff --git a/store/user.js b/store/user.js new file mode 100644 index 0000000..a45d105 --- /dev/null +++ b/store/user.js @@ -0,0 +1,87 @@ +import { login, logout, getInfo } from '@/api/login' +import { getToken, setToken, removeToken } from '@/common/auth' + +const user = { + state: { + token: getToken(), + name: '', + avatar: '', + roles: [] + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_NAME: (state, name) => { + state.name = name + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + }, + SET_ROLES: (state, roles) => { + state.roles = roles + } + }, + + actions: { + // 登录 + Login({ commit }, userInfo) { + const username = userInfo.username.trim() + return new Promise((resolve, reject) => { + login(username, userInfo.password).then(response => { + const data = response.data + setToken(data.token) + commit('SET_TOKEN', data.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo(state.token).then(response => { + const data = response.data + // if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组 + // commit('SET_ROLES', data.roles) + // } else { + // reject('getInfo: roles must be a non-null array !') + // } + commit('SET_NAME', data.name) + commit('SET_AVATAR', data.avatar) + resolve(response) + }).catch(error => { + reject(error) + }) + }) + }, + + // 登出 + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 前端 登出 + FedLogOut({ commit }) { + return new Promise(resolve => { + commit('SET_TOKEN', '') + removeToken() + resolve() + }) + } + } +} + +export default user diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..b9ce20d --- /dev/null +++ b/uni.scss @@ -0,0 +1,106 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:24upx; +$uni-font-size-base:28upx; +$uni-font-size-lg:32upx; + +/* 图片尺寸 */ +$uni-img-size-sm:40upx; +$uni-img-size-base:52upx; +$uni-img-size-lg:80upx; + +/* Border Radius */ +$uni-border-radius-sm: 4upx; +$uni-border-radius-base: 6upx; +$uni-border-radius-lg: 12upx; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 10px; +$uni-spacing-row-base: 20upx; +$uni-spacing-row-lg: 30upx; + +/* 垂直间距 */ +$uni-spacing-col-sm: 8upx; +$uni-spacing-col-base: 16upx; +$uni-spacing-col-lg: 24upx; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:40upx; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:36upx; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:30upx; + +// custom + +/* 页面左右间距 */ +$page-row-spacing: 30upx; +$page-color-base: #f8f8f8; +$page-color-light: #f8f6fc; +$base-color: #fa436a; + +/* 文字尺寸 */ +$font-sm: 24upx; +$font-base: 28upx; +$font-lg: 32upx; +/*文字颜色*/ +$font-color-dark: #303133; +$font-color-base: #606266; +$font-color-light: #909399; +$font-color-disabled: #C0C4CC; +$font-color-spec: #4399fc; +/* 边框颜色 */ +$border-color-dark: #DCDFE6; +$border-color-base: #E4E7ED; +$border-color-light: #EBEEF5; +/* 图片加载中颜色 */ +$image-bg-color: #eee; +/* 行为相关颜色 */ +$uni-color-primary:#fa436a; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d;