diff --git a/LICENSE b/LICENSE index ad64675..8d0c30c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 王兵 +Copyright (c) 2019 王兵 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/gulpfile.js b/gulpfile.js index 3ecaab5..fb292c2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,11 +5,11 @@ const config = require('./tools/config') const BuildTask = require('./tools/build') const id = require('./package.json').name || 'miniprogram-custom-component' -// build task instance +// 构建任务实例 // eslint-disable-next-line no-new new BuildTask(id, config.entry) -// clean the generated folders and files +// 清空生成目录和文件 gulp.task('clean', gulp.series(() => gulp.src(config.distPath, {read: false, allowEmpty: true}).pipe(clean()), done => { if (config.isDev) { return gulp.src(config.demoDist, {read: false, allowEmpty: true}) @@ -18,9 +18,9 @@ gulp.task('clean', gulp.series(() => gulp.src(config.distPath, {read: false, all return done() })) -// watch files and build +// 监听文件变化并进行开发模式构建 gulp.task('watch', gulp.series(`${id}-watch`)) -// build for develop +// 开发模式构建 gulp.task('dev', gulp.series(`${id}-dev`)) -// build for publish +// 生产模式构建 gulp.task('default', gulp.series(`${id}-default`)) diff --git a/package.json b/package.json index 82a223c..4739218 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,7 @@ "testEnvironment": "jsdom", "testURL": "https://jest.test", "collectCoverageFrom": [ - "src/**/*.js", - "!src/utils/calendar.js" + "src/**/*.js" ], "moduleDirectories": [ "node_modules", @@ -45,23 +44,26 @@ "babel-preset-env": "^1.7.0", "colors": "^1.3.1", "eslint": "^5.3.0", + "eslint-config-airbnb-base": "13.1.0", "eslint-loader": "^2.1.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-node": "^7.0.1", + "eslint-plugin-promise": "^3.8.0", "gulp": "^4.0.0", "gulp-clean": "^0.4.0", "gulp-if": "^2.0.2", "gulp-install": "^1.1.0", - "gulp-less": "^3.5.0", + "gulp-less": "^4.0.1", "gulp-rename": "^1.4.0", "gulp-sourcemaps": "^2.6.4", - "j-component": "git+https://github.com/JuneAndGreen/j-component.git", "jest": "^23.5.0", + "miniprogram-simulate": "latest", "through2": "^2.0.3", + "vinyl": "^2.2.0", "webpack": "^4.16.5", - "webpack-node-externals": "^1.7.2", - "eslint-config-airbnb-base": "13.1.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-node": "^7.0.1", - "eslint-plugin-promise": "^3.8.0" + "webpack-node-externals": "^1.7.2" }, - "dependencies": {} + "dependencies": { + "calendar": "github:pithyone/calendar.js" + } } diff --git a/src/index.js b/src/index.js index 9674e0a..18e3565 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -const calendar = require('utils/calendar') +const calendar = require('calendar') const start = 1901 const years = Array.from(new Array(200), (val, index) => index + start + '年') @@ -6,7 +6,6 @@ const months = Array.from(new Array(12), (val, index) => index + 1 + '月') const chinaMonths = Array.from(new Array(12), (val, index) => calendar.toChinaMonth(index + 1)) Component({ - externalClasses: ['picker-class'], properties: { value: { type: String, @@ -25,7 +24,7 @@ Component({ }, }, methods: { - _bindchange(e) { + _bindMultiPickerChange(e) { this.setData({ multiIndex: e.detail.value, }) @@ -33,9 +32,9 @@ Component({ const value = e.detail.value const [y, m, d] = [value[0] + start, value[1] + 1, value[2] + 1] - this.triggerEvent('change', {value: y + '-' + this._fill(m) + '-' + this._fill(d)}) + this.triggerEvent('change', {value: y + '-' + this._dateFormat(m) + '-' + this._dateFormat(d)}) }, - _bindcolumnchange(e) { + _bindMultiPickerColumnChange(e) { const multiArray = this.data.multiArray const multiIndex = this.data.multiIndex @@ -51,9 +50,9 @@ Component({ } if (this.data.chinese) { - multiArray[2] = this._computedMonthDays(y, m) + multiArray[2] = this._monthDaysCompute(y, m) } else { - multiArray[2] = this._computedSolarDays(y, m) + multiArray[2] = this._solarDaysCompute(y, m) } this.setData({ @@ -61,7 +60,7 @@ Component({ multiIndex, }) }, - _bindcancel() { + _bindMultiPickerCancel() { this._init() }, _init() { @@ -71,27 +70,27 @@ Component({ [y, m, d] = this.data.value.split('-') .map(Number) } else { - const day = new Date(); - [y, m, d] = [day.getFullYear(), day.getMonth() + 1, day.getDate()] + const lunar = calendar.solar2lunar(); + [y, m, d] = [lunar.cYear, lunar.cMonth, lunar.cDay] } if (this.data.chinese) { const day = this.data.value ? calendar.lunar2solar(y, m, d) : calendar.solar2lunar(y, m, d); [y, m, d] = [day.lYear, day.lMonth, day.lDay] - const days = this._computedMonthDays(y, m) + const days = this._monthDaysCompute(y, m) this.setData({ multiArray: [years, chinaMonths, days], multiIndex: [y - start, m - 1, d - 1], }) } else { - const days = this._computedSolarDays(y, m) + const days = this._solarDaysCompute(y, m) this.setData({ multiArray: [years, months, days], multiIndex: [y - start, m - 1, d - 1], }) } }, - _computedSolarDays(y, m) { + _solarDaysCompute(y, m) { const day = calendar.solarDays(y, m) return Array.from(new Array(day), (val, index) => { const date = index + 1 @@ -99,12 +98,12 @@ Component({ return date + '日 ' + lunar.ncWeek }) }, - _computedMonthDays(y, m) { + _monthDaysCompute(y, m) { const day = calendar.monthDays(y, m) return Array.from(new Array(day), (val, index) => calendar.toChinaDay(index + 1)) }, - _fill(d) { - return (d < 10 ? '0' : '') + d + _dateFormat(n) { + return (n < 10 ? '0' : '') + n }, }, }) diff --git a/src/index.wxml b/src/index.wxml index b27b078..24efba7 100644 --- a/src/index.wxml +++ b/src/index.wxml @@ -1,4 +1,10 @@ - + diff --git a/src/utils/calendar.js b/src/utils/calendar.js deleted file mode 100644 index f9dbc07..0000000 --- a/src/utils/calendar.js +++ /dev/null @@ -1,560 +0,0 @@ -/* eslint-disable */ - -;(function(root, factory) { - if (typeof define === 'function' && define.amd) { - define([], factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.Calendar = factory(); - } -}(this, function() { - /** - * @1900-2100区间内的公历、农历互转 - * @charset UTF-8 - * @Author Jea杨(JJonline@JJonline.Cn) - * @Time 2014-7-21 - * @Time 2016-8-13 Fixed 2033hex、Attribution Annals - * @Time 2016-9-25 Fixed lunar LeapMonth Param Bug - * @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year - * @Version 1.0.3 - * @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0] - * @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0] - */ - var Calendar = { - - /** - * 农历1900-2100的润大小信息表 - * @Array Of Property - * @return Hex - */ - lunarInfo:[0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,//1900-1909 - 0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,//1910-1919 - 0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,//1920-1929 - 0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,//1930-1939 - 0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,//1940-1949 - 0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,//1950-1959 - 0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,//1960-1969 - 0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,0x195a6,//1970-1979 - 0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,//1980-1989 - 0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,//1990-1999 - 0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,//2000-2009 - 0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,//2010-2019 - 0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,//2020-2029 - 0x05aa0,0x076a3,0x096d0,0x04afb,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,//2030-2039 - 0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0,//2040-2049 - /**Add By JJonline@JJonline.Cn**/ - 0x14b63,0x09370,0x049f8,0x04970,0x064b0,0x168a6,0x0ea50, 0x06b20,0x1a6c4,0x0aae0,//2050-2059 - 0x0a2e0,0x0d2e3,0x0c960,0x0d557,0x0d4a0,0x0da50,0x05d55,0x056a0,0x0a6d0,0x055d4,//2060-2069 - 0x052d0,0x0a9b8,0x0a950,0x0b4a0,0x0b6a6,0x0ad50,0x055a0,0x0aba4,0x0a5b0,0x052b0,//2070-2079 - 0x0b273,0x06930,0x07337,0x06aa0,0x0ad50,0x14b55,0x04b60,0x0a570,0x054e4,0x0d160,//2080-2089 - 0x0e968,0x0d520,0x0daa0,0x16aa6,0x056d0,0x04ae0,0x0a9d4,0x0a2d0,0x0d150,0x0f252,//2090-2099 - 0x0d520],//2100 - - /** - * 公历每个月份的天数普通表 - * @Array Of Property - * @return Number - */ - solarMonth:[31,28,31,30,31,30,31,31,30,31,30,31], - - /** - * 天干地支之天干速查表 - * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"] - * @return Cn string - */ - Gan:["\u7532","\u4e59","\u4e19","\u4e01","\u620a","\u5df1","\u5e9a","\u8f9b","\u58ec","\u7678"], - - /** - * 天干地支之地支速查表 - * @Array Of Property - * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"] - * @return Cn string - */ - Zhi:["\u5b50","\u4e11","\u5bc5","\u536f","\u8fb0","\u5df3","\u5348","\u672a","\u7533","\u9149","\u620c","\u4ea5"], - - /** - * 天干地支之地支速查表<=>生肖 - * @Array Of Property - * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"] - * @return Cn string - */ - Animals:["\u9f20","\u725b","\u864e","\u5154","\u9f99","\u86c7","\u9a6c","\u7f8a","\u7334","\u9e21","\u72d7","\u732a"], - - /** - * 24节气速查表 - * @Array Of Property - * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"] - * @return Cn string - */ - solarTerm:["\u5c0f\u5bd2","\u5927\u5bd2","\u7acb\u6625","\u96e8\u6c34","\u60ca\u86f0","\u6625\u5206","\u6e05\u660e","\u8c37\u96e8","\u7acb\u590f","\u5c0f\u6ee1","\u8292\u79cd","\u590f\u81f3","\u5c0f\u6691","\u5927\u6691","\u7acb\u79cb","\u5904\u6691","\u767d\u9732","\u79cb\u5206","\u5bd2\u9732","\u971c\u964d","\u7acb\u51ac","\u5c0f\u96ea","\u5927\u96ea","\u51ac\u81f3"], - - /** - * 1900-2100各年的24节气日期速查表 - * @Array Of Property - * @return 0x string For splice - */ - sTermInfo:['9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf97c3598082c95f8c965cc920f', - '97bd0b06bdb0722c965ce1cfcc920f','b027097bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e', - '97bcf97c359801ec95f8c965cc920f','97bd0b06bdb0722c965ce1cfcc920f','b027097bd097c36b0b6fc9274c91aa', - '97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f','97bd0b06bdb0722c965ce1cfcc920f', - 'b027097bd097c36b0b6fc9274c91aa','9778397bd19801ec9210c965cc920e','97b6b97bd19801ec95f8c965cc920f', - '97bd09801d98082c95f8e1cfcc920f','97bd097bd097c36b0b6fc9210c8dc2','9778397bd197c36c9210c9274c91aa', - '97b6b97bd19801ec95f8c965cc920e','97bd09801d98082c95f8e1cfcc920f','97bd097bd097c36b0b6fc9210c8dc2', - '9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec95f8c965cc920e','97bcf97c3598082c95f8e1cfcc920f', - '97bd097bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec9210c965cc920e', - '97bcf97c3598082c95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa', - '97b6b97bd19801ec9210c965cc920e','97bcf97c3598082c95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722', - '9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f', - '97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e', - '97bcf97c359801ec95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa', - '97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f','97bd097bd07f595b0b6fc920fb0722', - '9778397bd097c36b0b6fc9210c8dc2','9778397bd19801ec9210c9274c920e','97b6b97bd19801ec95f8c965cc920f', - '97bd07f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c920e', - '97b6b97bd19801ec95f8c965cc920f','97bd07f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2', - '9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec9210c965cc920e','97bd07f1487f595b0b0bc920fb0722', - '7f0e397bd097c36b0b6fc9210c8dc2','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e', - '97bcf7f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa', - '97b6b97bd19801ec9210c965cc920e','97bcf7f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722', - '9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf7f1487f531b0b0bb0b6fb0722', - '7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e', - '97bcf7f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa', - '97b6b97bd19801ec9210c9274c920e','97bcf7f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722', - '9778397bd097c36b0b6fc9210c91aa','97b6b97bd197c36c9210c9274c920e','97bcf7f0e47f531b0b0bb0b6fb0722', - '7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c920e', - '97b6b7f0e47f531b0723b0b6fb0722','7f0e37f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2', - '9778397bd097c36b0b70c9274c91aa','97b6b7f0e47f531b0723b0b6fb0721','7f0e37f1487f595b0b0bb0b6fb0722', - '7f0e397bd097c35b0b6fc9210c8dc2','9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721', - '7f0e27f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa', - '97b6b7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722', - '9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722', - '7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721', - '7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9274c91aa', - '97b6b7f0e47f531b0723b0787b0721','7f0e27f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722', - '9778397bd097c36b0b6fc9210c91aa','97b6b7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722', - '7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9210c8dc2','977837f0e37f149b0723b0787b0721', - '7f07e7f0e47f531b0723b0b6fb0722','7f0e37f5307f595b0b0bc920fb0722','7f0e397bd097c35b0b6fc9210c8dc2', - '977837f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0721','7f0e37f1487f595b0b0bb0b6fb0722', - '7f0e397bd097c35b0b6fc9210c8dc2','977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721', - '7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','977837f0e37f14998082b0787b06bd', - '7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722', - '977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722', - '7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721', - '7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14998082b0787b06bd', - '7f07e7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722', - '977837f0e37f14998082b0723b06bd','7f07e7f0e37f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722', - '7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b0721', - '7f07e7f0e47f531b0723b0b6fb0722','7f0e37f1487f595b0b0bb0b6fb0722','7f0e37f0e37f14898082b0723b02d5', - '7ec967f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0722','7f0e37f1487f531b0b0bb0b6fb0722', - '7f0e37f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721', - '7f0e37f1487f531b0b0bb0b6fb0722','7f0e37f0e37f14898082b072297c35','7ec967f0e37f14998082b0787b06bd', - '7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e37f0e37f14898082b072297c35', - '7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722', - '7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f149b0723b0787b0721', - '7f0e27f1487f531b0b0bb0b6fb0722','7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14998082b0723b06bd', - '7f07e7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722','7f0e37f0e366aa89801eb072297c35', - '7ec967f0e37f14998082b0723b06bd','7f07e7f0e37f14998083b0787b0721','7f0e27f0e47f531b0723b0b6fb0722', - '7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14898082b0723b02d5','7f07e7f0e37f14998082b0787b0721', - '7f07e7f0e47f531b0723b0b6fb0722','7f0e36665b66aa89801e9808297c35','665f67f0e37f14898082b0723b02d5', - '7ec967f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0722','7f0e36665b66a449801e9808297c35', - '665f67f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721', - '7f0e36665b66a449801e9808297c35','665f67f0e37f14898082b072297c35','7ec967f0e37f14998082b0787b06bd', - '7f07e7f0e47f531b0723b0b6fb0721','7f0e26665b66a449801e9808297c35','665f67f0e37f1489801eb072297c35', - '7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722'], - - /** - * 数字转中文速查表 - * @Array Of Property - * @trans ['日','一','二','三','四','五','六','七','八','九','十'] - * @return Cn string - */ - nStr1:["\u65e5","\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341"], - - /** - * 日期转农历称呼速查表 - * @Array Of Property - * @trans ['初','十','廿','卅'] - * @return Cn string - */ - nStr2:["\u521d","\u5341","\u5eff","\u5345"], - - /** - * 月份转农历称呼速查表 - * @Array Of Property - * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊'] - * @return Cn string - */ - nStr3:["\u6b63","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u51ac","\u814a"], - - /** - * 返回农历y年一整年的总天数 - * @param lunar Year - * @return Number - * @eg:var count = calendar.lYearDays(1987) ;//count=387 - */ - lYearDays:function(y) { - var i, sum = 348; - for(i=0x8000; i>0x8; i>>=1) { sum += (this.lunarInfo[y-1900] & i)? 1: 0; } - return(sum+this.leapDays(y)); - }, - - /** - * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0 - * @param lunar Year - * @return Number (0-12) - * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6 - */ - leapMonth:function(y) { //闰字编码 \u95f0 - return(this.lunarInfo[y-1900] & 0xf); - }, - - /** - * 返回农历y年闰月的天数 若该年没有闰月则返回0 - * @param lunar Year - * @return Number (0、29、30) - * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29 - */ - leapDays:function(y) { - if(this.leapMonth(y)) { - return((this.lunarInfo[y-1900] & 0x10000)? 30: 29); - } - return(0); - }, - - /** - * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法 - * @param lunar Year - * @return Number (-1、29、30) - * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29 - */ - monthDays:function(y,m) { - if(m>12 || m<1) {return -1}//月份参数从1至12,参数错误返回-1 - return( (this.lunarInfo[y-1900] & (0x10000>>m))? 30: 29 ); - }, - - /** - * 返回公历(!)y年m月的天数 - * @param solar Year - * @return Number (-1、28、29、30、31) - * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30 - */ - solarDays:function(y,m) { - if(m>12 || m<1) {return -1} //若参数错误 返回-1 - var ms = m-1; - if(ms==1) { //2月份的闰平规律测算后确认返回28或29 - return(((y%4 == 0) && (y%100 != 0) || (y%400 == 0))? 29: 28); - }else { - return(this.solarMonth[ms]); - } - }, - - /** - * 农历年份转换为干支纪年 - * @param lYear 农历年的年份数 - * @return Cn string - */ - toGanZhiYear:function(lYear) { - var ganKey = (lYear - 3) % 10; - var zhiKey = (lYear - 3) % 12; - if(ganKey == 0) ganKey = 10;//如果余数为0则为最后一个天干 - if(zhiKey == 0) zhiKey = 12;//如果余数为0则为最后一个地支 - return this.Gan[ganKey-1] + this.Zhi[zhiKey-1]; - - }, - - /** - * 公历月、日判断所属星座 - * @param cMonth [description] - * @param cDay [description] - * @return Cn string - */ - toAstro:function(cMonth,cDay) { - var s = "\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf"; - var arr = [20,19,21,21,21,22,23,23,23,23,22,22]; - return s.substr(cMonth*2 - (cDay < arr[cMonth-1] ? 2 : 0),2) + "\u5ea7";//座 - }, - - /** - * 传入offset偏移量返回干支 - * @param offset 相对甲子的偏移量 - * @return Cn string - */ - toGanZhi:function(offset) { - return this.Gan[offset%10] + this.Zhi[offset%12]; - }, - - /** - * 传入公历(!)y年获得该年第n个节气的公历日期 - * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起 - * @return day Number - * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春 - */ - getTerm:function(y,n) { - if(y<1900 || y>2100) {return -1;} - if(n<1 || n>24) {return -1;} - var _table = this.sTermInfo[y-1900]; - var _info = [ - parseInt('0x'+_table.substr(0,5)).toString() , - parseInt('0x'+_table.substr(5,5)).toString(), - parseInt('0x'+_table.substr(10,5)).toString(), - parseInt('0x'+_table.substr(15,5)).toString(), - parseInt('0x'+_table.substr(20,5)).toString(), - parseInt('0x'+_table.substr(25,5)).toString() - ]; - var _calday = [ - _info[0].substr(0,1), - _info[0].substr(1,2), - _info[0].substr(3,1), - _info[0].substr(4,2), - - _info[1].substr(0,1), - _info[1].substr(1,2), - _info[1].substr(3,1), - _info[1].substr(4,2), - - _info[2].substr(0,1), - _info[2].substr(1,2), - _info[2].substr(3,1), - _info[2].substr(4,2), - - _info[3].substr(0,1), - _info[3].substr(1,2), - _info[3].substr(3,1), - _info[3].substr(4,2), - - _info[4].substr(0,1), - _info[4].substr(1,2), - _info[4].substr(3,1), - _info[4].substr(4,2), - - _info[5].substr(0,1), - _info[5].substr(1,2), - _info[5].substr(3,1), - _info[5].substr(4,2), - ]; - return parseInt(_calday[n-1]); - }, - - /** - * 传入农历数字月份返回汉语通俗表示法 - * @param lunar month - * @return Cn string - * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月' - */ - toChinaMonth:function(m) { // 月 => \u6708 - if(m>12 || m<1) {return -1} //若参数错误 返回-1 - var s = this.nStr3[m-1]; - s+= "\u6708";//加上月字 - return s; - }, - - /** - * 传入农历日期数字返回汉字表示法 - * @param lunar day - * @return Cn string - * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一' - */ - toChinaDay:function(d){ //日 => \u65e5 - var s; - switch (d) { - case 10: - s = '\u521d\u5341'; break; - case 20: - s = '\u4e8c\u5341'; break; - break; - case 30: - s = '\u4e09\u5341'; break; - break; - default : - s = this.nStr2[Math.floor(d/10)]; - s += this.nStr1[d%10]; - } - return(s); - }, - - /** - * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春” - * @param y year - * @return Cn string - * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔' - */ - getAnimal: function(y) { - return this.Animals[(y - 4) % 12] - }, - - /** - * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON - * @param y solar year - * @param m solar month - * @param d solar day - * @return JSON object - * @eg:console.log(calendar.solar2lunar(1987,11,01)); - */ - solar2lunar:function (y,m,d) { //参数区间1900.1.31~2100.12.31 - //年份限定、上限 - if(y<1900 || y>2100) { - return -1;// undefined转换为数字变为NaN - } - //公历传参最下限 - if(y==1900&&m==1&&d<31) { - return -1; - } - //未传参 获得当天 - if(!y) { - var objDate = new Date(); - }else { - var objDate = new Date(y,parseInt(m)-1,d) - } - var i, leap=0, temp=0; - //修正ymd参数 - var y = objDate.getFullYear(), - m = objDate.getMonth()+1, - d = objDate.getDate(); - var offset = (Date.UTC(objDate.getFullYear(),objDate.getMonth(),objDate.getDate()) - Date.UTC(1900,0,31))/86400000; - for(i=1900; i<2101 && offset>0; i++) { - temp = this.lYearDays(i); - offset -= temp; - } - if(offset<0) { - offset+=temp; i--; - } - - //是否今天 - var isTodayObj = new Date(), - isToday = false; - if(isTodayObj.getFullYear()==y && isTodayObj.getMonth()+1==m && isTodayObj.getDate()==d) { - isToday = true; - } - //星期几 - var nWeek = objDate.getDay(), - cWeek = this.nStr1[nWeek]; - //数字表示周几顺应天朝周一开始的惯例 - if(nWeek==0) { - nWeek = 7; - } - //农历年 - var year = i; - var leap = this.leapMonth(i); //闰哪个月 - var isLeap = false; - - //效验闰月 - for(i=1; i<13 && offset>0; i++) { - //闰月 - if(leap>0 && i==(leap+1) && isLeap==false){ - --i; - isLeap = true; temp = this.leapDays(year); //计算农历闰月天数 - } - else{ - temp = this.monthDays(year, i);//计算农历普通月天数 - } - //解除闰月 - if(isLeap==true && i==(leap+1)) { isLeap = false; } - offset -= temp; - } - // 闰月导致数组下标重叠取反 - if(offset==0 && leap>0 && i==leap+1) - { - if(isLeap){ - isLeap = false; - }else{ - isLeap = true; --i; - } - } - if(offset<0) - { - offset += temp; --i; - } - //农历月 - var month = i; - //农历日 - var day = offset + 1; - //天干地支处理 - var sm = m-1; - var gzY = this.toGanZhiYear(year); - - // 当月的两个节气 - // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year` - var firstNode = this.getTerm(y,(m*2-1));//返回当月「节」为几日开始 - var secondNode = this.getTerm(y,(m*2));//返回当月「节」为几日开始 - - // 依据12节气修正干支月 - var gzM = this.toGanZhi((y-1900)*12+m+11); - if(d>=firstNode) { - gzM = this.toGanZhi((y-1900)*12+m+12); - } - - //传入的日期的节气与否 - var isTerm = false; - var Term = null; - if(firstNode==d) { - isTerm = true; - Term = this.solarTerm[m*2-2]; - } - if(secondNode==d) { - isTerm = true; - Term = this.solarTerm[m*2-1]; - } - //日柱 当月一日与 1900/1/1 相差天数 - var dayCyclical = Date.UTC(y,sm,1,0,0,0,0)/86400000+25567+10; - var gzD = this.toGanZhi(dayCyclical+d-1); - //该日期所属的星座 - var astro = this.toAstro(m,d); - - return {'lYear':year,'lMonth':month,'lDay':day,'Animal':this.getAnimal(year),'IMonthCn':(isLeap?"\u95f0":'')+this.toChinaMonth(month),'IDayCn':this.toChinaDay(day),'cYear':y,'cMonth':m,'cDay':d,'gzYear':gzY,'gzMonth':gzM,'gzDay':gzD,'isToday':isToday,'isLeap':isLeap,'nWeek':nWeek,'ncWeek':"\u661f\u671f"+cWeek,'isTerm':isTerm,'Term':Term,'astro':astro}; - }, - - /** - * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON - * @param y lunar year - * @param m lunar month - * @param d lunar day - * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可] - * @return JSON object - * @eg:console.log(calendar.lunar2solar(1987,9,10)); - */ - lunar2solar:function(y,m,d,isLeapMonth) { //参数区间1900.1.31~2100.12.1 - var isLeapMonth = !!isLeapMonth; - var leapOffset = 0; - var leapMonth = this.leapMonth(y); - var leapDay = this.leapDays(y); - if(isLeapMonth&&(leapMonth!=m)) {return -1;}//传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同 - if(y==2100&&m==12&&d>1 || y==1900&&m==1&&d<31) {return -1;}//超出了最大极限值 - var day = this.monthDays(y,m); - var _day = day; - //bugFix 2016-9-25 - //if month is leap, _day use leapDays method - if(isLeapMonth) { - _day = this.leapDays(y,m); - } - if(y < 1900 || y > 2100 || d > _day) {return -1;}//参数合法性效验 - - //计算农历的时间差 - var offset = 0; - for(var i=1900;i0) { - offset+=this.leapDays(y);isAdd = true; - } - } - offset+=this.monthDays(y,i); - } - //转换闰月农历 需补充该年闰月的前一个月的时差 - if(isLeapMonth) {offset+=day;} - //1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点) - var stmap = Date.UTC(1900,1,30,0,0,0); - var calObj = new Date((offset+d-31)*86400000+stmap); - var cY = calObj.getUTCFullYear(); - var cM = calObj.getUTCMonth()+1; - var cD = calObj.getUTCDate(); - - return this.solar2lunar(cY,cM,cD); - } - }; - - return Calendar; -})); diff --git a/test/data.js b/test/data.js new file mode 100644 index 0000000..7bc3918 --- /dev/null +++ b/test/data.js @@ -0,0 +1,5 @@ +module.exports = { + years: ['1901年', '1902年', '1903年', '1904年', '1905年', '1906年', '1907年', '1908年', '1909年', '1910年', '1911年', '1912年', '1913年', '1914年', '1915年', '1916年', '1917年', '1918年', '1919年', '1920年', '1921年', '1922年', '1923年', '1924年', '1925年', '1926年', '1927年', '1928年', '1929年', '1930年', '1931年', '1932年', '1933年', '1934年', '1935年', '1936年', '1937年', '1938年', '1939年', '1940年', '1941年', '1942年', '1943年', '1944年', '1945年', '1946年', '1947年', '1948年', '1949年', '1950年', '1951年', '1952年', '1953年', '1954年', '1955年', '1956年', '1957年', '1958年', '1959年', '1960年', '1961年', '1962年', '1963年', '1964年', '1965年', '1966年', '1967年', '1968年', '1969年', '1970年', '1971年', '1972年', '1973年', '1974年', '1975年', '1976年', '1977年', '1978年', '1979年', '1980年', '1981年', '1982年', '1983年', '1984年', '1985年', '1986年', '1987年', '1988年', '1989年', '1990年', '1991年', '1992年', '1993年', '1994年', '1995年', '1996年', '1997年', '1998年', '1999年', '2000年', '2001年', '2002年', '2003年', '2004年', '2005年', '2006年', '2007年', '2008年', '2009年', '2010年', '2011年', '2012年', '2013年', '2014年', '2015年', '2016年', '2017年', '2018年', '2019年', '2020年', '2021年', '2022年', '2023年', '2024年', '2025年', '2026年', '2027年', '2028年', '2029年', '2030年', '2031年', '2032年', '2033年', '2034年', '2035年', '2036年', '2037年', '2038年', '2039年', '2040年', '2041年', '2042年', '2043年', '2044年', '2045年', '2046年', '2047年', '2048年', '2049年', '2050年', '2051年', '2052年', '2053年', '2054年', '2055年', '2056年', '2057年', '2058年', '2059年', '2060年', '2061年', '2062年', '2063年', '2064年', '2065年', '2066年', '2067年', '2068年', '2069年', '2070年', '2071年', '2072年', '2073年', '2074年', '2075年', '2076年', '2077年', '2078年', '2079年', '2080年', '2081年', '2082年', '2083年', '2084年', '2085年', '2086年', '2087年', '2088年', '2089年', '2090年', '2091年', '2092年', '2093年', '2094年', '2095年', '2096年', '2097年', '2098年', '2099年', '2100年'], + months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + chinaMonths: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], +} diff --git a/test/index.test.js b/test/index.test.js index c9e63d2..bafb9d1 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,60 +1,355 @@ -const _ = require('./utils') - -const RealDate = Date +jest.mock('calendar') -const years = ['1901年', '1902年', '1903年', '1904年', '1905年', '1906年', '1907年', '1908年', '1909年', '1910年', '1911年', '1912年', '1913年', '1914年', '1915年', '1916年', '1917年', '1918年', '1919年', '1920年', '1921年', '1922年', '1923年', '1924年', '1925年', '1926年', '1927年', '1928年', '1929年', '1930年', '1931年', '1932年', '1933年', '1934年', '1935年', '1936年', '1937年', '1938年', '1939年', '1940年', '1941年', '1942年', '1943年', '1944年', '1945年', '1946年', '1947年', '1948年', '1949年', '1950年', '1951年', '1952年', '1953年', '1954年', '1955年', '1956年', '1957年', '1958年', '1959年', '1960年', '1961年', '1962年', '1963年', '1964年', '1965年', '1966年', '1967年', '1968年', '1969年', '1970年', '1971年', '1972年', '1973年', '1974年', '1975年', '1976年', '1977年', '1978年', '1979年', '1980年', '1981年', '1982年', '1983年', '1984年', '1985年', '1986年', '1987年', '1988年', '1989年', '1990年', '1991年', '1992年', '1993年', '1994年', '1995年', '1996年', '1997年', '1998年', '1999年', '2000年', '2001年', '2002年', '2003年', '2004年', '2005年', '2006年', '2007年', '2008年', '2009年', '2010年', '2011年', '2012年', '2013年', '2014年', '2015年', '2016年', '2017年', '2018年', '2019年', '2020年', '2021年', '2022年', '2023年', '2024年', '2025年', '2026年', '2027年', '2028年', '2029年', '2030年', '2031年', '2032年', '2033年', '2034年', '2035年', '2036年', '2037年', '2038年', '2039年', '2040年', '2041年', '2042年', '2043年', '2044年', '2045年', '2046年', '2047年', '2048年', '2049年', '2050年', '2051年', '2052年', '2053年', '2054年', '2055年', '2056年', '2057年', '2058年', '2059年', '2060年', '2061年', '2062年', '2063年', '2064年', '2065年', '2066年', '2067年', '2068年', '2069年', '2070年', '2071年', '2072年', '2073年', '2074年', '2075年', '2076年', '2077年', '2078年', '2079年', '2080年', '2081年', '2082年', '2083年', '2084年', '2085年', '2086年', '2087年', '2088年', '2089年', '2090年', '2091年', '2092年', '2093年', '2094年', '2095年', '2096年', '2097年', '2098年', '2099年', '2100年'] -const months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'] -const chinaMonths = ['正月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '冬月', '腊月'] -const days = ['1日 星期四', '2日 星期五', '3日 星期六', '4日 星期日', '5日 星期一', '6日 星期二', '7日 星期三', '8日 星期四', '9日 星期五', '10日 星期六', '11日 星期日', '12日 星期一', '13日 星期二', '14日 星期三', '15日 星期四', '16日 星期五', '17日 星期六', '18日 星期日', '19日 星期一', '20日 星期二', '21日 星期三', '22日 星期四', '23日 星期五', '24日 星期六', '25日 星期日', '26日 星期一', '27日 星期二', '28日 星期三', '29日 星期四', '30日 星期五'] -const chinaDays = ['初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十'] +const calendar = require('calendar') +const _ = require('./utils') +const data = require('./data') -let componentId let component -let times = 0 - -beforeAll(async () => { - componentId = await _.load('index', 'comp') -}) - -afterEach(() => { - global.Date = RealDate - times = 0 -}) - -test.each([ - ['2016-09-01', true, [years, chinaMonths, chinaDays], [115, 8, 0]], - ['2016-09-01', false, [years, months, days], [115, 8, 0]], - ['', true, [years, chinaMonths, chinaDays], [115, 7, 0]], - ['', false, [years, months, days], [115, 8, 0]], -])('render', async (value, chinese, multiArray, multiIndex) => { - // mock date - if (value === '') { - global.Date = class extends Date { - constructor(...props) { - super() - const mock = times === 0 ? new RealDate('2016-09-01') : new RealDate(...props) // mock date once - times++ - return mock - } - } - } +let that + +calendar.toChinaMonth.mockImplementation(index => index + '') +calendar.solarDays.mockReturnValue(1) +calendar.monthDays.mockReturnValue(1) +calendar.toChinaDay.mockReturnValue('初一') +calendar.lunar2solar.mockReturnValue({ + lYear: 2019, + lMonth: 2, + lDay: 25, +}) +calendar.solar2lunar + .mockReturnValueOnce({ + cYear: 2019, + cMonth: 2, + cDay: 22, + ncWeek: '星期五', + }) + .mockReturnValueOnce({ + cYear: 2019, + cMonth: 2, + cDay: 25, + ncWeek: '星期一', + }) + .mockReturnValueOnce({ + cYear: 2019, + cMonth: 2, + cDay: 25, + ncWeek: '星期一', + }) + .mockReturnValueOnce({ + cYear: 2020, + cMonth: 2, + cDay: 25, + ncWeek: '星期二', + }) + .mockReturnValueOnce({ + cYear: 2020, + cMonth: 3, + cDay: 25, + ncWeek: '星期三', + }) + .mockReturnValueOnce({ + cYear: 2020, + cMonth: 3, + cDay: 26, + ncWeek: '星期四', + }) + .mockReturnValueOnce({ + cYear: 2019, + cMonth: 2, + cDay: 25, + ncWeek: '星期一', + }) +// value: '2019-02-22' chinese: false +test('solar calendar 2019-02-22 render', () => { + const componentId = _.load('index', 'comp') component = _.render(componentId, { - value, - chinese, + value: '2019-02-22', + chinese: false, }) const parent = document.createElement('parent-wrapper') component.attach(parent) - expect(component.data) - .toEqual({ - value, - chinese, - multiArray, - multiIndex, - }) + that = component.instance - expect(_.match(component.dom, '')) + expect(_.match(component.dom, '')) .toBe(true) + + expect(calendar.toChinaMonth) + .toHaveBeenCalledTimes(12) + expect(calendar.toChinaMonth) + .toHaveBeenLastCalledWith(12) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(1) + expect(calendar.solar2lunar) + .toHaveBeenCalledWith(2019, 2, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(1) + expect(calendar.solarDays) + .toHaveBeenCalledWith(2019, 2) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期五']]) + + expect(component.data.multiIndex) + .toEqual([118, 1, 21]) +}) + +// value: '2019-02-25' chinese: false +test('value observer', () => { + component.setData({ + value: '2019-02-25', + }) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(2) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(2, 2019, 2, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(2) + expect(calendar.solarDays) + .toHaveBeenNthCalledWith(2, 2019, 2) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期一']]) + + expect(component.data.multiIndex) + .toEqual([118, 1, 24]) +}) + +// value: '2019-02-25' chinese: true +test('chinese observer', () => { + component.setData({ + chinese: true, + }) + + expect(calendar.lunar2solar) + .toHaveBeenCalledTimes(1) + expect(calendar.lunar2solar) + .toHaveBeenCalledWith(2019, 2, 25) + + expect(calendar.monthDays) + .toHaveBeenCalledTimes(1) + expect(calendar.monthDays) + .toHaveBeenCalledWith(2019, 2) + + expect(calendar.toChinaDay) + .toHaveBeenCalledTimes(1) + expect(calendar.toChinaDay) + .toHaveBeenCalledWith(1) + + expect(component.data.multiArray) + .toEqual([data.years, data.chinaMonths, ['初一']]) + + expect(component.data.multiIndex) + .toEqual([118, 1, 24]) +}) + +// value: '2019-02-26' chinese: true +test('change event', () => { + that._bindMultiPickerChange({detail: {value: [118, 1, 25]}}) + + expect(component.data.multiIndex) + .toEqual([118, 1, 25]) +}) + +// value: '2020-02-26' chinese: true +test('columnchange event', () => { + that._bindMultiPickerColumnChange({ + detail: { + column: 0, + value: 119, + }, + }) + + expect(calendar.monthDays) + .toHaveBeenCalledTimes(2) + expect(calendar.monthDays) + .toHaveBeenNthCalledWith(2, 2020, 2) + + expect(calendar.toChinaDay) + .toHaveBeenCalledTimes(2) + expect(calendar.toChinaDay) + .toHaveBeenNthCalledWith(2, 1) + + expect(component.data.multiArray) + .toEqual([data.years, data.chinaMonths, ['初一']]) + + expect(component.data.multiIndex) + .toEqual([119, 1, 25]) +}) + +// value: '2020-03-26' chinese: true +test('columnchange event', () => { + that._bindMultiPickerColumnChange({ + detail: { + column: 1, + value: 2, + }, + }) + + expect(calendar.monthDays) + .toHaveBeenCalledTimes(3) + expect(calendar.monthDays) + .toHaveBeenNthCalledWith(3, 2020, 3) + + expect(calendar.toChinaDay) + .toHaveBeenCalledTimes(3) + expect(calendar.toChinaDay) + .toHaveBeenNthCalledWith(3, 1) + + expect(component.data.multiArray) + .toEqual([data.years, data.chinaMonths, ['初一']]) + + expect(component.data.multiIndex) + .toEqual([119, 2, 25]) +}) + +// value: '2020-03-27' chinese: true +test('columnchange event', () => { + that._bindMultiPickerColumnChange({ + detail: { + column: 2, + value: 26, + }, + }) + + expect(calendar.monthDays) + .toHaveBeenCalledTimes(4) + expect(calendar.monthDays) + .toHaveBeenNthCalledWith(4, 2020, 3) + + expect(calendar.toChinaDay) + .toHaveBeenCalledTimes(4) + expect(calendar.toChinaDay) + .toHaveBeenNthCalledWith(4, 1) + + expect(component.data.multiArray) + .toEqual([data.years, data.chinaMonths, ['初一']]) + + expect(component.data.multiIndex) + .toEqual([119, 2, 26]) +}) + +// value: '2020-02-25' chinese: false +test('columnchange event', () => { + component.setData({ + chinese: false, + }) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(3) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(3, 2019, 2, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(3) + expect(calendar.solarDays) + .toHaveBeenNthCalledWith(3, 2019, 2) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期一']]) + + expect(component.data.multiIndex) + .toEqual([118, 1, 24]) + + that._bindMultiPickerColumnChange({ + detail: { + column: 0, + value: 119, + }, + }) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(4) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(4, 2020, 2, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(4) + expect(calendar.solarDays) + .toHaveBeenNthCalledWith(4, 2020, 2) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期二']]) + + expect(component.data.multiIndex) + .toEqual([119, 1, 24]) +}) + +// value: '2020-03-25' chinese: false +test('columnchange event', () => { + that._bindMultiPickerColumnChange({ + detail: { + column: 1, + value: 2, + }, + }) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(5) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(5, 2020, 3, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(5) + expect(calendar.solarDays) + .toHaveBeenNthCalledWith(5, 2020, 3) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期三']]) + + expect(component.data.multiIndex) + .toEqual([119, 2, 24]) +}) + +// value: '2020-03-26' chinese: false +test('columnchange event', () => { + that._bindMultiPickerColumnChange({ + detail: { + column: 2, + value: 25, + }, + }) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(6) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(6, 2020, 3, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(6) + expect(calendar.solarDays) + .toHaveBeenNthCalledWith(6, 2020, 3) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期四']]) + + expect(component.data.multiIndex) + .toEqual([119, 2, 25]) +}) + +// value: '2019-02-25' chinese: false +test('cancel event', () => { + that._bindMultiPickerCancel() + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(7) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(7, 2019, 2, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(7) + expect(calendar.solarDays) + .toHaveBeenNthCalledWith(7, 2019, 2) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期一']]) + + expect(component.data.multiIndex) + .toEqual([118, 1, 24]) }) diff --git a/test/index2.test.js b/test/index2.test.js new file mode 100644 index 0000000..d3c809c --- /dev/null +++ b/test/index2.test.js @@ -0,0 +1,55 @@ +jest.mock('calendar') + +const calendar = require('calendar') +const _ = require('./utils') +const data = require('./data') + +calendar.toChinaMonth.mockImplementation(index => index + '') +calendar.monthDays.mockReturnValue(1) +calendar.toChinaDay.mockReturnValue('初一') +calendar.lunar2solar.mockReturnValue({ + lYear: 2019, + lMonth: 1, + lDay: 18, +}) + +// 农历 2019-01-18 +test('lunar calendar 2019-01-18 render', () => { + const componentId = _.load('index', 'comp') + const component = _.render(componentId, { + value: '2019-01-18', + chinese: true, + }) + + const parent = document.createElement('parent-wrapper') + component.attach(parent) + + expect(_.match(component.dom, '')) + .toBe(true) + + expect(calendar.toChinaMonth) + .toHaveBeenCalledTimes(12) + expect(calendar.toChinaMonth) + .toHaveBeenLastCalledWith(12) + + expect(calendar.lunar2solar) + .toHaveBeenCalledTimes(1) + expect(calendar.lunar2solar) + .toHaveBeenCalledWith(2019, 1, 18) + + expect(calendar.monthDays) + .toHaveBeenCalledTimes(1) + expect(calendar.monthDays) + .toHaveBeenCalledWith(2019, 1) + + expect(calendar.toChinaDay) + .toHaveBeenCalledTimes(1) + expect(calendar.toChinaDay) + .toHaveBeenCalledWith(1) + + expect(component.data.multiArray) + .toEqual([data.years, data.chinaMonths, ['初一']]) + + expect(component.data.multiIndex) + .toEqual([118, 0, 17]) +}) diff --git a/test/index3.test.js b/test/index3.test.js new file mode 100644 index 0000000..a4e77f6 --- /dev/null +++ b/test/index3.test.js @@ -0,0 +1,52 @@ +jest.mock('calendar') + +const calendar = require('calendar') +const _ = require('./utils') +const data = require('./data') + +calendar.toChinaMonth.mockImplementation(index => index + '') +calendar.solarDays.mockReturnValue(1) +calendar.solar2lunar.mockReturnValue({ + cYear: 2019, + cMonth: 2, + cDay: 25, + ncWeek: '星期一', +}) + +// 公历 2019-02-25 +test('solar calendar 2019-02-25 render', () => { + const componentId = _.load('index', 'comp') + const component = _.render(componentId, { + value: '', + chinese: false, + }) + + const parent = document.createElement('parent-wrapper') + component.attach(parent) + + expect(_.match(component.dom, '')) + .toBe(true) + + expect(calendar.toChinaMonth) + .toHaveBeenCalledTimes(12) + expect(calendar.toChinaMonth) + .toHaveBeenLastCalledWith(12) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(2) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(1) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(2, 2019, 2, 1) + + expect(calendar.solarDays) + .toHaveBeenCalledTimes(1) + expect(calendar.solarDays) + .toHaveBeenCalledWith(2019, 2) + + expect(component.data.multiArray) + .toEqual([data.years, data.months, ['1日 星期一']]) + + expect(component.data.multiIndex) + .toEqual([118, 1, 24]) +}) diff --git a/test/index4.test.js b/test/index4.test.js new file mode 100644 index 0000000..e3c0413 --- /dev/null +++ b/test/index4.test.js @@ -0,0 +1,60 @@ +jest.mock('calendar') + +const calendar = require('calendar') +const _ = require('./utils') +const data = require('./data') + +calendar.toChinaMonth.mockImplementation(index => index + '') +calendar.monthDays.mockReturnValue(1) +calendar.toChinaDay.mockReturnValue('初一') +calendar.solar2lunar.mockReturnValue({ + cYear: 2019, + cMonth: 2, + cDay: 25, + lYear: 2019, + lMonth: 1, + lDay: 21, +}) + +// 农历 2019-01-21 +test('lunar calendar 2019-01-21 render', () => { + const componentId = _.load('index', 'comp') + const component = _.render(componentId, { + value: '', + chinese: true, + }) + + const parent = document.createElement('parent-wrapper') + component.attach(parent) + + expect(_.match(component.dom, '')) + .toBe(true) + + expect(calendar.toChinaMonth) + .toHaveBeenCalledTimes(12) + expect(calendar.toChinaMonth) + .toHaveBeenLastCalledWith(12) + + expect(calendar.solar2lunar) + .toHaveBeenCalledTimes(2) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(1) + expect(calendar.solar2lunar) + .toHaveBeenNthCalledWith(2, 2019, 2, 25) + + expect(calendar.monthDays) + .toHaveBeenCalledTimes(1) + expect(calendar.monthDays) + .toHaveBeenCalledWith(2019, 1) + + expect(calendar.toChinaDay) + .toHaveBeenCalledTimes(1) + expect(calendar.toChinaDay) + .toHaveBeenCalledWith(1) + + expect(component.data.multiArray) + .toEqual([data.years, data.chinaMonths, ['初一']]) + + expect(component.data.multiIndex) + .toEqual([118, 0, 20]) +}) diff --git a/test/utils.js b/test/utils.js index 963cc71..a56c560 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,289 +1,22 @@ -module.exports = require('../tools/test/helper') +const path = require('path') +const simulate = require('miniprogram-simulate') -const noop = () => {}; +const config = require('../tools/config') -global.wx = { - request: noop, - - uploadFile: noop, - downloadFile: noop, - - connectSocket: noop, - onSocketOpen: noop, - onSocketError: noop, - sendSocketMessage: noop, - onSocketMessage: noop, - closeSocket: noop, - onSocketClose: noop, - - chooseImage: noop, - previewImage: noop, - getImageInfo: noop, - saveImageToPhotosAlbum: noop, - - startRecord: noop, - stopRecord: noop, - - getRecorderManager: noop, - - playVoice: noop, - pauseVoice: noop, - stopVoice: noop, - - getBackgroundAudioPlayerState: noop, - playBackgroundAudio: noop, - pauseBackgroundAudio: noop, - seekBackgroundAudio: noop, - stopBackgroundAudio: noop, - onBackgroundAudioPlay: noop, - onBackgroundAudioPause: noop, - onBackgroundAudioStop: noop, - - getBackgroundAudioManager: noop, - - createAudioContext: noop, - createInnerAudioContext: noop, - getAvailableAudioSources: noop, - - chooseVideo: noop, - saveVideoToPhotosAlbum: noop, - - createVideoContext: noop, - - createCameraContext: noop, - - createLivePlayerContext: noop, - createLivePusherContext: noop, - - loadFontFace: noop, - - saveFile: noop, - getFileInfo: noop, - getSavedFileList: noop, - getSavedFileInfo: noop, - removeSavedFile: noop, - openDocument: noop, - - setStorage: noop, - setStorageSync: noop, - getStorage: noop, - getStorageSync: noop, - getStorageInfo: noop, - getStorageInfoSync: noop, - removeStorage: noop, - removeStorageSync: noop, - clearStorage: noop, - clearStorageSync: noop, - - getLocation: noop, - chooseLocation: noop, - - openLocation: noop, - - createMapContext: noop, - - getSystemInfo(options = {}) { - const res = { - errMsg: 'getSystemInfo:ok', - SDKVersion: '2.3.0', - batteryLevel: 100, - benchmarkLevel: 1, - brand: 'devtools', - fontSizeSetting: 16, - language: 'zh_CN', - model: 'iPhone 7 Plus', - pixelRatio: 3, - platform: 'devtools', - screenHeight: 736, - screenWidth: 414, - statusBarHeight: 20, - system: 'iOS 10.0.1', - version: '6.6.3', - windowHeight: 672, - windowWidth: 414, - } - typeof options.success === 'function' && options.success(res) - typeof options.complete === 'function' && options.complete(res) - }, - getSystemInfoSync() { - let info = {} - wx.getSystemInfo({ - success(res) { - info = res - } - }) - - delete info.errMsg - return info - }, - canIUse: noop, - - onMemoryWarning: noop, - - getNetworkType: noop, - onNetworkStatusChange: noop, - - onAccelerometerChange: noop, - startAccelerometer: noop, - stopAccelerometer: noop, - - onCompassChange: noop, - startCompass: noop, - stopCompass: noop, - - makePhoneCall: noop, - - scanCode: noop, - - setClipboardData: noop, - getClipboardData: noop, - - openBluetoothAdapter: noop, - closeBluetoothAdapter: noop, - getBluetoothAdapterState: noop, - onBluetoothAdapterStateChange: noop, - startBluetoothDevicesDiscovery: noop, - stopBluetoothDevicesDiscovery: noop, - getBluetoothDevices: noop, - getConnectedBluetoothDevices: noop, - onBluetoothDeviceFound: noop, - createBLEConnection: noop, - closeBLEConnection: noop, - getBLEDeviceServices: noop, - getBLEDeviceCharacteristics: noop, - readBLECharacteristicValue: noop, - writeBLECharacteristicValue: noop, - notifyBLECharacteristicValueChange: noop, - onBLEConnectionStateChange: noop, - onBLECharacteristicValueChange: noop, - - startBeaconDiscovery: noop, - stopBeaconDiscovery: noop, - getBeacons: noop, - onBeaconUpdate: noop, - onBeaconServiceChange: noop, - - setScreenBrightness: noop, - getScreenBrightness: noop, - setKeepScreenOn: noop, - - onUserCaptureScreen: noop, - - vibrateLong: noop, - vibrateShort: noop, - - addPhoneContact: noop, - - getHCEState: noop, - startHCE: noop, - stopHCE: noop, - onHCEMessage: noop, - sendHCEMessage: noop, - - startWifi: noop, - stopWifi: noop, - connectWifi: noop, - getWifiList: noop, - onGetWifiList: noop, - setWifiList: noop, - onWifiConnected: noop, - getConnectedWifi: noop, - - showToast: noop, - showLoading: noop, - hideToast: noop, - hideLoading: noop, - showModal: noop, - showActionSheet: noop, - - setNavigationBarTitle: noop, - showNavigationBarLoading: noop, - hideNavigationBarLoading: noop, - setNavigationBarColor: noop, - - setTabBarBadge: noop, - removeTabBarBadge: noop, - showTabBarRedDot: noop, - hideTabBarRedDot: noop, - setTabBarStyle: noop, - setTabBarItem: noop, - showTabBar: noop, - hideTabBar: noop, - - setBackgroundColor: noop, - setBackgroundTextStyle: noop, - - setTopBarText: noop, - - navigateTo: noop, - redirectTo: noop, - switchTab: noop, - navigateBack: noop, - reLaunch: noop, - - createAnimation: noop, - - pageScrollTo: noop, - - createCanvasContext: noop, - createContext: noop, - drawCanvas: noop, - canvasToTempFilePath: noop, - canvasGetImageData: noop, - canvasPutImageData: noop, - - startPullDownRefresh: noop, - stopPullDownRefresh: noop, - - createSelectorQuery: noop, - - createIntersectionObserver: noop, - - getExtConfig: noop, - getExtConfigSync: noop, - - login: noop, - checkSession: noop, - - authorize: noop, - - getUserInfo: noop, - - requestPayment: noop, - - showShareMenu: noop, - hideShareMenu: noop, - updateShareMenu: noop, - getShareInfo: noop, - - chooseAddress: noop, - - addCard: noop, - openCard: noop, - - openSetting: noop, - getSetting: noop, - - getWeRunData: noop, - - getAccountInfoSync: noop, - - navigateToMiniProgram: noop, - navigateBackMiniProgram: noop, - - chooseInvoiceTitle: noop, - - checkIsSupportSoterAuthentication: noop, - startSoterAuthentication: noop, - checkIsSoterEnrolledInDevice: noop, - - getUpdateManager: noop, +const srcPath = config.srcPath +const oldLoad = simulate.load +simulate.load = function (componentPath, ...args) { + componentPath = path.join(srcPath, componentPath) + return oldLoad(componentPath, ...args) +} - createWorker: noop, +module.exports = simulate - getLogManager: noop, +// adjust the simulated wx api +const oldGetSystemInfoSync = global.wx.getSystemInfoSync +global.wx.getSystemInfoSync = function() { + const res = oldGetSystemInfoSync() + res.SDKVersion = '2.4.1' - reportMonitor: noop, - - setEnableDebug: noop, + return res } diff --git a/test/wx.test.js b/test/wx.test.js new file mode 100644 index 0000000..0209e56 --- /dev/null +++ b/test/wx.test.js @@ -0,0 +1,18 @@ +const _ = require('./utils') + +test('wx.getSystemInfo', async () => { + wx.getSystemInfo({ + success(res) { + expect(res.errMsg).toBe('getSystemInfo:ok') + }, + complete(res) { + expect(res.errMsg).toBe('getSystemInfo:ok') + }, + }) +}) + +test('wx.getSystemInfoSync', async () => { + const info = wx.getSystemInfoSync() + expect(info.SDKVersion).toBe('2.4.1') + expect(info.version).toBe('6.6.3') +}) diff --git a/tools/build.js b/tools/build.js index 6a6634c..32733a5 100644 --- a/tools/build.js +++ b/tools/build.js @@ -11,6 +11,7 @@ const gulpInstall = require('gulp-install') const config = require('./config') const checkComponents = require('./checkcomponents') +const checkWxss = require('./checkwxss') const _ = require('./utils') const wxssConfig = config.wxss || {} @@ -18,14 +19,16 @@ const srcPath = config.srcPath const distPath = config.distPath /** - * get wxss stream + * 获取 wxss 流 */ function wxss(wxssFileList) { if (!wxssFileList.length) return false return gulp.src(wxssFileList, {cwd: srcPath, base: srcPath}) + .pipe(checkWxss.start()) // 开始处理 import .pipe(gulpif(wxssConfig.less && wxssConfig.sourcemap, sourcemaps.init())) .pipe(gulpif(wxssConfig.less, less({paths: [srcPath]}))) + .pipe(checkWxss.end()) // 结束处理 import .pipe(rename({extname: '.wxss'})) .pipe(gulpif(wxssConfig.less && wxssConfig.sourcemap, sourcemaps.write('./'))) .pipe(_.logger(wxssConfig.less ? 'generate' : undefined)) @@ -33,7 +36,7 @@ function wxss(wxssFileList) { } /** - * get js stream + * 获取 js 流 */ function js(jsFileMap, scope) { const webpackConfig = config.webpack @@ -75,7 +78,7 @@ function js(jsFileMap, scope) { } /** - * copy file + * 拷贝文件 */ function copy(copyFileList) { if (!copyFileList.length) return false @@ -86,7 +89,7 @@ function copy(copyFileList) { } /** - * install packages + * 安装依赖包 */ function install() { return gulp.series(async () => { @@ -122,12 +125,12 @@ class BuildTask { const id = this.id /** - * clean the dist folder + * 清空目标目录 */ gulp.task(`${id}-clean-dist`, () => gulp.src(distPath, {read: false, allowEmpty: true}).pipe(clean())) /** - * copy demo to the dev folder + * 拷贝 demo 到目标目录 */ let isDemoExists = false gulp.task(`${id}-demo`, gulp.series(async () => { @@ -147,12 +150,12 @@ class BuildTask { })) /** - * install packages for dev + * 安装依赖包 */ gulp.task(`${id}-install`, install()) /** - * check custom components + * 检查自定义组件 */ gulp.task(`${id}-component-check`, async () => { const entries = this.entries @@ -171,7 +174,7 @@ class BuildTask { }) /** - * write json to the dist folder + * 写 json 文件到目标目录 */ gulp.task(`${id}-component-json`, done => { const jsonFileList = this.componentListMap.jsonFileList @@ -184,7 +187,7 @@ class BuildTask { }) /** - * copy wxml to the dist folder + * 拷贝 wxml 文件到目标目录 */ gulp.task(`${id}-component-wxml`, done => { const wxmlFileList = this.componentListMap.wxmlFileList @@ -199,7 +202,7 @@ class BuildTask { }) /** - * generate wxss to the dist folder + * 生成 wxss 文件到目标目录 */ gulp.task(`${id}-component-wxss`, done => { const wxssFileList = this.componentListMap.wxssFileList @@ -214,7 +217,7 @@ class BuildTask { }) /** - * generate js to the dist folder + * 生成 js 文件到目标目录 */ gulp.task(`${id}-component-js`, done => { const jsFileList = this.componentListMap.jsFileList @@ -229,7 +232,7 @@ class BuildTask { }) /** - * copy resources to dist folder + * 拷贝相关资源到目标目录 */ gulp.task(`${id}-copy`, gulp.parallel(done => { const copyList = this.copyList @@ -248,12 +251,12 @@ class BuildTask { })) /** - * watch json + * 监听 json 变化 */ gulp.task(`${id}-watch-json`, () => gulp.watch(this.componentListMap.jsonFileList, {cwd: srcPath, base: srcPath}, gulp.series(`${id}-component-check`, gulp.parallel(`${id}-component-wxml`, `${id}-component-wxss`, `${id}-component-js`, `${id}-component-json`)))) /** - * watch wxml + * 监听 wxml 变化 */ gulp.task(`${id}-watch-wxml`, () => { this.cachedComponentListMap.wxmlFileList = null @@ -261,7 +264,7 @@ class BuildTask { }) /** - * watch wxss + * 监听 wxss 变化 */ gulp.task(`${id}-watch-wxss`, () => { this.cachedComponentListMap.wxssFileList = null @@ -269,7 +272,7 @@ class BuildTask { }) /** - * watch resources + * 监听相关资源变化 */ gulp.task(`${id}-watch-copy`, () => { const copyList = this.copyList @@ -283,7 +286,7 @@ class BuildTask { }) /** - * watch demo + * 监听 demo 变化 */ gulp.task(`${id}-watch-demo`, () => { const demoSrc = config.demoSrc @@ -298,12 +301,12 @@ class BuildTask { }) /** - * watch installed packages + * 监听安装包列表变化 */ gulp.task(`${id}-watch-install`, () => gulp.watch(path.resolve(__dirname, '../package.json'), install())) /** - * build custom component + * 构建相关任务 */ gulp.task(`${id}-build`, gulp.series(`${id}-clean-dist`, `${id}-component-check`, gulp.parallel(`${id}-component-wxml`, `${id}-component-wxss`, `${id}-component-js`, `${id}-component-json`, `${id}-copy`))) diff --git a/tools/checkcomponents.js b/tools/checkcomponents.js index 53f3766..0f06a3f 100644 --- a/tools/checkcomponents.js +++ b/tools/checkcomponents.js @@ -6,7 +6,7 @@ const config = require('./config') const srcPath = config.srcPath /** - * get json path's info + * 获取 json 路径相关信息 */ function getJsonPathInfo(jsonPath) { const dirPath = path.dirname(jsonPath) @@ -20,7 +20,7 @@ function getJsonPathInfo(jsonPath) { } /** - * check included components + * 检测是否包含其他自定义组件 */ const checkProps = ['usingComponents', 'componentGenerics'] async function checkIncludedComponents(jsonPath, componentListMap) { @@ -41,7 +41,7 @@ async function checkIncludedComponents(jsonPath, componentListMap) { value = _.transformPath(value, path.sep) - // check relative path + // 检查相对路径 const componentPath = `${path.join(dirPath, value)}.json` // eslint-disable-next-line no-await-in-loop const isExists = await _.checkFileExists(componentPath) @@ -52,7 +52,7 @@ async function checkIncludedComponents(jsonPath, componentListMap) { } } - // checked + // 进入存储 componentListMap.wxmlFileList.push(`${fileBase}.wxml`) componentListMap.wxssFileList.push(`${fileBase}.wxss`) componentListMap.jsonFileList.push(`${fileBase}.json`) @@ -68,7 +68,7 @@ module.exports = async function (entry) { jsonFileList: [], jsFileList: [], - jsFileMap: {}, // for webpack entry + jsFileMap: {}, // 为 webpack entry 所用 } const isExists = await _.checkFileExists(entry) diff --git a/tools/checkwxss.js b/tools/checkwxss.js new file mode 100644 index 0000000..a9a7ff6 --- /dev/null +++ b/tools/checkwxss.js @@ -0,0 +1,100 @@ +const path = require('path') +const through = require('through2') +const Vinyl = require('vinyl') + +const _ = require('./utils') + +/** + * 获取 import 列表 + */ +function getImportList(wxss, filePath) { + const reg = /@import\s+(?:(?:"([^"]+)")|(?:'([^"]+)'));/ig + const importList = [] + let execRes = reg.exec(wxss) + + while (execRes && (execRes[1] || execRes[2])) { + importList.push({ + code: execRes[0], + path: path.join(path.dirname(filePath), execRes[1] || execRes[2]), + }) + execRes = reg.exec(wxss) + } + + return importList +} + +/** + * 获取 wxss 内容 + */ +async function getContent(wxss, filePath, cwd) { + let importList = [] + + if (wxss) { + const currentImportList = getImportList(wxss, filePath) + + for (const item of currentImportList) { + // 替换掉 import 语句,不让 less 编译 + wxss = wxss.replace(item.code, `/* *updated for miniprogram-custom-component* ${item.code} */`) + + // 处理依赖的 wxss + const importWxss = await _.readFile(item.path) + const importInfo = await getContent(importWxss, item.path, cwd) + + // 获取依赖列表 + importList.push(new Vinyl({ + cwd, + path: item.path, + contents: Buffer.from(importInfo.wxss, 'utf8'), + })) + importList = importList.concat(importInfo.importList) + } + } + + return { + wxss, + importList, + } +} + +module.exports = { + start() { + return through.obj(function (file, enc, cb) { + if (file.isBuffer()) { + getContent(file.contents.toString('utf8'), file.path, file.cwd).then(res => { + const { wxss, importList } = res + + importList.forEach(importFile => this.push(importFile)) + + file.contents = Buffer.from(wxss, 'utf8') + this.push(file) + cb() + }).catch(err => { + // eslint-disable-next-line no-console + + console.warn(`deal with ${file.path} failed: ${err.stack}`) + this.push(file) + cb() + }) + } else { + this.push(file) + cb() + } + }) + }, + + end() { + return through.obj(function (file, enc, cb) { + if (file.isBuffer) { + const reg = /\/\*\s\*updated for miniprogram-custom-component\*\s(@import\s+(?:(?:"([^"]+)")|(?:'([^"]+)'));)\s\*\//ig + const wxss = file.contents.toString('utf8').replace(reg, (all, $1) => $1) + + file.contents = Buffer.from(wxss, 'utf8') + this.push(file) + cb() + } else { + this.push(file) + cb() + } + }) + }, +} diff --git a/tools/config.js b/tools/config.js index da089f2..00a62f7 100644 --- a/tools/config.js +++ b/tools/config.js @@ -16,15 +16,15 @@ module.exports = { isDev, isWatch, - srcPath: src, - distPath: isDev ? dev : dist, + srcPath: src, // 源目录 + distPath: isDev ? dev : dist, // 目标目录 - demoSrc, - demoDist, + demoSrc, // demo 源目录 + demoDist, // demo 目标目录 wxss: { - less: false, // compile wxss with less - sourcemap: false, // source map for less + less: false, // 使用 less 来编写 wxss + sourcemap: false, // 生成 less sourcemap }, webpack: { @@ -34,7 +34,7 @@ module.exports = { libraryTarget: 'commonjs2', }, target: 'node', - externals: [nodeExternals()], // ignore node_modules + externals: [nodeExternals()], // 忽略 node_modules module: { rules: [{ test: /\.js$/i, @@ -56,12 +56,12 @@ module.exports = { optimization: { minimize: false, }, - // devtool: 'nosources-source-map', // source map for js + // devtool: 'nosources-source-map', // 生成 js sourcemap performance: { hints: 'warning', assetFilter: assetFilename => assetFilename.endsWith('.js') } }, - copy: ['./wxml', './wxss', './wxs', './images'], // will copy to dist + copy: ['./images'], // 将会复制到目标目录 } diff --git a/tools/demo/pages/index/index.wxml b/tools/demo/pages/index/index.wxml index 67719e1..a096254 100644 --- a/tools/demo/pages/index/index.wxml +++ b/tools/demo/pages/index/index.wxml @@ -8,8 +8,8 @@ - - + + diff --git a/tools/test/helper.js b/tools/test/helper.js deleted file mode 100644 index 6bc4a0d..0000000 --- a/tools/test/helper.js +++ /dev/null @@ -1,163 +0,0 @@ -const path = require('path') - -const jComponent = require('j-component') - -const config = require('../config') -const _ = require('../utils') - -const srcPath = config.srcPath -const componentMap = {} -let nowLoad = null - -/** - * register custom component - */ -global.Component = options => { - const component = nowLoad - const definition = Object.assign({ - template: component.wxml, - usingComponents: component.json.usingComponents, - tagName: component.tagName, - }, options) - - component.id = jComponent.register(definition) -} - -/** - * register behavior - */ -global.Behavior = options => jComponent.behavior(options) - -/** - * register global components - */ -// eslint-disable-next-line semi-style -;[ - 'view', 'scroll-view', 'swiper', 'movable-view', 'cover-view', 'cover-view', - 'icon', 'text', 'rich-text', 'progress', - 'button', 'checkbox', 'form', 'input', 'label', 'picker', 'picker', 'picker-view', 'radio', 'slider', 'switch', 'textarea', - 'navigator', 'function-page-navigator', - 'audio', 'image', 'video', 'camera', 'live-player', 'live-pusher', - 'map', - 'canvas', - 'open-data', 'web-view', 'ad' -].forEach(name => { - jComponent.register({ - id: name, - tagName: `wx-${name}`, - template: '' - }) -}) - -/** - * Touch polyfill - */ -class Touch { - constructor(options = {}) { - this.clientX = 0 - this.clientY = 0 - this.identifier = 0 - this.pageX = 0 - this.pageY = 0 - this.screenX = 0 - this.screenY = 0 - this.target = null - - Object.keys(options).forEach(key => { - this[key] = options[key] - }) - } -} -global.Touch = window.Touch = Touch - -/** - * load component - */ -async function load(componentPath, tagName) { - if (typeof componentPath === 'object') { - const definition = componentPath - - return jComponent.register(definition) - } - - const wholePath = path.join(srcPath, componentPath) - - const oldLoad = nowLoad - const component = nowLoad = {} - - component.tagName = tagName - component.wxml = await _.readFile(`${wholePath}.wxml`) - component.wxss = await _.readFile(`${wholePath}.wxss`) - component.json = _.readJson(`${wholePath}.json`) - - if (!component.json) { - throw new Error(`invalid component: ${wholePath}`) - } - - // preload using components - const usingComponents = component.json.usingComponents || {} - const usingComponentKeys = Object.keys(usingComponents) - for (let i = 0, len = usingComponentKeys.length; i < len; i++) { - const key = usingComponentKeys[i] - const usingPath = path.join(path.dirname(componentPath), usingComponents[key]) - // eslint-disable-next-line no-await-in-loop - const id = await load(usingPath) - - usingComponents[key] = id - } - - // require js - // eslint-disable-next-line import/no-dynamic-require - require(wholePath) - - nowLoad = oldLoad - componentMap[wholePath] = component - - return component.id -} - -/** - * render component - */ -function render(componentId, properties) { - if (!componentId) throw new Error('you need to pass the componentId') - - return jComponent.create(componentId, properties) -} - -/** - * test a dom is similar to the html - */ -function match(dom, html) { - if (!(dom instanceof window.Element) || !html || typeof html !== 'string') return false - - // remove some - html = html.trim() - .replace(/(>)[\n\r\s\t]+(<)/g, '$1$2') - - const a = dom.cloneNode() - const b = dom.cloneNode() - - a.innerHTML = dom.innerHTML - b.innerHTML = html - - return a.isEqualNode(b) -} - -/** - * wait for some time - */ -function sleep(time = 0) { - return new Promise(resolve => { - setTimeout(() => { - resolve() - }, time) - }) -} - -module.exports = { - load, - render, - match, - sleep, -} diff --git a/tools/utils.js b/tools/utils.js index 360a461..42797e8 100644 --- a/tools/utils.js +++ b/tools/utils.js @@ -6,7 +6,7 @@ const colors = require('colors') const through = require('through2') /** - * async function wrapper + * 异步函数封装 */ function wrap(func, scope) { return function (...args) { @@ -36,14 +36,14 @@ const readFileSync = wrap(fs.readFile) const writeFileSync = wrap(fs.writeFile) /** - * transform path segment separator + * 调整路径分隔符 */ function transformPath(filePath, sep = '/') { return filePath.replace(/[\\/]/g, sep) } /** - * check file exists + * 检查文件是否存在 */ async function checkFileExists(filePath) { try { @@ -55,14 +55,14 @@ async function checkFileExists(filePath) { } /** - * create folder + * 递归创建目录 */ async function recursiveMkdir(dirPath) { const prevDirPath = path.dirname(dirPath) try { await accessSync(prevDirPath) } catch (err) { - // prevDirPath is not exist + // 上一级目录不存在 await recursiveMkdir(prevDirPath) } @@ -71,18 +71,18 @@ async function recursiveMkdir(dirPath) { const stat = await statSync(dirPath) if (stat && !stat.isDirectory()) { - // dirPath already exists but is not a directory - await renameSync(dirPath, `${dirPath}.bak`) // rename to a file with the suffix ending in '.bak' + // 目标路径存在,但不是目录 + await renameSync(dirPath, `${dirPath}.bak`) // 将此文件重命名为 .bak 后缀 await mkdirSync(dirPath) } } catch (err) { - // dirPath is not exist + // 目标路径不存在 await mkdirSync(dirPath) } } /** - * read json + * 读取 json */ function readJson(filePath) { try { @@ -96,7 +96,7 @@ function readJson(filePath) { } /** - * read file + * 读取文件 */ async function readFile(filePath) { try { @@ -108,7 +108,7 @@ async function readFile(filePath) { } /** - * write file + * 写文件 */ async function writeFile(filePath, data) { try { @@ -121,7 +121,7 @@ async function writeFile(filePath, data) { } /** - * time format + * 时间格式化 */ function format(time, reg) { const date = typeof time === 'string' ? new Date(time) : time @@ -143,7 +143,7 @@ function format(time, reg) { } /** - * logger plugin + * 日志插件 */ function logger(action = 'copy') { return through.obj(function (file, enc, cb) { @@ -158,7 +158,7 @@ function logger(action = 'copy') { } /** - * compare arrays + * 比较数组是否相等 */ function compareArray(arr1, arr2) { if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false @@ -172,7 +172,7 @@ function compareArray(arr1, arr2) { } /** - * merge two object + * 合并两个对象 */ function merge(obj1, obj2) { Object.keys(obj2).forEach(key => { @@ -189,7 +189,7 @@ function merge(obj1, obj2) { } /** - * get random id + * 获取 id */ let seed = +new Date() function getId() {