oipage 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG +61 -61
- package/README.md +122 -122
- package/bin/options.js +73 -73
- package/bin/run +208 -208
- package/browserjs/getStyle/index.d.ts +10 -10
- package/browserjs/getStyle/index.js +12 -12
- package/browserjs/index.d.ts +12 -12
- package/browserjs/index.js +8 -8
- package/browserjs/onReady/index.d.ts +7 -7
- package/browserjs/onReady/index.js +7 -7
- package/browserjs/setStyle/index.d.ts +9 -9
- package/browserjs/setStyle/index.js +4 -4
- package/corejs/animation/index.d.ts +11 -11
- package/corejs/animation/index.js +101 -101
- package/corejs/index.d.ts +9 -9
- package/corejs/index.js +6 -6
- package/corejs/throttle/index.d.ts +30 -30
- package/corejs/throttle/index.js +49 -49
- package/nodejs/core/file.js +162 -162
- package/nodejs/core/image.js +4 -4
- package/nodejs/core/log.js +89 -89
- package/nodejs/core/network.js +39 -39
- package/nodejs/core/options.js +48 -48
- package/nodejs/core/remote.js +60 -60
- package/nodejs/core/responseFileList.js +27 -27
- package/nodejs/core/server.js +198 -198
- package/nodejs/data/404.js +51 -51
- package/nodejs/data/mime.types.js +111 -111
- package/nodejs/form/common.js +2 -2
- package/nodejs/form/index.js +79 -79
- package/nodejs/form/select.js +9 -9
- package/nodejs/index.js +57 -57
- package/nodejs/loader/simpleScss.js +247 -247
- package/nodejs/loader/xhtml.js +520 -520
- package/nodejs/reader/plain.js +20 -20
- package/package.json +33 -33
- package/stylecss/index.css +3 -3
- package/stylecss/normalize.css +93 -93
- package/stylecss/rasterize.css +317 -317
- package/stylecss/skeleton.css +16 -16
- package/types/get-options.d.ts +5 -5
- package/types/index.d.ts +186 -186
package/nodejs/loader/xhtml.js
CHANGED
|
@@ -1,521 +1,521 @@
|
|
|
1
|
-
// 标记所有没有闭合结点的直接自闭合
|
|
2
|
-
let closeTag = function (tagArray) {
|
|
3
|
-
|
|
4
|
-
let needClose = [];
|
|
5
|
-
|
|
6
|
-
tagArray.forEach(function (tag, i) {
|
|
7
|
-
if (tag.type == 'beginTag') {
|
|
8
|
-
|
|
9
|
-
needClose.push([i, tag.tagName]);
|
|
10
|
-
|
|
11
|
-
} else if (tag.type == 'endTag') {
|
|
12
|
-
|
|
13
|
-
while (needClose.length > 0) {
|
|
14
|
-
|
|
15
|
-
let needCloseTag = needClose.pop();
|
|
16
|
-
|
|
17
|
-
if (needCloseTag[1] == tag.tagName) {
|
|
18
|
-
break;
|
|
19
|
-
} else {
|
|
20
|
-
tagArray[needCloseTag[0]].type = 'fullTag';
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
return tagArray;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// 分析deep
|
|
32
|
-
// 我们会在这里校对那些没有结束标签的开始标签
|
|
33
|
-
// 这步结束以后,每个都是一个单独的标签
|
|
34
|
-
// 也就是不用再区分开始或闭合了
|
|
35
|
-
let analyseDeep = function (tagArray) {
|
|
36
|
-
|
|
37
|
-
// 闭合标签
|
|
38
|
-
tagArray = closeTag(tagArray);
|
|
39
|
-
|
|
40
|
-
let deep = 0, tagDeepArray = [];
|
|
41
|
-
|
|
42
|
-
tagArray.forEach(function (tag) {
|
|
43
|
-
|
|
44
|
-
if (tag.type == 'beginTag') {
|
|
45
|
-
|
|
46
|
-
tagDeepArray.push({
|
|
47
|
-
type: "tag",
|
|
48
|
-
name: tag.tagName,
|
|
49
|
-
attrs: tag.attrs,
|
|
50
|
-
__deep__: ++deep,
|
|
51
|
-
__tagType__: "double"
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
} else if (tag.type == 'endTag') {
|
|
55
|
-
|
|
56
|
-
deep -= 1;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
} else if (tag.type == 'textcode') {
|
|
60
|
-
|
|
61
|
-
// 如果是文本
|
|
62
|
-
tagDeepArray.push({
|
|
63
|
-
type: "text",
|
|
64
|
-
content: tag.tagName,
|
|
65
|
-
__deep__: deep + 1
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
} else if (tag.type == 'comment') {
|
|
69
|
-
|
|
70
|
-
// 如果是注释
|
|
71
|
-
tagDeepArray.push({
|
|
72
|
-
type: "comment",
|
|
73
|
-
content: tag.tagName,
|
|
74
|
-
__deep__: deep + 1
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
} else {
|
|
78
|
-
|
|
79
|
-
// 如果是自闭合结点
|
|
80
|
-
tagDeepArray.push({
|
|
81
|
-
type: "tag",
|
|
82
|
-
name: tag.tagName,
|
|
83
|
-
attrs: tag.attrs,
|
|
84
|
-
__deep__: deep + 1,
|
|
85
|
-
__tagType__: "single"
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
return tagDeepArray;
|
|
93
|
-
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// 分析结点的属性
|
|
97
|
-
let analyseTag = function (attrString) {
|
|
98
|
-
let attr = {}, index = 0;
|
|
99
|
-
|
|
100
|
-
attrString = attrString.trim();
|
|
101
|
-
|
|
102
|
-
let getOneAttr = function () {
|
|
103
|
-
|
|
104
|
-
// 属性名和属性值
|
|
105
|
-
let attrName = "", attrValue = "";
|
|
106
|
-
|
|
107
|
-
// 先寻找属性名
|
|
108
|
-
for (; index < attrString.length; index++) {
|
|
109
|
-
|
|
110
|
-
// 寻找属性名的时候遇到空白或结尾的时候,肯定没有属性值
|
|
111
|
-
if (/^[\x20\t\r\n\f]{0,}$/.test(attrString[index]) || index == attrString.length - 1) {
|
|
112
|
-
|
|
113
|
-
attrName += attrString[index];
|
|
114
|
-
|
|
115
|
-
// 如果属性名是空白,就不需要记录了
|
|
116
|
-
if (!/^[\x20\t\r\n\f]{0,}$/.test(attrName)) {
|
|
117
|
-
attr[attrName.trim()] = "";
|
|
118
|
-
}
|
|
119
|
-
index += 1;
|
|
120
|
-
break;
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// 如果遇到等号,说明属性名寻找结束了
|
|
125
|
-
else if (attrString[index] == '=') {
|
|
126
|
-
|
|
127
|
-
// 接着寻找属性值
|
|
128
|
-
index += 1;
|
|
129
|
-
|
|
130
|
-
// 由于属性可能由引号包裹或直接暴露
|
|
131
|
-
let preCode = null, preLeng = -1;
|
|
132
|
-
|
|
133
|
-
// 如果是由'或者"包裹
|
|
134
|
-
if (attrString.substr(index, 1) == '"' || attrString.substr(index, 1) == "'") {
|
|
135
|
-
preCode = attrString.substr(index, 1);
|
|
136
|
-
preLeng = 1;
|
|
137
|
-
index += 1;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// 如果是由\'或\"包裹
|
|
141
|
-
else if (attrString.substr(index, 2) == '\"' || attrString.substr(index, 2) == "\'") {
|
|
142
|
-
preCode = attrString.substr(index, 2);
|
|
143
|
-
preLeng = 2;
|
|
144
|
-
index += 2;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// 开始正式寻找属性值
|
|
148
|
-
|
|
149
|
-
// 如果没有包裹,是直接暴露在外面的
|
|
150
|
-
// 我们寻找到空格或结尾即可
|
|
151
|
-
if (preCode !== null) {
|
|
152
|
-
|
|
153
|
-
for (; index < attrString.length; index++) {
|
|
154
|
-
if (attrString.substr(index, preLeng) == preCode) {
|
|
155
|
-
attr[attrName.trim()] = attrValue.trim();
|
|
156
|
-
index += 2;
|
|
157
|
-
break;
|
|
158
|
-
} else {
|
|
159
|
-
attrValue += attrString[index];
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// 如果是包裹的
|
|
166
|
-
// 我们确定寻找到对应的包裹闭合即可
|
|
167
|
-
else {
|
|
168
|
-
for (; index < attrString.length; index++) {
|
|
169
|
-
if (/^[\x20\t\r\n\f]{0,}$/.test(attrString[index])) {
|
|
170
|
-
attr[attrName.trim()] = attrValue.trim();
|
|
171
|
-
index += 1;
|
|
172
|
-
break;
|
|
173
|
-
} else {
|
|
174
|
-
attrValue += attrString[index];
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
break;
|
|
180
|
-
|
|
181
|
-
} else {
|
|
182
|
-
attrName += attrString[index];
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// 如果还有字符串,继续解析
|
|
187
|
-
if (index < attrString.length) {
|
|
188
|
-
getOneAttr();
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
getOneAttr();
|
|
194
|
-
|
|
195
|
-
return attr;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
let nextTagFun = function (template) {
|
|
199
|
-
|
|
200
|
-
let i = -1,
|
|
201
|
-
|
|
202
|
-
// 当前面对的字符
|
|
203
|
-
currentChar = null;
|
|
204
|
-
|
|
205
|
-
// 如果前面是获取的js或css,还有pre等开始标签,比较特殊,直接寻址闭合的
|
|
206
|
-
let preIsSpecial = false, specialCode = "";
|
|
207
|
-
let specialTag = ['script', 'pre', 'style', 'code'];
|
|
208
|
-
|
|
209
|
-
// 获取下一个字符
|
|
210
|
-
let next = function () {
|
|
211
|
-
currentChar = i++ < template.length - 1 ? template[i] : null;
|
|
212
|
-
return currentChar;
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
// 获取往后n个值
|
|
216
|
-
let nextNValue = function (n) {
|
|
217
|
-
return template.substring(i, n + i > template.length ? template.length : n + i);
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
next();
|
|
221
|
-
// 剔除开头的空白
|
|
222
|
-
while (new RegExp("[\\x20\\t\\r\\n\\f]").test(currentChar) && i < template.length - 1) next();
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* 一个Tag存在哪些类型?如下:
|
|
227
|
-
* 1.<tag-name> { tagName:'tag-name', type:'beginTag', attrs:{} } 开始标签
|
|
228
|
-
* 2.</tag-name> { tagName:'tag-name', type:'endTag' } 结束标签
|
|
229
|
-
* 3.<tag-name /> { tagName:'tag-name', type:'fullTag', attrs:{} } 自闭合标签
|
|
230
|
-
* 4.text { tagName:'text', type:'textcode' } 文本结点
|
|
231
|
-
* 5.<!-- text --> { tagName:'text', type:'comment' } 注释
|
|
232
|
-
* 6.<!DOCTYPE text> { tagName:'text', type:'DOCTYPE' } 声明
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*/
|
|
236
|
-
return function () {
|
|
237
|
-
|
|
238
|
-
let tag = currentChar, tagObj = {};
|
|
239
|
-
|
|
240
|
-
if (tag == null) return null;
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* 特殊标签内容获取
|
|
244
|
-
* ========================================
|
|
245
|
-
*/
|
|
246
|
-
|
|
247
|
-
// 如果是获取特殊标签里面的内容
|
|
248
|
-
// 先不考虑里面包含'</XXX>'
|
|
249
|
-
if (preIsSpecial) {
|
|
250
|
-
tagObj.type = 'textcode';
|
|
251
|
-
tagObj.tagName = tag;
|
|
252
|
-
while (nextNValue(specialCode.length + 3) != '</' + specialCode + '>' && i < template.length) {
|
|
253
|
-
tagObj.tagName += next();
|
|
254
|
-
}
|
|
255
|
-
tagObj.tagName = tagObj.tagName.replace(/<$/, '');
|
|
256
|
-
preIsSpecial = false;
|
|
257
|
-
return tagObj;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* 特殊标签获取
|
|
262
|
-
* ========================================
|
|
263
|
-
*/
|
|
264
|
-
// 针对特殊的comment
|
|
265
|
-
if (nextNValue(4) == '<!--') {
|
|
266
|
-
tagObj.type = 'comment';
|
|
267
|
-
tagObj.tagName = tag;
|
|
268
|
-
while (nextNValue(3) != '-->' && i < template.length) {
|
|
269
|
-
tagObj.tagName += next();
|
|
270
|
-
}
|
|
271
|
-
next(); next(); next();
|
|
272
|
-
tagObj.tagName = tagObj.tagName.replace(/^<!--/, '').replace(/-$/, '');
|
|
273
|
-
return tagObj;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// 针对特殊的doctype
|
|
277
|
-
if (nextNValue(9) == '<!DOCTYPE') {
|
|
278
|
-
tagObj.type = 'DOCTYPE';
|
|
279
|
-
tagObj.tagName = tag;
|
|
280
|
-
while (nextNValue(1) != '>' && i < template.length) {
|
|
281
|
-
tagObj.tagName += next();
|
|
282
|
-
}
|
|
283
|
-
next();
|
|
284
|
-
tagObj.tagName = tagObj.tagName.replace(/^<!DOCTYPE/, '').replace(/>$/, '');
|
|
285
|
-
return tagObj;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* 普通的
|
|
290
|
-
* ========================================
|
|
291
|
-
*/
|
|
292
|
-
|
|
293
|
-
// 如果是期望归结非文本结点
|
|
294
|
-
else if (tag == '<') {
|
|
295
|
-
|
|
296
|
-
// 标记是否处于属性值是字符串包裹中
|
|
297
|
-
let isAttrString = false, attrLeftValue = null, attrLeftLen = null;
|
|
298
|
-
|
|
299
|
-
// 如果在包裹中或者没有遇到‘>’说明没有结束
|
|
300
|
-
while ((isAttrString || currentChar != '>') && i < template.length) {
|
|
301
|
-
|
|
302
|
-
tag += next();
|
|
303
|
-
|
|
304
|
-
// 如果是包裹里面,试探是否即将遇到了结束
|
|
305
|
-
if (isAttrString) {
|
|
306
|
-
|
|
307
|
-
let next23Value = nextNValue(attrLeftLen + 1).substring(1);
|
|
308
|
-
if (next23Value == attrLeftValue) {
|
|
309
|
-
isAttrString = false;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// 如果在包裹外面,试探是否即将进入包裹
|
|
315
|
-
else {
|
|
316
|
-
|
|
317
|
-
let next23Value = nextNValue(2);
|
|
318
|
-
if (next23Value == '="' || next23Value == "='") {
|
|
319
|
-
attrLeftValue = next23Value.replace('=', '');
|
|
320
|
-
attrLeftLen = 1;
|
|
321
|
-
isAttrString = true;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
next23Value = nextNValue(3);
|
|
325
|
-
if (next23Value == '=\"' || next23Value == "=\'") {
|
|
326
|
-
attrLeftValue = next23Value.replace('=', '');
|
|
327
|
-
attrLeftLen = 2;
|
|
328
|
-
isAttrString = true;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// 针对特殊的结束标签
|
|
337
|
-
if (/^<\//.test(tag)) {
|
|
338
|
-
tagObj.tagName = tag.replace(/^<\//, '').replace(/>$/, '');
|
|
339
|
-
tagObj.type = 'endTag';
|
|
340
|
-
} else {
|
|
341
|
-
|
|
342
|
-
if (/\/>$/.test(tag)) {
|
|
343
|
-
tagObj.type = 'fullTag';
|
|
344
|
-
tag = tag.replace(/\/>$/, '');
|
|
345
|
-
} else {
|
|
346
|
-
tagObj.type = 'beginTag';
|
|
347
|
-
tag = tag.replace(/>$/, '');
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
tag = tag.replace(/^</, '');
|
|
351
|
-
|
|
352
|
-
tagObj.tagName = "";
|
|
353
|
-
let j = 0;
|
|
354
|
-
for (; j < tag.length; j++) {
|
|
355
|
-
if (tag[j] == ' ') break;
|
|
356
|
-
tagObj.tagName += tag[j];
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
let attrString = tag.substring(j);
|
|
360
|
-
if (/^[\x20\t\r\n\f]{0,}$/.test(attrString)) {
|
|
361
|
-
tagObj.attrs = {};
|
|
362
|
-
} else {
|
|
363
|
-
tagObj.attrs = analyseTag(attrString);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// 如果是归结文本结点
|
|
371
|
-
// 如果文本中包含<的先忽略考虑
|
|
372
|
-
else {
|
|
373
|
-
tagObj.type = 'textcode';
|
|
374
|
-
tagObj.tagName = currentChar;
|
|
375
|
-
while (nextNValue(1) != '<' && i < template.length) {
|
|
376
|
-
tagObj.tagName += next();
|
|
377
|
-
}
|
|
378
|
-
tagObj.tagName = tagObj.tagName.replace(/<$/, '');
|
|
379
|
-
i -= 1;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
// 如果遇到开始script或者style、pre等特殊标签,标记开始获取特殊文本
|
|
384
|
-
if (tagObj.type == 'beginTag') {
|
|
385
|
-
if (specialTag.indexOf(tagObj.tagName.toLowerCase()) > -1) {
|
|
386
|
-
preIsSpecial = true;
|
|
387
|
-
specialCode = tagObj.tagName;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// 如果遇到结束script或者style、pre等特殊标签,标记结束获取特殊文本
|
|
393
|
-
else if (tagObj.type == 'endTag') {
|
|
394
|
-
if (specialTag.indexOf(tagObj.tagName.toLowerCase()) > -1) {
|
|
395
|
-
preIsSpecial = false;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
next();
|
|
400
|
-
|
|
401
|
-
return tagObj;
|
|
402
|
-
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
module.exports = function (source) {
|
|
408
|
-
// 获取读取下一个标签对象
|
|
409
|
-
let nextTag = nextTagFun("<root>" + source.trim() + "</root>");
|
|
410
|
-
|
|
411
|
-
let tag = nextTag(), DomTree = [];
|
|
412
|
-
while (tag != null) {
|
|
413
|
-
|
|
414
|
-
if (tag.type == 'textcode' && /^[\x20\t\r\n\f]{0,}$/.test(tag.tagName)) {
|
|
415
|
-
|
|
416
|
-
// 空白文本结点过滤掉
|
|
417
|
-
|
|
418
|
-
} else if (tag.type == 'DOCTYPE') {
|
|
419
|
-
|
|
420
|
-
// DOCTYPE过滤掉
|
|
421
|
-
|
|
422
|
-
} else if (tag.type == 'comment') {
|
|
423
|
-
|
|
424
|
-
// 注释过滤掉
|
|
425
|
-
|
|
426
|
-
} else {
|
|
427
|
-
tag.tagName = tag.tagName.trim();
|
|
428
|
-
DomTree.push(tag);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
tag = nextTag();
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// 分析层次
|
|
435
|
-
DomTree = analyseDeep(DomTree);
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* 模仿浏览器构建的一棵树,每个结点有如下属性:
|
|
439
|
-
*
|
|
440
|
-
* 1.parentNode index 父结点
|
|
441
|
-
* 2.childNodes [] 孩子结点
|
|
442
|
-
* 3.preNode index 前一个兄弟结点
|
|
443
|
-
* 4.nextNode index 后一个兄弟结点
|
|
444
|
-
*
|
|
445
|
-
* 5.attrs:{} 当前结点的属性
|
|
446
|
-
* 6.name 节点名称
|
|
447
|
-
* 7.type 节点类型(tag和text)
|
|
448
|
-
* 8.content 文本结点内容
|
|
449
|
-
*
|
|
450
|
-
* 需要注意的是:如果一个文本结点内容只包含回车,tab,空格等空白字符,会直接被忽视
|
|
451
|
-
*/
|
|
452
|
-
|
|
453
|
-
let presNode = [null], preDeep = 0;
|
|
454
|
-
for (let i = 0; i < DomTree.length; i++) {
|
|
455
|
-
|
|
456
|
-
// 当前结点
|
|
457
|
-
let currentIndex = i, currentDeep = DomTree[i].__deep__;
|
|
458
|
-
DomTree[i].childNodes = [];
|
|
459
|
-
DomTree[i].preNode = null;
|
|
460
|
-
DomTree[i].nextNode = null;
|
|
461
|
-
|
|
462
|
-
// 前置三个结点
|
|
463
|
-
let lastPre = presNode[presNode.length - 1];
|
|
464
|
-
let last2Pre = presNode.length > 1 ? presNode[presNode.length - 2] : null;
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
// 如果遇到的是兄弟结点
|
|
468
|
-
if (currentDeep == preDeep) {
|
|
469
|
-
|
|
470
|
-
// 修改兄弟关系
|
|
471
|
-
DomTree[currentIndex].preNode = lastPre;
|
|
472
|
-
DomTree[lastPre].nextNode = currentIndex;
|
|
473
|
-
|
|
474
|
-
// 修改父子关系
|
|
475
|
-
DomTree[currentIndex].parentNode = last2Pre;
|
|
476
|
-
DomTree[last2Pre].childNodes.push(currentIndex);
|
|
477
|
-
|
|
478
|
-
// 校对presNode
|
|
479
|
-
presNode[presNode.length - 1] = currentIndex;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// 如果是遇到了孩子
|
|
483
|
-
else if (currentDeep > preDeep) {
|
|
484
|
-
|
|
485
|
-
// 修改兄弟关系
|
|
486
|
-
// todo
|
|
487
|
-
|
|
488
|
-
// 修改父子关系
|
|
489
|
-
DomTree[currentIndex].parentNode = lastPre;
|
|
490
|
-
if (lastPre != null) DomTree[lastPre].childNodes.push(currentIndex);
|
|
491
|
-
|
|
492
|
-
// 校对presNode
|
|
493
|
-
presNode.push(currentIndex);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// 如果是遇到了祖先
|
|
497
|
-
else {
|
|
498
|
-
|
|
499
|
-
let preTempIndex = presNode[presNode.length - 1 - (preDeep - currentDeep)];
|
|
500
|
-
let preTemp2Index = presNode[presNode.length - 2 - (preDeep - currentDeep)];
|
|
501
|
-
|
|
502
|
-
// 修改兄弟关系
|
|
503
|
-
DomTree[currentIndex].preNode = preTempIndex;
|
|
504
|
-
if (preTempIndex != null) DomTree[preTempIndex].nextNode = currentIndex;
|
|
505
|
-
|
|
506
|
-
// 修改父子关系
|
|
507
|
-
DomTree[currentIndex].parentNode = preTemp2Index;
|
|
508
|
-
if (preTemp2Index != null) DomTree[preTemp2Index].childNodes.push(currentIndex);
|
|
509
|
-
|
|
510
|
-
// 校对presNode
|
|
511
|
-
for (let j = 0; j < preDeep - currentDeep; j++) { presNode.pop(); }
|
|
512
|
-
presNode[presNode.length - 1] = currentIndex;
|
|
513
|
-
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
preDeep = currentDeep;
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
return DomTree;
|
|
1
|
+
// 标记所有没有闭合结点的直接自闭合
|
|
2
|
+
let closeTag = function (tagArray) {
|
|
3
|
+
|
|
4
|
+
let needClose = [];
|
|
5
|
+
|
|
6
|
+
tagArray.forEach(function (tag, i) {
|
|
7
|
+
if (tag.type == 'beginTag') {
|
|
8
|
+
|
|
9
|
+
needClose.push([i, tag.tagName]);
|
|
10
|
+
|
|
11
|
+
} else if (tag.type == 'endTag') {
|
|
12
|
+
|
|
13
|
+
while (needClose.length > 0) {
|
|
14
|
+
|
|
15
|
+
let needCloseTag = needClose.pop();
|
|
16
|
+
|
|
17
|
+
if (needCloseTag[1] == tag.tagName) {
|
|
18
|
+
break;
|
|
19
|
+
} else {
|
|
20
|
+
tagArray[needCloseTag[0]].type = 'fullTag';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return tagArray;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 分析deep
|
|
32
|
+
// 我们会在这里校对那些没有结束标签的开始标签
|
|
33
|
+
// 这步结束以后,每个都是一个单独的标签
|
|
34
|
+
// 也就是不用再区分开始或闭合了
|
|
35
|
+
let analyseDeep = function (tagArray) {
|
|
36
|
+
|
|
37
|
+
// 闭合标签
|
|
38
|
+
tagArray = closeTag(tagArray);
|
|
39
|
+
|
|
40
|
+
let deep = 0, tagDeepArray = [];
|
|
41
|
+
|
|
42
|
+
tagArray.forEach(function (tag) {
|
|
43
|
+
|
|
44
|
+
if (tag.type == 'beginTag') {
|
|
45
|
+
|
|
46
|
+
tagDeepArray.push({
|
|
47
|
+
type: "tag",
|
|
48
|
+
name: tag.tagName,
|
|
49
|
+
attrs: tag.attrs,
|
|
50
|
+
__deep__: ++deep,
|
|
51
|
+
__tagType__: "double"
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
} else if (tag.type == 'endTag') {
|
|
55
|
+
|
|
56
|
+
deep -= 1;
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
} else if (tag.type == 'textcode') {
|
|
60
|
+
|
|
61
|
+
// 如果是文本
|
|
62
|
+
tagDeepArray.push({
|
|
63
|
+
type: "text",
|
|
64
|
+
content: tag.tagName,
|
|
65
|
+
__deep__: deep + 1
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
} else if (tag.type == 'comment') {
|
|
69
|
+
|
|
70
|
+
// 如果是注释
|
|
71
|
+
tagDeepArray.push({
|
|
72
|
+
type: "comment",
|
|
73
|
+
content: tag.tagName,
|
|
74
|
+
__deep__: deep + 1
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
} else {
|
|
78
|
+
|
|
79
|
+
// 如果是自闭合结点
|
|
80
|
+
tagDeepArray.push({
|
|
81
|
+
type: "tag",
|
|
82
|
+
name: tag.tagName,
|
|
83
|
+
attrs: tag.attrs,
|
|
84
|
+
__deep__: deep + 1,
|
|
85
|
+
__tagType__: "single"
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return tagDeepArray;
|
|
93
|
+
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// 分析结点的属性
|
|
97
|
+
let analyseTag = function (attrString) {
|
|
98
|
+
let attr = {}, index = 0;
|
|
99
|
+
|
|
100
|
+
attrString = attrString.trim();
|
|
101
|
+
|
|
102
|
+
let getOneAttr = function () {
|
|
103
|
+
|
|
104
|
+
// 属性名和属性值
|
|
105
|
+
let attrName = "", attrValue = "";
|
|
106
|
+
|
|
107
|
+
// 先寻找属性名
|
|
108
|
+
for (; index < attrString.length; index++) {
|
|
109
|
+
|
|
110
|
+
// 寻找属性名的时候遇到空白或结尾的时候,肯定没有属性值
|
|
111
|
+
if (/^[\x20\t\r\n\f]{0,}$/.test(attrString[index]) || index == attrString.length - 1) {
|
|
112
|
+
|
|
113
|
+
attrName += attrString[index];
|
|
114
|
+
|
|
115
|
+
// 如果属性名是空白,就不需要记录了
|
|
116
|
+
if (!/^[\x20\t\r\n\f]{0,}$/.test(attrName)) {
|
|
117
|
+
attr[attrName.trim()] = "";
|
|
118
|
+
}
|
|
119
|
+
index += 1;
|
|
120
|
+
break;
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 如果遇到等号,说明属性名寻找结束了
|
|
125
|
+
else if (attrString[index] == '=') {
|
|
126
|
+
|
|
127
|
+
// 接着寻找属性值
|
|
128
|
+
index += 1;
|
|
129
|
+
|
|
130
|
+
// 由于属性可能由引号包裹或直接暴露
|
|
131
|
+
let preCode = null, preLeng = -1;
|
|
132
|
+
|
|
133
|
+
// 如果是由'或者"包裹
|
|
134
|
+
if (attrString.substr(index, 1) == '"' || attrString.substr(index, 1) == "'") {
|
|
135
|
+
preCode = attrString.substr(index, 1);
|
|
136
|
+
preLeng = 1;
|
|
137
|
+
index += 1;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 如果是由\'或\"包裹
|
|
141
|
+
else if (attrString.substr(index, 2) == '\"' || attrString.substr(index, 2) == "\'") {
|
|
142
|
+
preCode = attrString.substr(index, 2);
|
|
143
|
+
preLeng = 2;
|
|
144
|
+
index += 2;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 开始正式寻找属性值
|
|
148
|
+
|
|
149
|
+
// 如果没有包裹,是直接暴露在外面的
|
|
150
|
+
// 我们寻找到空格或结尾即可
|
|
151
|
+
if (preCode !== null) {
|
|
152
|
+
|
|
153
|
+
for (; index < attrString.length; index++) {
|
|
154
|
+
if (attrString.substr(index, preLeng) == preCode) {
|
|
155
|
+
attr[attrName.trim()] = attrValue.trim();
|
|
156
|
+
index += 2;
|
|
157
|
+
break;
|
|
158
|
+
} else {
|
|
159
|
+
attrValue += attrString[index];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// 如果是包裹的
|
|
166
|
+
// 我们确定寻找到对应的包裹闭合即可
|
|
167
|
+
else {
|
|
168
|
+
for (; index < attrString.length; index++) {
|
|
169
|
+
if (/^[\x20\t\r\n\f]{0,}$/.test(attrString[index])) {
|
|
170
|
+
attr[attrName.trim()] = attrValue.trim();
|
|
171
|
+
index += 1;
|
|
172
|
+
break;
|
|
173
|
+
} else {
|
|
174
|
+
attrValue += attrString[index];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
break;
|
|
180
|
+
|
|
181
|
+
} else {
|
|
182
|
+
attrName += attrString[index];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 如果还有字符串,继续解析
|
|
187
|
+
if (index < attrString.length) {
|
|
188
|
+
getOneAttr();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
getOneAttr();
|
|
194
|
+
|
|
195
|
+
return attr;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
let nextTagFun = function (template) {
|
|
199
|
+
|
|
200
|
+
let i = -1,
|
|
201
|
+
|
|
202
|
+
// 当前面对的字符
|
|
203
|
+
currentChar = null;
|
|
204
|
+
|
|
205
|
+
// 如果前面是获取的js或css,还有pre等开始标签,比较特殊,直接寻址闭合的
|
|
206
|
+
let preIsSpecial = false, specialCode = "";
|
|
207
|
+
let specialTag = ['script', 'pre', 'style', 'code'];
|
|
208
|
+
|
|
209
|
+
// 获取下一个字符
|
|
210
|
+
let next = function () {
|
|
211
|
+
currentChar = i++ < template.length - 1 ? template[i] : null;
|
|
212
|
+
return currentChar;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// 获取往后n个值
|
|
216
|
+
let nextNValue = function (n) {
|
|
217
|
+
return template.substring(i, n + i > template.length ? template.length : n + i);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
next();
|
|
221
|
+
// 剔除开头的空白
|
|
222
|
+
while (new RegExp("[\\x20\\t\\r\\n\\f]").test(currentChar) && i < template.length - 1) next();
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* 一个Tag存在哪些类型?如下:
|
|
227
|
+
* 1.<tag-name> { tagName:'tag-name', type:'beginTag', attrs:{} } 开始标签
|
|
228
|
+
* 2.</tag-name> { tagName:'tag-name', type:'endTag' } 结束标签
|
|
229
|
+
* 3.<tag-name /> { tagName:'tag-name', type:'fullTag', attrs:{} } 自闭合标签
|
|
230
|
+
* 4.text { tagName:'text', type:'textcode' } 文本结点
|
|
231
|
+
* 5.<!-- text --> { tagName:'text', type:'comment' } 注释
|
|
232
|
+
* 6.<!DOCTYPE text> { tagName:'text', type:'DOCTYPE' } 声明
|
|
233
|
+
*
|
|
234
|
+
*
|
|
235
|
+
*/
|
|
236
|
+
return function () {
|
|
237
|
+
|
|
238
|
+
let tag = currentChar, tagObj = {};
|
|
239
|
+
|
|
240
|
+
if (tag == null) return null;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* 特殊标签内容获取
|
|
244
|
+
* ========================================
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
// 如果是获取特殊标签里面的内容
|
|
248
|
+
// 先不考虑里面包含'</XXX>'
|
|
249
|
+
if (preIsSpecial) {
|
|
250
|
+
tagObj.type = 'textcode';
|
|
251
|
+
tagObj.tagName = tag;
|
|
252
|
+
while (nextNValue(specialCode.length + 3) != '</' + specialCode + '>' && i < template.length) {
|
|
253
|
+
tagObj.tagName += next();
|
|
254
|
+
}
|
|
255
|
+
tagObj.tagName = tagObj.tagName.replace(/<$/, '');
|
|
256
|
+
preIsSpecial = false;
|
|
257
|
+
return tagObj;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* 特殊标签获取
|
|
262
|
+
* ========================================
|
|
263
|
+
*/
|
|
264
|
+
// 针对特殊的comment
|
|
265
|
+
if (nextNValue(4) == '<!--') {
|
|
266
|
+
tagObj.type = 'comment';
|
|
267
|
+
tagObj.tagName = tag;
|
|
268
|
+
while (nextNValue(3) != '-->' && i < template.length) {
|
|
269
|
+
tagObj.tagName += next();
|
|
270
|
+
}
|
|
271
|
+
next(); next(); next();
|
|
272
|
+
tagObj.tagName = tagObj.tagName.replace(/^<!--/, '').replace(/-$/, '');
|
|
273
|
+
return tagObj;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// 针对特殊的doctype
|
|
277
|
+
if (nextNValue(9) == '<!DOCTYPE') {
|
|
278
|
+
tagObj.type = 'DOCTYPE';
|
|
279
|
+
tagObj.tagName = tag;
|
|
280
|
+
while (nextNValue(1) != '>' && i < template.length) {
|
|
281
|
+
tagObj.tagName += next();
|
|
282
|
+
}
|
|
283
|
+
next();
|
|
284
|
+
tagObj.tagName = tagObj.tagName.replace(/^<!DOCTYPE/, '').replace(/>$/, '');
|
|
285
|
+
return tagObj;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 普通的
|
|
290
|
+
* ========================================
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
// 如果是期望归结非文本结点
|
|
294
|
+
else if (tag == '<') {
|
|
295
|
+
|
|
296
|
+
// 标记是否处于属性值是字符串包裹中
|
|
297
|
+
let isAttrString = false, attrLeftValue = null, attrLeftLen = null;
|
|
298
|
+
|
|
299
|
+
// 如果在包裹中或者没有遇到‘>’说明没有结束
|
|
300
|
+
while ((isAttrString || currentChar != '>') && i < template.length) {
|
|
301
|
+
|
|
302
|
+
tag += next();
|
|
303
|
+
|
|
304
|
+
// 如果是包裹里面,试探是否即将遇到了结束
|
|
305
|
+
if (isAttrString) {
|
|
306
|
+
|
|
307
|
+
let next23Value = nextNValue(attrLeftLen + 1).substring(1);
|
|
308
|
+
if (next23Value == attrLeftValue) {
|
|
309
|
+
isAttrString = false;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// 如果在包裹外面,试探是否即将进入包裹
|
|
315
|
+
else {
|
|
316
|
+
|
|
317
|
+
let next23Value = nextNValue(2);
|
|
318
|
+
if (next23Value == '="' || next23Value == "='") {
|
|
319
|
+
attrLeftValue = next23Value.replace('=', '');
|
|
320
|
+
attrLeftLen = 1;
|
|
321
|
+
isAttrString = true;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
next23Value = nextNValue(3);
|
|
325
|
+
if (next23Value == '=\"' || next23Value == "=\'") {
|
|
326
|
+
attrLeftValue = next23Value.replace('=', '');
|
|
327
|
+
attrLeftLen = 2;
|
|
328
|
+
isAttrString = true;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// 针对特殊的结束标签
|
|
337
|
+
if (/^<\//.test(tag)) {
|
|
338
|
+
tagObj.tagName = tag.replace(/^<\//, '').replace(/>$/, '');
|
|
339
|
+
tagObj.type = 'endTag';
|
|
340
|
+
} else {
|
|
341
|
+
|
|
342
|
+
if (/\/>$/.test(tag)) {
|
|
343
|
+
tagObj.type = 'fullTag';
|
|
344
|
+
tag = tag.replace(/\/>$/, '');
|
|
345
|
+
} else {
|
|
346
|
+
tagObj.type = 'beginTag';
|
|
347
|
+
tag = tag.replace(/>$/, '');
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
tag = tag.replace(/^</, '');
|
|
351
|
+
|
|
352
|
+
tagObj.tagName = "";
|
|
353
|
+
let j = 0;
|
|
354
|
+
for (; j < tag.length; j++) {
|
|
355
|
+
if (tag[j] == ' ') break;
|
|
356
|
+
tagObj.tagName += tag[j];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
let attrString = tag.substring(j);
|
|
360
|
+
if (/^[\x20\t\r\n\f]{0,}$/.test(attrString)) {
|
|
361
|
+
tagObj.attrs = {};
|
|
362
|
+
} else {
|
|
363
|
+
tagObj.attrs = analyseTag(attrString);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// 如果是归结文本结点
|
|
371
|
+
// 如果文本中包含<的先忽略考虑
|
|
372
|
+
else {
|
|
373
|
+
tagObj.type = 'textcode';
|
|
374
|
+
tagObj.tagName = currentChar;
|
|
375
|
+
while (nextNValue(1) != '<' && i < template.length) {
|
|
376
|
+
tagObj.tagName += next();
|
|
377
|
+
}
|
|
378
|
+
tagObj.tagName = tagObj.tagName.replace(/<$/, '');
|
|
379
|
+
i -= 1;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
// 如果遇到开始script或者style、pre等特殊标签,标记开始获取特殊文本
|
|
384
|
+
if (tagObj.type == 'beginTag') {
|
|
385
|
+
if (specialTag.indexOf(tagObj.tagName.toLowerCase()) > -1) {
|
|
386
|
+
preIsSpecial = true;
|
|
387
|
+
specialCode = tagObj.tagName;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// 如果遇到结束script或者style、pre等特殊标签,标记结束获取特殊文本
|
|
393
|
+
else if (tagObj.type == 'endTag') {
|
|
394
|
+
if (specialTag.indexOf(tagObj.tagName.toLowerCase()) > -1) {
|
|
395
|
+
preIsSpecial = false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
next();
|
|
400
|
+
|
|
401
|
+
return tagObj;
|
|
402
|
+
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
module.exports = function (source) {
|
|
408
|
+
// 获取读取下一个标签对象
|
|
409
|
+
let nextTag = nextTagFun("<root>" + source.trim() + "</root>");
|
|
410
|
+
|
|
411
|
+
let tag = nextTag(), DomTree = [];
|
|
412
|
+
while (tag != null) {
|
|
413
|
+
|
|
414
|
+
if (tag.type == 'textcode' && /^[\x20\t\r\n\f]{0,}$/.test(tag.tagName)) {
|
|
415
|
+
|
|
416
|
+
// 空白文本结点过滤掉
|
|
417
|
+
|
|
418
|
+
} else if (tag.type == 'DOCTYPE') {
|
|
419
|
+
|
|
420
|
+
// DOCTYPE过滤掉
|
|
421
|
+
|
|
422
|
+
} else if (tag.type == 'comment') {
|
|
423
|
+
|
|
424
|
+
// 注释过滤掉
|
|
425
|
+
|
|
426
|
+
} else {
|
|
427
|
+
tag.tagName = tag.tagName.trim();
|
|
428
|
+
DomTree.push(tag);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
tag = nextTag();
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// 分析层次
|
|
435
|
+
DomTree = analyseDeep(DomTree);
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* 模仿浏览器构建的一棵树,每个结点有如下属性:
|
|
439
|
+
*
|
|
440
|
+
* 1.parentNode index 父结点
|
|
441
|
+
* 2.childNodes [] 孩子结点
|
|
442
|
+
* 3.preNode index 前一个兄弟结点
|
|
443
|
+
* 4.nextNode index 后一个兄弟结点
|
|
444
|
+
*
|
|
445
|
+
* 5.attrs:{} 当前结点的属性
|
|
446
|
+
* 6.name 节点名称
|
|
447
|
+
* 7.type 节点类型(tag和text)
|
|
448
|
+
* 8.content 文本结点内容
|
|
449
|
+
*
|
|
450
|
+
* 需要注意的是:如果一个文本结点内容只包含回车,tab,空格等空白字符,会直接被忽视
|
|
451
|
+
*/
|
|
452
|
+
|
|
453
|
+
let presNode = [null], preDeep = 0;
|
|
454
|
+
for (let i = 0; i < DomTree.length; i++) {
|
|
455
|
+
|
|
456
|
+
// 当前结点
|
|
457
|
+
let currentIndex = i, currentDeep = DomTree[i].__deep__;
|
|
458
|
+
DomTree[i].childNodes = [];
|
|
459
|
+
DomTree[i].preNode = null;
|
|
460
|
+
DomTree[i].nextNode = null;
|
|
461
|
+
|
|
462
|
+
// 前置三个结点
|
|
463
|
+
let lastPre = presNode[presNode.length - 1];
|
|
464
|
+
let last2Pre = presNode.length > 1 ? presNode[presNode.length - 2] : null;
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
// 如果遇到的是兄弟结点
|
|
468
|
+
if (currentDeep == preDeep) {
|
|
469
|
+
|
|
470
|
+
// 修改兄弟关系
|
|
471
|
+
DomTree[currentIndex].preNode = lastPre;
|
|
472
|
+
DomTree[lastPre].nextNode = currentIndex;
|
|
473
|
+
|
|
474
|
+
// 修改父子关系
|
|
475
|
+
DomTree[currentIndex].parentNode = last2Pre;
|
|
476
|
+
DomTree[last2Pre].childNodes.push(currentIndex);
|
|
477
|
+
|
|
478
|
+
// 校对presNode
|
|
479
|
+
presNode[presNode.length - 1] = currentIndex;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// 如果是遇到了孩子
|
|
483
|
+
else if (currentDeep > preDeep) {
|
|
484
|
+
|
|
485
|
+
// 修改兄弟关系
|
|
486
|
+
// todo
|
|
487
|
+
|
|
488
|
+
// 修改父子关系
|
|
489
|
+
DomTree[currentIndex].parentNode = lastPre;
|
|
490
|
+
if (lastPre != null) DomTree[lastPre].childNodes.push(currentIndex);
|
|
491
|
+
|
|
492
|
+
// 校对presNode
|
|
493
|
+
presNode.push(currentIndex);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// 如果是遇到了祖先
|
|
497
|
+
else {
|
|
498
|
+
|
|
499
|
+
let preTempIndex = presNode[presNode.length - 1 - (preDeep - currentDeep)];
|
|
500
|
+
let preTemp2Index = presNode[presNode.length - 2 - (preDeep - currentDeep)];
|
|
501
|
+
|
|
502
|
+
// 修改兄弟关系
|
|
503
|
+
DomTree[currentIndex].preNode = preTempIndex;
|
|
504
|
+
if (preTempIndex != null) DomTree[preTempIndex].nextNode = currentIndex;
|
|
505
|
+
|
|
506
|
+
// 修改父子关系
|
|
507
|
+
DomTree[currentIndex].parentNode = preTemp2Index;
|
|
508
|
+
if (preTemp2Index != null) DomTree[preTemp2Index].childNodes.push(currentIndex);
|
|
509
|
+
|
|
510
|
+
// 校对presNode
|
|
511
|
+
for (let j = 0; j < preDeep - currentDeep; j++) { presNode.pop(); }
|
|
512
|
+
presNode[presNode.length - 1] = currentIndex;
|
|
513
|
+
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
preDeep = currentDeep;
|
|
517
|
+
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return DomTree;
|
|
521
521
|
};
|