Skip to content

Commit

Permalink
feat(directive): 开启wxa指令功能,新增wxa:mock指令
Browse files Browse the repository at this point in the history
  • Loading branch information
szyuan authored and Genuifx committed Mar 5, 2020
1 parent 05cc3f5 commit 2a5062a
Show file tree
Hide file tree
Showing 9 changed files with 8,968 additions and 9,496 deletions.
18,146 changes: 8,712 additions & 9,434 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@
"publishConfig": {
"access": "public"
}
}
}
1 change: 1 addition & 0 deletions packages/wxa-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"inquirer": "^6.2.0",
"js-base64": "^2.4.0",
"mkdirp": "^0.5.1",
"mockjs": "^1.1.0",
"node-notifier": "^5.2.1",
"promise.prototype.finally": "^3.1.0",
"shelljs": "^0.8.3",
Expand Down
18 changes: 18 additions & 0 deletions packages/wxa-cli/src/resolvers/directive/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import mock from './mock/index';
// import anotherDirective from './anotherDirective';
// ...

export default directive;

const directiveHandlerList = {
mock
// anotherDirective
// ...
}

function directive(drc, element, mdl){
let drcName = drc.name;
if(drcName && directiveHandlerList[drcName]) {
directiveHandlerList[drcName](drc, element, mdl);
}
}
71 changes: 71 additions & 0 deletions packages/wxa-cli/src/resolvers/directive/mock/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
# wxa:mock
为input自动填入响应字符,避免开发时重复花时间手动输入
*仅开发时启用(NODE_ENV为空或==='development')*
指令格式1:`wxa:mock="占位符"` 或 `wxa:mock="占位符(参数[,参数])"`
*/

import Mock from 'mockjs';
import wxaMockExtends from './mock-extends';
import wxaMock from './wxa-mock';

const Random = Mock.Random;
Random.extend(wxaMockExtends(Random));

export default mock;

function mock(drc, element, mdl){
// drc: {name, value}
if(isDev()) {
let targetList = findMockTarget(element);
targetList.forEach(target => {
let mockResult = getMockResult(drc);
target.attribs.value = mockResult;
setWarningStyle(target);
})
}
}

function getMockResult(drc) {
let mockResult = '';
let drcValuePrefix = drc.value[0];

if(drcValuePrefix === '$') {
// wxa提供
mockResult = wxaMock.mock(drc.value);
}else {
// mock.js
mockResult = Mock.mock(drc.value);
}

return mockResult;
}

function findMockTarget(el) {
let targetList = [];
let tagName = el.name;
if(tagName === 'input') {
targetList.push(el);
}else {
if(el.children && el.children.length) {
el.children.forEach(child => {
targetList = targetList.concat(findMockTarget(child));
})
}
}
return targetList;
}



// 设置警示样式,避免mock信息上生产环境
function setWarningStyle(el){
let originStyle = el.attribs.style || '';
el.attribs.style = originStyle + '; outline: 1px dashed rgba(255,0,0,0.2); text-shadow: #FC0 1px 0 2px !important;'
}
// 判断开发环境,避免mock信息上生产环境
function isDev() {
let env = process.env.NODE_ENV;
let isDevEnv = Boolean(~[undefined, 'development'].indexOf(env));
return isDevEnv;
}
51 changes: 51 additions & 0 deletions packages/wxa-cli/src/resolvers/directive/mock/mock-extends.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// wxa自定义拓展的mock规则

export default function extend(random) {
return {
// 身份证号
idNo,
// 星座
constellation
}
}

function idNo(oldest, youngest) {
return getIDCardNo(this, oldest, youngest);
}

function constellation(rule) {
let constellations = ['白羊座', '金牛座', '双子座', '巨蟹座', '狮子座', '处女座', '天秤座', '天蝎座', '射手座', '摩羯座', '水瓶座', '双鱼座']
return this.pick(constellations)
}


// 生成身份证号
function getIDCardNo(mock, oldest, youngest) {
let coefficientArray = [ "7","9","10","5","8","4","2","1","6","3","7","9","10","5","8","4","2"];// 加权因子
let lastNumberArray = [ "1","0","X","9","8","7","6","5","4","3","2"];// 校验码
let address = "420101"; // 住址
let oldestYear = oldest ? oldest : 1900;
let youngestYear = youngest ? youngest : 2019;
// let year = getRandom(youngestYear, oldestYear);
let year = mock.natural(youngestYear, oldestYear);
let month = paddingZero(mock.natural(1, 12));
let date = paddingZero(mock.natural(1, 28));
let birthday = `${year}${month}${date}`; // 生日

let s = Math.floor(Math.random()*10).toString() + Math.floor(Math.random()*10).toString() + Math.floor(Math.random()*10).toString();
let array = (address + birthday + s).split("");
let total = 0;
for(let i in array){
total = total + parseInt(array[i])*parseInt(coefficientArray[i]);
}
let lastNumber = lastNumberArray[parseInt(total%11)];
let id_no_String = address + birthday + s + lastNumber;
return id_no_String;
}


function paddingZero(num) {
let number = num + '';
let res = (Number(num) > 9) ? number : 0 + number;
return res;
}
12 changes: 12 additions & 0 deletions packages/wxa-cli/src/resolvers/directive/mock/wxa-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// wxa自定义的mock规则

export default {
mock
}

function mock(rule) {
let ruleValue = rule.substr(1);
// TODO
return '';
}

161 changes: 100 additions & 61 deletions packages/wxa-cli/src/resolvers/xml/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import CSSManager from '../css/index';
import debugPKG from 'debug';
import {logger, error} from '../../helpers/logger';
import domSerializer from 'dom-serializer';
import directive from '../directive';

let debug = debugPKG('WXA:XMLManager');
let debugXMLStyle = debugPKG('WXA:XMLManager-style');
// const SOURCE_ATTR = ['src', 'href'];
// const STYLE_
const WXA_DIRECTIVE_PREFIX = 'wxa';
const WECHAT_DIRECTIVE_PREFIX = 'wx';

class XMLManager {
constructor(resolve, meta) {
Expand All @@ -23,97 +26,133 @@ class XMLManager {

let libs = [];

mdl.xml.forEach((element) => {
libs = libs.concat(this.walkXML(element, mdl));
// mdl.xml.forEach((element) => {
// libs = libs.concat(this.walkXML(element, mdl));
// });

// Node <-- Element
// Node <-- Attr
// Node <-- CharacterData <-- Text
mdl.xml.forEach(node => {
libs = libs.concat(this.walkXML(node, mdl));
});

mdl.code = new Coder().decodeTemplate(domSerializer(mdl.xml, {xmlMode: true}));

return libs;
}

walkXML(xml, mdl) {
walkXML(node, mdl) {
let libs = [];
// ignore comment
if (xml.type === 'comment') return libs;
if (node.type === 'comment') return libs;

if (xml.type === 'tag') {
libs = libs.concat(this.walkAttr(xml.attribs, mdl));
if (node.type === 'tag') {
// 此处的node即element
libs = libs.concat(this.walkAttr(node.attribs, node, mdl));
}

if (xml.children) {
libs = libs.concat(Array.prototype.slice.call(xml.children).reduce((ret, child)=>{
if (node.children) {
libs = libs.concat(Array.prototype.slice.call(node.children).reduce((ret, child)=>{
return ret.concat(this.walkXML(child, mdl));
}, []));
}

return libs;
}

walkAttr(attributes, mdl) {
walkAttr(attributes, element, mdl) {
let libs = [];
debug('attributes walk %o', attributes);
for (let name in attributes) {
if (!attributes.hasOwnProperty(name)) continue;
// debug('attributes walk %o', attributes);
for (let attrFullName in attributes) {
if (!attributes.hasOwnProperty(attrFullName)) continue;

let attrFullNameTmp = (~attrFullName.indexOf(':')) ? attrFullName : ':'+attrFullName;
let attrPrefixNameSplit = attrFullNameTmp.split(':');
let prefix = attrPrefixNameSplit[0] || null;
let name = attrPrefixNameSplit[1] || '';

// let attr = attributes[name];
// TODO optimize
let attr = {
nodeName: name,
nodeValue: attributes[name],
prefix,
name,
value: attributes[attrFullName],
};

// debug('attribute %O', attr);
switch (attr.nodeName) {
case 'src':
case 'href': {
try {
let dr = new DependencyResolver(this.resolve, this.meta);

let {lib, source, pret} = dr.resolveDep(attr.nodeValue, mdl);
let libOutputPath = dr.getOutputPath(source, pret, mdl);
let resolved = dr.getResolved(lib, libOutputPath, mdl);

libs.push({
src: source,
pret: pret,
meta: {source, outputPath: libOutputPath},
reference: {
$$AttrNode: attr,
$$category: 'xml',
resolved,
},
});

attr.nodeValue = resolved;
} catch (e) {
error('Resolve Error', {name: mdl.src, error: e, code: attr.nodeValue});
if(!attr.prefix) {
// 无前缀普通属性
switch (attr.name) {
case 'src':
case 'href': {
try {
let dr = new DependencyResolver(this.resolve, this.meta);

let {lib, source, pret} = dr.resolveDep(attr.value, mdl);
let libOutputPath = dr.getOutputPath(source, pret, mdl);
let resolved = dr.getResolved(lib, libOutputPath, mdl);

libs.push({
src: source,
pret: pret,
meta: {source, outputPath: libOutputPath},
reference: {
$$AttrNode: attr,
$$category: 'xml',
resolved,
},
});

attr.value = resolved;
} catch (e) {
error('Resolve Error', {name: mdl.src, error: e, code: attr.value});
}

break;
}

break;
}

case 'style': {
debugXMLStyle(attr.nodeName, attr.nodeType, attr.nodeValue, typeof attr.nodeValue);
if (!attr.nodeValue) break;
try {
let CM = new CSSManager(this.resolve, this.meta);
let {libs: subLibs, code} = CM.resolveStyle(attr.nodeValue, mdl);

// add parentNode to it.
subLibs = subLibs.map((lib)=>(lib.$$AttrNode=attr, lib));
// normalize dependencies.
libs = libs.concat(subLibs);

attr.nodeValue = code;
} catch (e) {
error('Resolve Error', {name: mdl.src, error: e, code: attr.nodeValue});
case 'style': {
debugXMLStyle(attr.name, attr.nodeType, attr.value, typeof attr.value);
if (!attr.value) break;
try {
let CM = new CSSManager(this.resolve, this.meta);
let {libs: subLibs, code} = CM.resolveStyle(attr.value, mdl);

// add parentNode to it.
subLibs = subLibs.map((lib)=>(lib.$$AttrNode=attr, lib));
// normalize dependencies.
libs = libs.concat(subLibs);

attr.value = code;
} catch (e) {
error('Resolve Error', {name: mdl.src, error: e, code: attr.value});
}

break;
}

break;
default: {
// 其他属性不处理
}
}
}else {
// 带前缀的属性处理
switch(attr.prefix) {
// wxa指令
case WXA_DIRECTIVE_PREFIX: {
let drc = {
name: attr.name,
value: attr.value
}
directive(drc, element, mdl);
}

// 微信小程序指令
case WECHAT_DIRECTIVE_PREFIX: {

default: {
}

default: {
// 其他前缀属性不处理
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/wxa-cli/src/wxa.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ commander
.option('--no-progress', '不展示文件进度')
.option('--verbose', '展示多余的信息')
.option('-t, --target', '编译目标平台,如微信小程序wechat, 头条小程序tt')
.option('-d-mock', '开启mock指令')
// .option('--max-watch-project <max>', '三方开发模式,最多同时监听几个项目, default: 3')
.action(async (cmd)=>{
showSlogan();
console.info(`🤖 Building with ${chalk.keyword('orange')(process.env.NODE_ENV || 'development')} env` );
Expand Down

0 comments on commit 2a5062a

Please sign in to comment.