john's tech blog

hope is coming


  • 首页

  • 标签

  • 归档

hexo-cli源码分析之context.js

发表于 2016-08-28 | 更新于 2019-05-07

hexo-cli 1.0.2源码解读

hexo入口函数中的Context

hexo.js中定义了context.js,用来实例化hexo对象。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function Context(base, args) {
base = base || process.cwd();
args = args || {};

EventEmitter.call(this);//用到了nodejs的EventEmitter

this.base_dir = base;
this.log = logger(args);

this.extend = {
console: new ConsoleExtend()
};
}

require('util').inherits(Context, EventEmitter);

Context.prototype.init = function() {
// Do nothing
};

Context.prototype.call = function(name, args, callback) {
if (!callback && typeof args === 'function') {//如果没有callback且args为函数
callback = args;
args = {};
}

var self = this;

//用了bluebird的Promise
return new Promise(function(resolve, reject) {
var c = self.extend.console.get(name);

if (c) {
c.call(self, args).then(resolve, reject);
} else {
reject(new Error('Console `' + name + '` has not been registered yet!'));
}
}).asCallback(callback);
};

Context.prototype.exit = function(err) {
if (err) {
this.log.fatal(
{err: err},
'Something\'s wrong. Maybe you can find the solution here: %s',
chalk.underline('http://hexo.io/docs/troubleshooting.html')
);
}
};

Context.prototype.unwatch = function() {
// Do nothing
};

module.exports = Context;

hexo-cli源码分析之入口文件hexo.js

发表于 2016-08-28 | 更新于 2019-05-07

hexo-cli 1.0.2源码解读

hexo入口函数

package.json中定义了

1
2
3
"bin": {
"hexo": "./bin/hexo"
}

所以到bin目录下的hexo

1
2
3
4
5
#!/usr/bin/env node

'use strict';


require('../lib/hexo')();

再到lib目录下的hexo.js,发现定义了module.exports= entry,那么找到entry方法

在没有找到hexo模块的情况下什么命令都不起作用

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
function entry(cwd, args) {
cwd = cwd || process.cwd();
//如果没有输入cwd那么就获取运行当前脚本的工作目录的路径
//ChangeWorkingDirectory cwd
//比如 hexo n 那么就是{ _: [ 'n' ] }
//hexo n --cwd e:\ss 就是{ _: [ 'help' ], cwd: 'e:\\ss' }
args = camelCaseKeys(args || minimist(process.argv.slice(2)));

//Context中注册了EventEmitter
var hexo = new Context(cwd, args);
var log = hexo.log;

// Change the title in console
process.title = 'hexo';

function handleError(err) {
log.fatal(err);
process.exit(2);
}
//findPkg其实就是检查package.json中是否有hexo
//并加载node_modules中的hexo 模块
return findPkg(cwd, args).then(function(path) {
if (!path) return;

hexo.base_dir = path;
//加载node_modules中的hexo模块
return loadModule(path, args).catch(function() {
log.error('Local hexo not found in %s', chalk.magenta(tildify(path)));
log.error('Try running: \'npm install hexo --save\'');
process.exit(2);
});
}).then(function(mod) {
if (mod) hexo = mod;
log = hexo.log;

require('./console')(hexo);

return hexo.init();
}).then(function() {
var cmd = '';

if (!args.h && !args.help) {
cmd = args._.shift();

if (cmd) {
var c = hexo.extend.console.get(cmd);
if (!c) cmd = 'help';
} else {
cmd = 'help';
}
} else {
cmd = 'help';
}

watchSignal(hexo);

return hexo.call(cmd, args).then(function() {
return hexo.exit();
}).catch(function(err) {
return hexo.exit(err).then(function() {
handleError(err);
});
});
}).catch(handleError);
}

process
NodeJs中的EventEmitter

jquery之静态filter函数解析

发表于 2016-08-27 | 更新于 2019-05-09

jquery1.0源码解读

filter函数

1.0源码:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
expr: {
"": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",
"#": "a.getAttribute('id')&&a.getAttribute('id')==m[2]",
":": {
// Position Checks
lt: "i<m[3]-0",
gt: "i>m[3]-0",
nth: "m[3]-0==i",
eq: "m[3]-0==i",
first: "i==0",
last: "i==r.length-1",
even: "i%2==0",
odd: "i%2",

// Child Checks
"first-child": "jQuery.sibling(a,0).cur",
"last-child": "jQuery.sibling(a,0).last",
"only-child": "jQuery.sibling(a).length==1",

// Parent Checks
parent: "a.childNodes.length",
empty: "!a.childNodes.length",

// Text Check
contains: "(a.innerText||a.innerHTML).indexOf(m[3])>=0",

// Visibility
visible: "a.type!='hidden'&&jQuery.css(a,'display')!='none'&&jQuery.css(a,'visibility')!='hidden'",
hidden: "a.type=='hidden'||jQuery.css(a,'display')=='none'||jQuery.css(a,'visibility')=='hidden'",

// Form elements
enabled: "!a.disabled",
disabled: "a.disabled",
checked: "a.checked",
selected: "a.selected"
},
".": "jQuery.className.has(a,m[2])",
"@": {
"=": "z==m[4]",
"!=": "z!=m[4]",
"^=": "!z.indexOf(m[4])",
"$=": "z.substr(z.length - m[4].length,m[4].length)==m[4]",
"*=": "z.indexOf(m[4])>=0",
"": "z"
},
"[": "jQuery.find(m[2],a).length"
},
// The regular expressions that power the parsing engine
//正则提供解析能力
parse: [
// Match: [@value='test'], [@foo]
[ "\\[ *(@)S *([!*$^=]*) *Q\\]", 1 ],

// Match: [div], [div p]
[ "(\\[)Q\\]", 0 ],

// Match: :contains('foo') * 匹配前面的子表达式任意次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。
[ "(:)S\\(Q\\)", 0 ],//(:)([a-z*_-][a-z0-9_-]*)\\(*'?\"?([^'\"]*?)'?\"? *\\)

// Match: :even, :last-chlid
[ "([:.#]*)S", 0 ]
],
//t 一般为字符串
//r为 元素集合
filter: function(t,r,not) {
// Figure out if we're doing regular, or inverse, filtering
//not 为undefined的时候 not!==false返回true
//所以g = jQuery.grep
//grep静态函数第三个参数为true的话就返回不满足条件的新的元素
//t为:not(.example)的时候就会递归调用
//最终调用的是grep函数
var g = not !== false ? jQuery.grep :
function(a,f) {return jQuery.grep(a,f,true);};

//not(.example) 符合正则
while ( t && /^[a-z[({<*:.#]/i.test(t) ) {

var p = jQuery.parse;//parse数组

for ( var i = 0; i < p.length; i++ ) {
var re = new RegExp( "^" + p[i][0]

// Look for a string-like sequence
.replace( 'S', "([a-z*_-][a-z0-9_-]*)" )

// Look for something (optionally) enclosed with quotes
.replace( 'Q', " *'?\"?([^'\"]*?)'?\"? *" ), "i" );

var m = re.exec( t );

//:not(.example)递归调用到这
//满足.example的就是[ "([:.#]*)S", 0 ]
if ( m ) {
// Re-organize the match
if ( p[i][1] )//Match: [@value='test'], [@foo] p[i][1] 为1
m = ["", m[1], m[3], m[2], m[4]];

// Remove what we just matched
t = t.replace( re, "" );//一般t就为空了,所以最后就跳出while循环
//.example的话 t就为空了
break;//这里就退出循环了
}
}

// :not() is a special case that can be optomized by
// keeping it out of the expression list
//:not(.example)
//m[0] = :not(.example)
//m[1] = :
//m[2] = not
//m[3] = .example
if ( m[1] == ":" && m[2] == "not" )
r = jQuery.filter(m[3],r,false).r;//递归下 到里面grep就是为包装grep的函数了

// Otherwise, find the expression to execute
//m[0] = .example
//m[1] = .
//m[2] = example
else {

//m[1]为.那么 在expr数组中就返回jQuery.className.has(a,m[2])
var f = jQuery.expr[m[1]];
if ( f.constructor != String )
f = jQuery.expr[m[1]][m[2]];

// Build a custom macro to enclose it
eval("f = function(a,i){" +
( m[1] == "@" ? "z=jQuery.attr(a,m[3]);" : "" ) +
"return " + f + "}");

// Execute it against the current filter
//f 为 function(a,i){
// return jQuery.className.has(a,m[2]) //m[2] 此时为'example'
//}
//再结合 g = function(a,f) {return jQuery.grep(a,f,true);};
//相当于jQuery.grep(r,f,true)
r = g( r, f );
}
}

// Return an array of filtered elements (r)
// and the modified expression string (t)
return { r: r, t: t };
},
className: {
add: function(o,c){
if (jQuery.className.has(o,c)) return;
o.className += ( o.className ? " " : "" ) + c;
},
remove: function(o,c){
o.className = !c ? "" :
o.className.replace(
new RegExp("(^|\\s*\\b[^-])"+c+"($|\\b(?=[^-]))", "g"), "");
},
has: function(e,a) {
if ( e.className != undefined )
e = e.className;//直接把e.className给e
//以a开头和结束
//或者a前面和后面是空格
return new RegExp("(^|\\s)" + a + "(\\s|$)").test(e);
}
},

jquery之map函数解析

发表于 2016-08-27 | 更新于 2019-05-09

jquery1.0源码解读

filter函数

1.0源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
map: function(elems, fn) {
// If a string is passed in for the function, make a function
// for it (a handy shortcut)
if ( fn.constructor == String )
fn = new Function("a","return " + fn);

var result = [];//初始化一个空数组

// Go through the array, translating each of the items to their
// new value (or values).
for ( var i = 0; i < elems.length; i++ ) {
var val = fn(elems[i],i);//调用参数fn 函数 返回fn中的新结果

//跟grep的函数区别就在于返回的是函数中新的返回值
//这就是映射
//而不是返回满足函数条件的旧元素
if ( val !== null && val != undefined ) {
if ( val.constructor != Array ) val = [val];
result = jQuery.merge( result, val );//合并
}
}

return result;
}

jquery之filter函数解析

发表于 2016-08-27 | 更新于 2019-05-09

jquery1.0源码解读

filter函数

1.0源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
filter: function(t) {

//返回pushStack的结果
//这种 与加或 的方法值得学习
return this.pushStack(
//如果参数是数组 那么就调用map函数
//返回新的结果
t.constructor == Array &&
jQuery.map(this,function(a){
for ( var i = 0; i < t.length; i++ )
if ( jQuery.filter(t[i],[a]).r.length )
return a;
}) ||
//如果参数是true那么就直接get()获取
//如果参数是false那么就返回空数组
t.constructor == Boolean &&
( t ? this.get() : [] ) ||
//如果参数是函数那么就调用grep函数
t.constructor == Function &&
jQuery.grep( this, t ) ||
//如果参数是其他类型那么就调用静态的filter函数
jQuery.filter(t,this).r, arguments );
}

根据函数类型判断再内部调用不同的函数:

1.grep函数内部就是遍历元素数组,调用参数函数t,如果满足t函数,那么就push到result数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
grep: function(elems, fn, inv) {
// If a string is passed in for the function, make a function
// for it (a handy shortcut)
if ( fn.constructor == String )
fn = new Function("a","i","return " + fn);
//定义局部数组
var result = [];

// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0; i < elems.length; i++ )
if ( !inv && fn(elems[i],i) || inv && !fn(elems[i],i) )
result.push( elems[i] );

return result;
}

比如

1
2
3
4
5
6
var elems = $('li');

elems.filter(function(index) {
//index就是elems的一个元素
return $("strong",index).length == 1;//
}).css('background-color', 'red');

jQuery的静态方法是通过extent扩展方法生成的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function jQuery(){

}

jQuery.extend = function(obj,prop) {
//巧妙的运用了obj =this;转换了角色
//obj就变成jQuery
//prop就变成了obj
if ( !prop ) { prop = obj; obj = this; }
for ( var i in prop ) obj[i] = prop[i];
return obj;
};

//jQuery静态方法就可以通过如下方法引入
jQuery.extend({

})

1…424344…47

John

232 日志
43 标签
GitHub Twitter
欢迎关注我的公众号:沉迷Spring
© 2023 johnwonder
由 Hexo 强力驱动 v3.2.0
|
主题 – NexT.Pisces v7.1.1
|
0%