plist 3.0.3 → 3.0.4

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.
@@ -0,0 +1,642 @@
1
+ //[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
2
+ //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
3
+ //[5] Name ::= NameStartChar (NameChar)*
4
+ var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
5
+ var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
6
+ var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
7
+ //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
8
+ //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
9
+
10
+ //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
11
+ //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
12
+ var S_TAG = 0;//tag name offerring
13
+ var S_ATTR = 1;//attr name offerring
14
+ var S_ATTR_SPACE=2;//attr name end and space offer
15
+ var S_EQ = 3;//=space?
16
+ var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
17
+ var S_ATTR_END = 5;//attr value end and no space(quot end)
18
+ var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
19
+ var S_TAG_CLOSE = 7;//closed el<el />
20
+
21
+ /**
22
+ * Creates an error that will not be caught by XMLReader aka the SAX parser.
23
+ *
24
+ * @param {string} message
25
+ * @param {any?} locator Optional, can provide details about the location in the source
26
+ * @constructor
27
+ */
28
+ function ParseError(message, locator) {
29
+ this.message = message
30
+ this.locator = locator
31
+ if(Error.captureStackTrace) Error.captureStackTrace(this, ParseError);
32
+ }
33
+ ParseError.prototype = new Error();
34
+ ParseError.prototype.name = ParseError.name
35
+
36
+ function XMLReader(){
37
+
38
+ }
39
+
40
+ XMLReader.prototype = {
41
+ parse:function(source,defaultNSMap,entityMap){
42
+ var domBuilder = this.domBuilder;
43
+ domBuilder.startDocument();
44
+ _copy(defaultNSMap ,defaultNSMap = {})
45
+ parse(source,defaultNSMap,entityMap,
46
+ domBuilder,this.errorHandler);
47
+ domBuilder.endDocument();
48
+ }
49
+ }
50
+ function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
51
+ function fixedFromCharCode(code) {
52
+ // String.prototype.fromCharCode does not supports
53
+ // > 2 bytes unicode chars directly
54
+ if (code > 0xffff) {
55
+ code -= 0x10000;
56
+ var surrogate1 = 0xd800 + (code >> 10)
57
+ , surrogate2 = 0xdc00 + (code & 0x3ff);
58
+
59
+ return String.fromCharCode(surrogate1, surrogate2);
60
+ } else {
61
+ return String.fromCharCode(code);
62
+ }
63
+ }
64
+ function entityReplacer(a){
65
+ var k = a.slice(1,-1);
66
+ if(k in entityMap){
67
+ return entityMap[k];
68
+ }else if(k.charAt(0) === '#'){
69
+ return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
70
+ }else{
71
+ errorHandler.error('entity not found:'+a);
72
+ return a;
73
+ }
74
+ }
75
+ function appendText(end){//has some bugs
76
+ if(end>start){
77
+ var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
78
+ locator&&position(start);
79
+ domBuilder.characters(xt,0,end-start);
80
+ start = end
81
+ }
82
+ }
83
+ function position(p,m){
84
+ while(p>=lineEnd && (m = linePattern.exec(source))){
85
+ lineStart = m.index;
86
+ lineEnd = lineStart + m[0].length;
87
+ locator.lineNumber++;
88
+ //console.log('line++:',locator,startPos,endPos)
89
+ }
90
+ locator.columnNumber = p-lineStart+1;
91
+ }
92
+ var lineStart = 0;
93
+ var lineEnd = 0;
94
+ var linePattern = /.*(?:\r\n?|\n)|.*$/g
95
+ var locator = domBuilder.locator;
96
+
97
+ var parseStack = [{currentNSMap:defaultNSMapCopy}]
98
+ var closeMap = {};
99
+ var start = 0;
100
+ while(true){
101
+ try{
102
+ var tagStart = source.indexOf('<',start);
103
+ if(tagStart<0){
104
+ if(!source.substr(start).match(/^\s*$/)){
105
+ var doc = domBuilder.doc;
106
+ var text = doc.createTextNode(source.substr(start));
107
+ doc.appendChild(text);
108
+ domBuilder.currentElement = text;
109
+ }
110
+ return;
111
+ }
112
+ if(tagStart>start){
113
+ appendText(tagStart);
114
+ }
115
+ switch(source.charAt(tagStart+1)){
116
+ case '/':
117
+ var end = source.indexOf('>',tagStart+3);
118
+ var tagName = source.substring(tagStart+2,end);
119
+ var config = parseStack.pop();
120
+ if(end<0){
121
+
122
+ tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
123
+ errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
124
+ end = tagStart+1+tagName.length;
125
+ }else if(tagName.match(/\s</)){
126
+ tagName = tagName.replace(/[\s<].*/,'');
127
+ errorHandler.error("end tag name: "+tagName+' maybe not complete');
128
+ end = tagStart+1+tagName.length;
129
+ }
130
+ var localNSMap = config.localNSMap;
131
+ var endMatch = config.tagName == tagName;
132
+ var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase()
133
+ if(endIgnoreCaseMach){
134
+ domBuilder.endElement(config.uri,config.localName,tagName);
135
+ if(localNSMap){
136
+ for(var prefix in localNSMap){
137
+ domBuilder.endPrefixMapping(prefix) ;
138
+ }
139
+ }
140
+ if(!endMatch){
141
+ errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName ); // No known test case
142
+ }
143
+ }else{
144
+ parseStack.push(config)
145
+ }
146
+
147
+ end++;
148
+ break;
149
+ // end elment
150
+ case '?':// <?...?>
151
+ locator&&position(tagStart);
152
+ end = parseInstruction(source,tagStart,domBuilder);
153
+ break;
154
+ case '!':// <!doctype,<![CDATA,<!--
155
+ locator&&position(tagStart);
156
+ end = parseDCC(source,tagStart,domBuilder,errorHandler);
157
+ break;
158
+ default:
159
+ locator&&position(tagStart);
160
+ var el = new ElementAttributes();
161
+ var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
162
+ //elStartEnd
163
+ var end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);
164
+ var len = el.length;
165
+
166
+
167
+ if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
168
+ el.closed = true;
169
+ if(!entityMap.nbsp){
170
+ errorHandler.warning('unclosed xml attribute');
171
+ }
172
+ }
173
+ if(locator && len){
174
+ var locator2 = copyLocator(locator,{});
175
+ //try{//attribute position fixed
176
+ for(var i = 0;i<len;i++){
177
+ var a = el[i];
178
+ position(a.offset);
179
+ a.locator = copyLocator(locator,{});
180
+ }
181
+ domBuilder.locator = locator2
182
+ if(appendElement(el,domBuilder,currentNSMap)){
183
+ parseStack.push(el)
184
+ }
185
+ domBuilder.locator = locator;
186
+ }else{
187
+ if(appendElement(el,domBuilder,currentNSMap)){
188
+ parseStack.push(el)
189
+ }
190
+ }
191
+
192
+
193
+
194
+ if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
195
+ end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)
196
+ }else{
197
+ end++;
198
+ }
199
+ }
200
+ }catch(e){
201
+ if (e instanceof ParseError) {
202
+ throw e;
203
+ }
204
+ errorHandler.error('element parse error: '+e)
205
+ end = -1;
206
+ }
207
+ if(end>start){
208
+ start = end;
209
+ }else{
210
+ //TODO: 这里有可能sax回退,有位置错误风险
211
+ appendText(Math.max(tagStart,start)+1);
212
+ }
213
+ }
214
+ }
215
+ function copyLocator(f,t){
216
+ t.lineNumber = f.lineNumber;
217
+ t.columnNumber = f.columnNumber;
218
+ return t;
219
+ }
220
+
221
+ /**
222
+ * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
223
+ * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
224
+ */
225
+ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
226
+
227
+ /**
228
+ * @param {string} qname
229
+ * @param {string} value
230
+ * @param {number} startIndex
231
+ */
232
+ function addAttribute(qname, value, startIndex) {
233
+ if (qname in el.attributeNames) errorHandler.fatalError('Attribute ' + qname + ' redefined')
234
+ el.addValue(qname, value, startIndex)
235
+ }
236
+ var attrName;
237
+ var value;
238
+ var p = ++start;
239
+ var s = S_TAG;//status
240
+ while(true){
241
+ var c = source.charAt(p);
242
+ switch(c){
243
+ case '=':
244
+ if(s === S_ATTR){//attrName
245
+ attrName = source.slice(start,p);
246
+ s = S_EQ;
247
+ }else if(s === S_ATTR_SPACE){
248
+ s = S_EQ;
249
+ }else{
250
+ //fatalError: equal must after attrName or space after attrName
251
+ throw new Error('attribute equal must after attrName'); // No known test case
252
+ }
253
+ break;
254
+ case '\'':
255
+ case '"':
256
+ if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
257
+ ){//equal
258
+ if(s === S_ATTR){
259
+ errorHandler.warning('attribute value must after "="')
260
+ attrName = source.slice(start,p)
261
+ }
262
+ start = p+1;
263
+ p = source.indexOf(c,start)
264
+ if(p>0){
265
+ value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
266
+ addAttribute(attrName, value, start-1);
267
+ s = S_ATTR_END;
268
+ }else{
269
+ //fatalError: no end quot match
270
+ throw new Error('attribute value no end \''+c+'\' match');
271
+ }
272
+ }else if(s == S_ATTR_NOQUOT_VALUE){
273
+ value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
274
+ //console.log(attrName,value,start,p)
275
+ addAttribute(attrName, value, start);
276
+ //console.dir(el)
277
+ errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
278
+ start = p+1;
279
+ s = S_ATTR_END
280
+ }else{
281
+ //fatalError: no equal before
282
+ throw new Error('attribute value must after "="'); // No known test case
283
+ }
284
+ break;
285
+ case '/':
286
+ switch(s){
287
+ case S_TAG:
288
+ el.setTagName(source.slice(start,p));
289
+ case S_ATTR_END:
290
+ case S_TAG_SPACE:
291
+ case S_TAG_CLOSE:
292
+ s =S_TAG_CLOSE;
293
+ el.closed = true;
294
+ case S_ATTR_NOQUOT_VALUE:
295
+ case S_ATTR:
296
+ case S_ATTR_SPACE:
297
+ break;
298
+ //case S_EQ:
299
+ default:
300
+ throw new Error("attribute invalid close char('/')") // No known test case
301
+ }
302
+ break;
303
+ case ''://end document
304
+ errorHandler.error('unexpected end of input');
305
+ if(s == S_TAG){
306
+ el.setTagName(source.slice(start,p));
307
+ }
308
+ return p;
309
+ case '>':
310
+ switch(s){
311
+ case S_TAG:
312
+ el.setTagName(source.slice(start,p));
313
+ case S_ATTR_END:
314
+ case S_TAG_SPACE:
315
+ case S_TAG_CLOSE:
316
+ break;//normal
317
+ case S_ATTR_NOQUOT_VALUE://Compatible state
318
+ case S_ATTR:
319
+ value = source.slice(start,p);
320
+ if(value.slice(-1) === '/'){
321
+ el.closed = true;
322
+ value = value.slice(0,-1)
323
+ }
324
+ case S_ATTR_SPACE:
325
+ if(s === S_ATTR_SPACE){
326
+ value = attrName;
327
+ }
328
+ if(s == S_ATTR_NOQUOT_VALUE){
329
+ errorHandler.warning('attribute "'+value+'" missed quot(")!');
330
+ addAttribute(attrName, value.replace(/&#?\w+;/g,entityReplacer), start)
331
+ }else{
332
+ if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
333
+ errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
334
+ }
335
+ addAttribute(value, value, start)
336
+ }
337
+ break;
338
+ case S_EQ:
339
+ throw new Error('attribute value missed!!');
340
+ }
341
+ // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
342
+ return p;
343
+ /*xml space '\x20' | #x9 | #xD | #xA; */
344
+ case '\u0080':
345
+ c = ' ';
346
+ default:
347
+ if(c<= ' '){//space
348
+ switch(s){
349
+ case S_TAG:
350
+ el.setTagName(source.slice(start,p));//tagName
351
+ s = S_TAG_SPACE;
352
+ break;
353
+ case S_ATTR:
354
+ attrName = source.slice(start,p)
355
+ s = S_ATTR_SPACE;
356
+ break;
357
+ case S_ATTR_NOQUOT_VALUE:
358
+ var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
359
+ errorHandler.warning('attribute "'+value+'" missed quot(")!!');
360
+ addAttribute(attrName, value, start)
361
+ case S_ATTR_END:
362
+ s = S_TAG_SPACE;
363
+ break;
364
+ //case S_TAG_SPACE:
365
+ //case S_EQ:
366
+ //case S_ATTR_SPACE:
367
+ // void();break;
368
+ //case S_TAG_CLOSE:
369
+ //ignore warning
370
+ }
371
+ }else{//not space
372
+ //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
373
+ //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
374
+ switch(s){
375
+ //case S_TAG:void();break;
376
+ //case S_ATTR:void();break;
377
+ //case S_ATTR_NOQUOT_VALUE:void();break;
378
+ case S_ATTR_SPACE:
379
+ var tagName = el.tagName;
380
+ if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){
381
+ errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!')
382
+ }
383
+ addAttribute(attrName, attrName, start);
384
+ start = p;
385
+ s = S_ATTR;
386
+ break;
387
+ case S_ATTR_END:
388
+ errorHandler.warning('attribute space is required"'+attrName+'"!!')
389
+ case S_TAG_SPACE:
390
+ s = S_ATTR;
391
+ start = p;
392
+ break;
393
+ case S_EQ:
394
+ s = S_ATTR_NOQUOT_VALUE;
395
+ start = p;
396
+ break;
397
+ case S_TAG_CLOSE:
398
+ throw new Error("elements closed character '/' and '>' must be connected to");
399
+ }
400
+ }
401
+ }//end outer switch
402
+ //console.log('p++',p)
403
+ p++;
404
+ }
405
+ }
406
+ /**
407
+ * @return true if has new namespace define
408
+ */
409
+ function appendElement(el,domBuilder,currentNSMap){
410
+ var tagName = el.tagName;
411
+ var localNSMap = null;
412
+ //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
413
+ var i = el.length;
414
+ while(i--){
415
+ var a = el[i];
416
+ var qName = a.qName;
417
+ var value = a.value;
418
+ var nsp = qName.indexOf(':');
419
+ if(nsp>0){
420
+ var prefix = a.prefix = qName.slice(0,nsp);
421
+ var localName = qName.slice(nsp+1);
422
+ var nsPrefix = prefix === 'xmlns' && localName
423
+ }else{
424
+ localName = qName;
425
+ prefix = null
426
+ nsPrefix = qName === 'xmlns' && ''
427
+ }
428
+ //can not set prefix,because prefix !== ''
429
+ a.localName = localName ;
430
+ //prefix == null for no ns prefix attribute
431
+ if(nsPrefix !== false){//hack!!
432
+ if(localNSMap == null){
433
+ localNSMap = {}
434
+ //console.log(currentNSMap,0)
435
+ _copy(currentNSMap,currentNSMap={})
436
+ //console.log(currentNSMap,1)
437
+ }
438
+ currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
439
+ a.uri = 'http://www.w3.org/2000/xmlns/'
440
+ domBuilder.startPrefixMapping(nsPrefix, value)
441
+ }
442
+ }
443
+ var i = el.length;
444
+ while(i--){
445
+ a = el[i];
446
+ var prefix = a.prefix;
447
+ if(prefix){//no prefix attribute has no namespace
448
+ if(prefix === 'xml'){
449
+ a.uri = 'http://www.w3.org/XML/1998/namespace';
450
+ }if(prefix !== 'xmlns'){
451
+ a.uri = currentNSMap[prefix || '']
452
+
453
+ //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
454
+ }
455
+ }
456
+ }
457
+ var nsp = tagName.indexOf(':');
458
+ if(nsp>0){
459
+ prefix = el.prefix = tagName.slice(0,nsp);
460
+ localName = el.localName = tagName.slice(nsp+1);
461
+ }else{
462
+ prefix = null;//important!!
463
+ localName = el.localName = tagName;
464
+ }
465
+ //no prefix element has default namespace
466
+ var ns = el.uri = currentNSMap[prefix || ''];
467
+ domBuilder.startElement(ns,localName,tagName,el);
468
+ //endPrefixMapping and startPrefixMapping have not any help for dom builder
469
+ //localNSMap = null
470
+ if(el.closed){
471
+ domBuilder.endElement(ns,localName,tagName);
472
+ if(localNSMap){
473
+ for(prefix in localNSMap){
474
+ domBuilder.endPrefixMapping(prefix)
475
+ }
476
+ }
477
+ }else{
478
+ el.currentNSMap = currentNSMap;
479
+ el.localNSMap = localNSMap;
480
+ //parseStack.push(el);
481
+ return true;
482
+ }
483
+ }
484
+ function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
485
+ if(/^(?:script|textarea)$/i.test(tagName)){
486
+ var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
487
+ var text = source.substring(elStartEnd+1,elEndStart);
488
+ if(/[&<]/.test(text)){
489
+ if(/^script$/i.test(tagName)){
490
+ //if(!/\]\]>/.test(text)){
491
+ //lexHandler.startCDATA();
492
+ domBuilder.characters(text,0,text.length);
493
+ //lexHandler.endCDATA();
494
+ return elEndStart;
495
+ //}
496
+ }//}else{//text area
497
+ text = text.replace(/&#?\w+;/g,entityReplacer);
498
+ domBuilder.characters(text,0,text.length);
499
+ return elEndStart;
500
+ //}
501
+
502
+ }
503
+ }
504
+ return elStartEnd+1;
505
+ }
506
+ function fixSelfClosed(source,elStartEnd,tagName,closeMap){
507
+ //if(tagName in closeMap){
508
+ var pos = closeMap[tagName];
509
+ if(pos == null){
510
+ //console.log(tagName)
511
+ pos = source.lastIndexOf('</'+tagName+'>')
512
+ if(pos<elStartEnd){//忘记闭合
513
+ pos = source.lastIndexOf('</'+tagName)
514
+ }
515
+ closeMap[tagName] =pos
516
+ }
517
+ return pos<elStartEnd;
518
+ //}
519
+ }
520
+ function _copy(source,target){
521
+ for(var n in source){target[n] = source[n]}
522
+ }
523
+ function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
524
+ var next= source.charAt(start+2)
525
+ switch(next){
526
+ case '-':
527
+ if(source.charAt(start + 3) === '-'){
528
+ var end = source.indexOf('-->',start+4);
529
+ //append comment source.substring(4,end)//<!--
530
+ if(end>start){
531
+ domBuilder.comment(source,start+4,end-start-4);
532
+ return end+3;
533
+ }else{
534
+ errorHandler.error("Unclosed comment");
535
+ return -1;
536
+ }
537
+ }else{
538
+ //error
539
+ return -1;
540
+ }
541
+ default:
542
+ if(source.substr(start+3,6) == 'CDATA['){
543
+ var end = source.indexOf(']]>',start+9);
544
+ domBuilder.startCDATA();
545
+ domBuilder.characters(source,start+9,end-start-9);
546
+ domBuilder.endCDATA()
547
+ return end+3;
548
+ }
549
+ //<!DOCTYPE
550
+ //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
551
+ var matchs = split(source,start);
552
+ var len = matchs.length;
553
+ if(len>1 && /!doctype/i.test(matchs[0][0])){
554
+ var name = matchs[1][0];
555
+ var pubid = false;
556
+ var sysid = false;
557
+ if(len>3){
558
+ if(/^public$/i.test(matchs[2][0])){
559
+ pubid = matchs[3][0];
560
+ sysid = len>4 && matchs[4][0];
561
+ }else if(/^system$/i.test(matchs[2][0])){
562
+ sysid = matchs[3][0];
563
+ }
564
+ }
565
+ var lastMatch = matchs[len-1]
566
+ domBuilder.startDTD(name, pubid, sysid);
567
+ domBuilder.endDTD();
568
+
569
+ return lastMatch.index+lastMatch[0].length
570
+ }
571
+ }
572
+ return -1;
573
+ }
574
+
575
+
576
+
577
+ function parseInstruction(source,start,domBuilder){
578
+ var end = source.indexOf('?>',start);
579
+ if(end){
580
+ var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
581
+ if(match){
582
+ var len = match[0].length;
583
+ domBuilder.processingInstruction(match[1], match[2]) ;
584
+ return end+2;
585
+ }else{//error
586
+ return -1;
587
+ }
588
+ }
589
+ return -1;
590
+ }
591
+
592
+ function ElementAttributes(){
593
+ this.attributeNames = {}
594
+ }
595
+ ElementAttributes.prototype = {
596
+ setTagName:function(tagName){
597
+ if(!tagNamePattern.test(tagName)){
598
+ throw new Error('invalid tagName:'+tagName)
599
+ }
600
+ this.tagName = tagName
601
+ },
602
+ addValue:function(qName, value, offset) {
603
+ if(!tagNamePattern.test(qName)){
604
+ throw new Error('invalid attribute:'+qName)
605
+ }
606
+ this.attributeNames[qName] = this.length;
607
+ this[this.length++] = {qName:qName,value:value,offset:offset}
608
+ },
609
+ length:0,
610
+ getLocalName:function(i){return this[i].localName},
611
+ getLocator:function(i){return this[i].locator},
612
+ getQName:function(i){return this[i].qName},
613
+ getURI:function(i){return this[i].uri},
614
+ getValue:function(i){return this[i].value}
615
+ // ,getIndex:function(uri, localName)){
616
+ // if(localName){
617
+ //
618
+ // }else{
619
+ // var qName = uri
620
+ // }
621
+ // },
622
+ // getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
623
+ // getType:function(uri,localName){}
624
+ // getType:function(i){},
625
+ }
626
+
627
+
628
+
629
+ function split(source,start){
630
+ var match;
631
+ var buf = [];
632
+ var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
633
+ reg.lastIndex = start;
634
+ reg.exec(source);//skip <
635
+ while(match = reg.exec(source)){
636
+ buf.push(match);
637
+ if(match[1])return buf;
638
+ }
639
+ }
640
+
641
+ exports.XMLReader = XMLReader;
642
+ exports.ParseError = ParseError;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "plist",
3
3
  "description": "Mac OS X Plist parser/builder for Node.js and browsers",
4
- "version": "3.0.3",
4
+ "version": "3.0.4",
5
5
  "author": "Nathan Rajlich <nathan@tootallnate.net>",
6
6
  "contributors": [
7
7
  "Hans Huebner <hans.huebner@gmail.com>",
@@ -26,8 +26,7 @@
26
26
  "main": "index.js",
27
27
  "dependencies": {
28
28
  "base64-js": "^1.5.1",
29
- "xmlbuilder": "^9.0.7",
30
- "xmldom": "^0.6.0"
29
+ "xmlbuilder": "^9.0.7"
31
30
  },
32
31
  "devDependencies": {
33
32
  "browserify": "^16.5.2",