Permalink
Browse files

Add module enml-js

  • Loading branch information...
1 parent d1325f6 commit 42d3321d277100534df511c6f2a531ffe7c13c84 @wanasit committed Jan 25, 2013
View
14 node_modules/enml-js/README.md
@@ -0,0 +1,14 @@
+enml-js
+===========
+
+[Evernote's ENML](http://dev.evernote.com/documentation/cloud/chapters/ENML.php) library in Javascript.
+
+
+Functions
+============
+
+* **enml.ENMLOfPlainText**(String) - Encode plain text in ENML format.
+
+
+* **enml.HTMLOfENML**(String, [ Map <String, URL> ]) - Translate ENML to HTML for viewing in browsers. Showing images you have to provide a map of images' hash and their src url.
+
View
212 node_modules/enml-js/enml.js
@@ -0,0 +1,212 @@
+(function() {
+
+ /**
+ * URLOfResource
+ * Create URL of the resource on Evernote's server
+ * @param { string } guid - the resource's guid
+ * @param { string } shardId - shard id of the resource owner
+ * @return string - URL
+ */
+ function URLOfResource(guid, shardId){
+ return 'https://www.evernote.com/shard/'+shardId+'/res/'+guid;
+ }
+
+ /**
+ * enmlHashToBodyHash
+ * 'bodyHash' returned from Evernote API is not equal to 'enmlHash' (hash string in the notes' content).
+ * 'enmlHash' is 'bodyHash' in ascii-hex form
+ * @param { string } enmlHash - (Hash string in notes' content)
+ * @return string - bodyHash (Binary hash in Evernote API)
+ */
+ function BodyHashOfENMLHash(enmlHash){
+
+ var buffer = [];
+ for(var i =0 ; i<enmlHash.length; i += 2)
+ buffer.push( parseInt(enmlHash[i],16)*16 + parseInt(enmlHash[i+1],16));
+
+ var bodyHash = '';
+ for(var i =0 ; i<buffer.length; i ++){
+ if(buffer[i] >= 128)
+ bodyHash += String.fromCharCode(65533);
+ else
+ bodyHash += String.fromCharCode(buffer[i]);
+ }
+
+ return bodyHash;
+ }
+
+ /**
+ * ENMLOfPlainText
+ * @param { string } text (Plain)
+ * @return string - ENML
+ */
+ function ENMLOfPlainText(text){
+
+ var writer = new XMLWriter;
+
+ writer.startDocument = writer.startDocument || writer.writeStartDocument;
+ writer.endDocument = writer.endDocument || writer.writeEndDocument;
+ writer.startDocument = writer.startElement || writer.writeStartElement;
+ writer.startDocument = writer.endElement || writer.writeEndElement;
+
+ writer.startDocument('1.0', 'UTF-8', false);
+ writer.write('<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">');
+ writer.write("\n")
+ writer.startElement('en-note');
+ writer.writeAttribute('style', 'word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;');
+
+ var lines = text.match(/^.*((\r\n|\n|\r)|$)/gm);
+
+ lines.forEach(function(line) {
+ writer.startElement('div');
+ writer.text(line.replace(/(\r\n|\n|\r)/,''));
+ writer.endElement();
+
+ writer.text("\n")
+ });
+
+ writer.endElement();
+ writer.endDocument();
+
+ return writer.toString();
+ }
+
+ /**
+ * PlainTextOfENML
+ * @param { string } text (ENML)
+ * @return string - text
+ */
+ function PlainTextOfENML(enml){
+
+ var text = enml || '';
+ text = text.replace(/(<\/(div|ui|li)>)/ig,"\n");
+ text = text.replace(/(<(li)>)/ig," - ");
+ text = text.replace(/(<([^>]+)>)/ig,"");
+ text = text.replace(/(\r\n|\n|\r)/gm," ");
+ text = text.replace(/(\s+)/gm," ");
+
+ return text;
+ }
+
+ /**
+ * HTMLOfENML
+ * Convert ENML into HTML for showing in web browsers.
+ *
+ * @param { string } text (ENML)
+ * @param { string } shard ( shardId )
+ * @param { Map <string (hash), string (url) >, Optional } resources
+ * @return string - HTML
+ */
+ function HTMLOfENML(text, resources){
+
+ resources = resources || {};
+ var writer = new XMLWriter;
+
+ var parser = new SaxParser(function(cb) {
+
+ cb.onStartElementNS(function(elem, attrs, prefix, uri, namespaces) {
+
+ if(elem == 'en-note'){
+ writer.startElement('html');
+ writer.startElement('head');
+
+ writer.startElement('meta');
+ writer.writeAttribute('http-equiv', 'Content-Type');
+ writer.writeAttribute('content', 'text/html; charset=UTF-8');
+ writer.endElement();
+
+ writer.endElement();
+
+ writer.startElement('body');
+ writer.writeAttribute('style', 'word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;');
+ } else if(elem == 'en-todo'){
+
+ writer.startElement('input');
+ writer.writeAttribute('type', 'checkbox');
+
+ } else if(elem == 'en-media'){
+
+ var type = null;
+ var hash = null;
+ var width = 0;
+ var height = 0;
+
+ if(attrs) attrs.forEach(function(attr) {
+ if(attr[0] == 'type') type = attr[1];
+ if(attr[0] == 'hash') hash = attr[1];
+ if(attr[0] == 'width') width = attr[1];
+ if(attr[0] == 'height') height = attr[1];
+ });
+
+ if(!type.match('image')) return;
+ writer.startElement('img');
+
+ hash = BodyHashOfENMLHash(hash);
+ var resource = resources[hash];
+
+ if(resource) {
+ writer.writeAttribute('src', resource);
+ }
+
+ if(width) writer.writeAttribute('width', width);
+ if(height) writer.writeAttribute('height', height);
+
+ } else {
+ writer.startElement(elem);
+ }
+
+ if(attrs) attrs.forEach(function(attr) {
+ writer.writeAttribute(attr[0], attr[1]);
+ });
+ });
+ cb.onEndElementNS(function(elem, prefix, uri) {
+
+ if(elem == 'en-note'){
+ writer.endElement(); //body
+ writer.endElement(); //html
+ }
+ else if(elem == 'en-todo'){
+
+ }
+ else if(elem == 'en-media'){
+
+ }else{
+
+ writer.endElement();
+ }
+ });
+ cb.onCharacters(function(chars) {
+ writer.text(chars);
+ });
+
+ });
+
+ parser.parseString(text);
+ return writer.toString();
+ }
+
+ if(typeof exports == 'undefined'){
+
+ var XMLWriter = window.XMLWriter;
+ var SaxParser = window.SaxParser;
+
+ //Browser Code
+ window.enml = {};
+ window.enml.URLOfResource = URLOfResource;
+ window.enml.ENMLOfPlainText = ENMLOfPlainText;
+ window.enml.HTMLOfENML = HTMLOfENML;
+ window.enml.PlainTextOfENML = PlainTextOfENML;
+ }
+ else{
+
+ //Node JS
+ var XMLWriter = require('./lib/xml-writer');
+ var SaxParser = require('./lib/xml-parser').SaxParser;
+
+ exports.URLOfResource = URLOfResource;
+ exports.ENMLOfPlainText = ENMLOfPlainText;
+ exports.HTMLOfENML = HTMLOfENML;
+ exports.PlainTextOfENML = PlainTextOfENML;
+ }
+
+})()
View
106 node_modules/enml-js/examples/browser/example.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>ENML Example</title>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
+
+ <script type="text/javascript" src="../../lib/xml-parser.js"></script>
+ <script type="text/javascript" src="../../lib/xml-writer.js"></script>
+ <script type="text/javascript" src="../../enml.js"></script>
+
+
+ <script type="text/javascript">
+
+ $(function() {
+
+ $.get('../ex0.txt', function(text0) {
+ var enml0 = enml.ENMLOfPlainText(text0);
+ var elem = $('#test0');
+
+ console.log("================ Example 0 (TEXT) ================")
+ console.log(text0)
+ elem.find('.src').html(text0);
+
+ console.log("================ Example 0 (ENML) ================")
+ console.log(enml0)
+ elem.find('.dst').html(enml0);
+ })
+
+ $.get('../ex1.enml', function(enml1) {
+ var html1 = enml.HTMLOfENML(enml1);
+ var text1 = enml.PlainTextOfENML(enml1);
+ var elem = $('#test1');
+
+ console.log("================ Example 1 (TEXT) ================")
+ console.log(html1)
+ elem.find('.src').html(html1);
+
+ console.log("================ Example 1 (ENML) ================")
+ console.log(enml1)
+ elem.find('.dst').html(html1);
+
+
+ console.log(text1)
+
+ },'text')
+
+ $.get('../note2.json', function(note2) {
+
+ var shardId = '48' //HARDCODE...
+ note2 = JSON.parse(note2);
+
+ var resources = {};
+ for(var i in note2.resources){
+ var resource = note2.resources[i];
+ resources[resource.data.bodyHash] = enml.URLOfResource(resource.guid, shardId);
+ }
+
+ var html2 = enml.HTMLOfENML(note2.content, resources);
+ var text2 = enml.PlainTextOfENML(note2.content, resources);
+ var elem = $('#test2');
+
+ console.log("================ Example 2 (ENML) ================")
+ console.log(note2.content)
+ elem.find('.src').html(note2.content);
+
+ console.log("================ Example 2 (HTML) ================")
+ console.log(html2)
+ elem.find('.dst').html(html2);
+
+
+ console.log(text2)
+ })
+
+
+ })
+
+
+
+
+
+
+ </script>
+
+</head>
+<body>
+ <div class="testcase" id="test0">
+ <h1 id="qunit-header">Test 0</h1>
+ <div class="src"></div>
+ <div class="dst"></div>
+ </div>
+
+ <div class="testcase" id="test1">
+ <h1 id="qunit-header">Test 1</h1>
+ <div class="src"></div>
+ <div class="dst"></div>
+ </div>
+
+ <div class="testcase" id="test2">
+ <h1 id="qunit-header">Test 2</h1>
+ <div class="src"></div>
+ <div class="dst"></div>
+ </div>
+
+</body>
+</html>
View
7 node_modules/enml-js/examples/ex0.txt
@@ -0,0 +1,7 @@
+Hickory, dickory, dock,
+The mouse ran up the clock.
+The clock struck one,
+The mouse ran down,
+Hickory, dickory, dock.
+
+-- Author unknown
View
11 node_modules/enml-js/examples/ex1.enml
@@ -0,0 +1,11 @@
+<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
+<en-note><div style="font-family:sans-serif;font-size:1em;"><div style="font-family:sans-serif;font-size:1em;background-color:rgb(243, 243, 243);background-image:url(http://bits.wikimedia.org/en.wikipedia.org/data:image/png;"><div style="background-image:url(http://bits.wikimedia.org/en.wikipedia.org/data:image/png;background-color:white;color:black;direction:ltr;background-position:0% 0%;background-repeat:no-repeat repeat;line-height:1.5em;-webkit-transition:margin-left 250ms, padding 250ms;"><div style="font-size:0.8em;line-height:1.5em;"><div dir="ltr" lang="en" style="direction:ltr;"><p style="margin:0.4em 0px 0.5em;line-height:1.5em;"><b>The Crazy Ones</b></p>
+<dl style="margin-top:0.2em;margin-bottom:0.5em;"><dt style="font-weight:bold;margin-bottom:0.1em;">Original</dt></dl>
+<table style="font-size:100%;margin:auto;border-collapse:collapse;border:none;background-color:transparent;width:auto;"><tr><td colspan="1" rowspan="1" valign="top" width="20" style="border:none;color:#B2B7F2;font-size:35px;font-family:'Times New Roman', serif;font-weight:bold;text-align:left;padding:10px 10px;">“</td><td colspan="1" rowspan="1" valign="top" style="border:none;padding:4px 10px;">
+<p style="margin:0.4em 0px 0.5em;line-height:1.5em;">Here’s to the crazy ones. The misfits. The rebels. The troublemakers. The round pegs in the square holes.</p>
+<p style="margin:0.4em 0px 0.5em;line-height:1.5em;">The ones who see things differently. They’re not fond of rules. And they have no respect for the status quo. You can quote them, disagree with them, glorify or vilify them.</p>
+<p style="margin:0.4em 0px 0.5em;line-height:1.5em;">About the only thing you can’t do is ignore them. Because they change things. They invent. They imagine. They heal. They explore. They create. They inspire. They push the human race forward.</p>
+<p style="margin:0.4em 0px 0.5em;line-height:1.5em;">Maybe they have to be crazy.</p>
+<p style="margin:0.4em 0px 0.5em;line-height:1.5em;">How else can you stare at an empty canvas and see a work of art? Or sit in silence and hear a song that’s never been written? Or gaze at a red planet and see a laboratory on wheels?</p>
+<p style="margin:0.4em 0px 0.5em;line-height:1.5em;">We make tools for these kinds of people.</p>
+<p style="margin:0.4em 0px 0.5em;line-height:1.5em;">While some see them as the crazy ones, we see genius. Because the people who are crazy enough to think they can change the world, are the ones who do.</p></td></tr></table></div></div></div></div></div></en-note>
View
66 node_modules/enml-js/examples/node-js/example.js
@@ -0,0 +1,66 @@
+
+var fs = require('fs');
+var util = require('util');
+
+
+var enml = require('../../enml');
+
+
+var text0 = fs.readFileSync('../ex0.txt','utf8');
+var enml0 = enml.ENMLOfPlainText(text0);
+
+console.log("================ Example 0 (TEXT) ================")
+console.log(text0)
+
+console.log("================ Example 0 (ENML) ================")
+console.log(enml0)
+
+
+var enml1 = fs.readFileSync('../ex1.enml','utf8');
+var html1 = enml.HTMLOfENML(enml1);
+var text1 = enml.PlainTextOfENML(enml1);
+
+console.log("================ Example 1 (ENML) ================")
+console.log(enml1)
+
+console.log("================ Example 1 (HTML) ================")
+console.log(html1)
+
+console.log("================ Example 1 (TEXT) ================")
+console.log(text1)
+
+var note2 = fs.readFileSync('../note2.json','utf8');
+var shardId = '48' //HARDCODE...
+note2 = JSON.parse(note2);
+
+var resources = {};
+for(var i in note2.resources){
+ var resource = note2.resources[i];
+
+ var hash = ''
+ for(var i=0;i<resource.data.bodyHash.length;i++){
+
+ if(resource.data.bodyHash.charCodeAt(i) < 128 || resource.data.bodyHash.charCodeAt(i) == 65533 )
+ hash += resource.data.bodyHash.charAt(i)
+ else
+ hash += String.fromCharCode(65533) + String.fromCharCode(65533);
+ }
+
+ console.log(hash)
+ resources[hash] = enml.URLOfResource(resource.guid, shardId);
+}
+
+var html2 = enml.HTMLOfENML(note2.content, resources);
+var text2 = enml.PlainTextOfENML(note2.content);
+
+console.log("================ Example 2 (ENML) ================")
+console.log(note2.content)
+
+console.log("================ Example 2 (HTML) ================")
+console.log(html2)
+
+console.log("================ Example 2 (TEXT) ================")
+console.log(text2)
+
+
+
View
1 node_modules/enml-js/examples/note2.json
@@ -0,0 +1 @@
+{"guid":"9fb0abe9-6627-4e86-8e74-055b34137b4d","title":"Hi there","content":"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n<en-note style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;\">\n<span><en-media type=\"image/png\" hash=\"4914ced8925f9adcc1c58ab87813c81f\"/></span>\n</en-note>\n","contentHash":"�\u0003���m�\u0012jbd�\u0006\u001aڈ","contentLength":320,"created":1356611678000,"updated":1356611700000,"deleted":null,"active":true,"updateSequenceNum":21302,"notebookGuid":"84783338-b32b-495a-a7f4-6f62eea45426","tagGuids":null,"resources":[{"guid":"fd20dbc8-7628-4e7d-a8ae-5e24b6524e21","noteGuid":"9fb0abe9-6627-4e86-8e74-055b34137b4d","data":{"bodyHash":"I\u0014�ؒ_���Ŋ�x\u0013�\u001f","size":2176,"body":null},"mime":"image/png","width":215,"height":54,"duration":null,"active":true,"recognition":{"bodyHash":"�X�Q��\u00153\u0002�ۖRh\u0010�","size":411,"body":null},"attributes":{"sourceURL":null,"timestamp":null,"latitude":null,"longitude":null,"altitude":null,"cameraMake":null,"cameraModel":null,"clientWillIndex":null,"recoType":null,"fileName":"88391522-4fe7-11e2-8e31-a34ebd4d0192.png","attachment":null},"updateSequenceNum":21303,"alternateData":null}],"attributes":{"subjectDate":null,"latitude":null,"longitude":null,"altitude":null,"author":"Wanasit Tanakitrungruang","source":null,"sourceURL":null,"sourceApplication":null,"shareDate":null},"tagNames":null}
View
62 node_modules/enml-js/examples/note3.json
@@ -0,0 +1,62 @@
+{
+ "guid": "4fa776ce-be89-4715-8b78-13c687fb62be",
+ "title": "無標題",
+ "content": "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/></head><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;\"><div>\n<div><br clear=\"none\"/></div>\n<div>\n<div><en-media alt=\"Evernote Logo\" hash=\"4914ced8925f9adcc1c58ab87813c81f\" type=\"image/png\"/>\n<h1> </h1>\n</div>\n</div>\n</div></body></html>",
+ "contentHash": "l\u000b�T#���\u0003\fH\u001b��a�",
+ "contentLength": 301,
+ "created": 1356396242000,
+ "updated": 1356400484000,
+ "deleted": null,
+ "active": true,
+ "updateSequenceNum": 85,
+ "notebookGuid": "a69f2542-0630-439f-ae75-2c115e9b9146",
+ "tagGuids": null,
+ "resources": [
+ {
+ "guid": "697af336-7530-4de7-ab70-e253afb650c0",
+ "noteGuid": "4fa776ce-be89-4715-8b78-13c687fb62be",
+ "data": {
+ "bodyHash": "I\u0014�ؒ_���Ŋ�x\u0013\u001f",
+ "size": 2176,
+ "body": null
+ },
+ "mime": "image/png",
+ "width": 215,
+ "height": 54,
+ "duration": null,
+ "active": true,
+ "recognition": {
+ "bodyHash": "�X�Q��\u00153\u0002�ۖRh\u0010",
+ "size": 411,
+ "body": null
+ },
+ "attributes": {
+ "sourceURL": null,
+ "timestamp": null,
+ "latitude": null,
+ "longitude": null,
+ "altitude": null,
+ "cameraMake": null,
+ "cameraModel": null,
+ "clientWillIndex": null,
+ "recoType": null,
+ "fileName": null,
+ "attachment": null
+ },
+ "updateSequenceNum": 86,
+ "alternateData": null
+ }
+ ],
+ "attributes": {
+ "subjectDate": null,
+ "latitude": null,
+ "longitude": null,
+ "altitude": null,
+ "author": null,
+ "source": null,
+ "sourceURL": null,
+ "sourceApplication": null,
+ "shareDate": null
+ },
+ "tagNames": null
+}
View
1,245 node_modules/enml-js/lib/xml-parser.js
@@ -0,0 +1,1245 @@
+// node-xml
+// An xml parser for node.js
+// (C) Rob Righter (@robrighter) 2009 - 2010, Licensed under the MIT-LICENSE
+// Contributions from David Joham
+
+
+(function () {
+
+// CONSTANTS
+var whitespace = "\n\r\t ";
+
+
+//XMLP is a pull-based parser. The calling application passes in a XML string
+//to the constructor, then repeatedly calls .next() to parse the next segment.
+//.next() returns a flag indicating what type of segment was found, and stores
+//data temporarily in couple member variables (name, content, array of
+//attributes), which can be accessed by several .get____() methods.
+//
+//Basically, XMLP is the lowest common denominator parser - an very simple
+//API which other wrappers can be built against.
+
+
+var XMLP = function(strXML) {
+ // Normalize line breaks
+ strXML = SAXStrings.replace(strXML, null, null, "\r\n", "\n");
+ strXML = SAXStrings.replace(strXML, null, null, "\r", "\n");
+
+ this.m_xml = strXML;
+ this.m_iP = 0;
+ this.m_iState = XMLP._STATE_PROLOG;
+ this.m_stack = new Stack();
+ this._clearAttributes();
+ this.m_pause = false;
+ this.m_preInterruptIState = XMLP._STATE_PROLOG;
+ this.m_namespaceList = new Array();
+ this.m_chunkTransitionContinuation = null;
+
+}
+
+
+// CONSTANTS (these must be below the constructor)
+XMLP._NONE = 0;
+XMLP._ELM_B = 1;
+XMLP._ELM_E = 2;
+XMLP._ELM_EMP = 3;
+XMLP._ATT = 4;
+XMLP._TEXT = 5;
+XMLP._ENTITY = 6;
+XMLP._PI = 7;
+XMLP._CDATA = 8;
+XMLP._COMMENT = 9;
+XMLP._DTD = 10;
+XMLP._ERROR = 11;
+XMLP._INTERRUPT = 12;
+
+XMLP._CONT_XML = 0;
+XMLP._CONT_ALT = 1;
+
+XMLP._ATT_NAME = 0;
+XMLP._ATT_VAL = 1;
+
+XMLP._STATE_PROLOG = 1;
+XMLP._STATE_DOCUMENT = 2;
+XMLP._STATE_MISC = 3;
+
+XMLP._errs = new Array();
+XMLP._errs[XMLP.ERR_CLOSE_PI = 0 ] = "PI: missing closing sequence";
+XMLP._errs[XMLP.ERR_CLOSE_DTD = 1 ] = "DTD: missing closing sequence";
+XMLP._errs[XMLP.ERR_CLOSE_COMMENT = 2 ] = "Comment: missing closing sequence";
+XMLP._errs[XMLP.ERR_CLOSE_CDATA = 3 ] = "CDATA: missing closing sequence";
+XMLP._errs[XMLP.ERR_CLOSE_ELM = 4 ] = "Element: missing closing sequence";
+XMLP._errs[XMLP.ERR_CLOSE_ENTITY = 5 ] = "Entity: missing closing sequence";
+XMLP._errs[XMLP.ERR_PI_TARGET = 6 ] = "PI: target is required";
+XMLP._errs[XMLP.ERR_ELM_EMPTY = 7 ] = "Element: cannot be both empty and closing";
+XMLP._errs[XMLP.ERR_ELM_NAME = 8 ] = "Element: name must immediatly follow \"<\"";
+XMLP._errs[XMLP.ERR_ELM_LT_NAME = 9 ] = "Element: \"<\" not allowed in element names";
+XMLP._errs[XMLP.ERR_ATT_VALUES = 10] = "Attribute: values are required and must be in quotes";
+XMLP._errs[XMLP.ERR_ATT_LT_NAME = 11] = "Element: \"<\" not allowed in attribute names";
+XMLP._errs[XMLP.ERR_ATT_LT_VALUE = 12] = "Attribute: \"<\" not allowed in attribute values";
+XMLP._errs[XMLP.ERR_ATT_DUP = 13] = "Attribute: duplicate attributes not allowed";
+XMLP._errs[XMLP.ERR_ENTITY_UNKNOWN = 14] = "Entity: unknown entity";
+XMLP._errs[XMLP.ERR_INFINITELOOP = 15] = "Infininte loop";
+XMLP._errs[XMLP.ERR_DOC_STRUCTURE = 16] = "Document: only comments, processing instructions, or whitespace allowed outside of document element";
+XMLP._errs[XMLP.ERR_ELM_NESTING = 17] = "Element: must be nested correctly";
+
+
+
+XMLP.prototype.continueParsing = function(strXML) {
+
+ if(this.m_chunkTransitionContinuation){
+ strXML = this.m_chunkTransitionContinuation + strXML;
+ }
+ // Normalize line breaks
+ strXML = SAXStrings.replace(strXML, null, null, "\r\n", "\n");
+ strXML = SAXStrings.replace(strXML, null, null, "\r", "\n");
+
+ this.m_xml = strXML;
+ this.m_iP = 0;
+ this.m_iState = XMLP._STATE_DOCUMENT;
+ //this.m_stack = new Stack();
+ //this._clearAttributes();
+ this.m_pause = false;
+ this.m_preInterruptIState = XMLP._STATE_PROLOG;
+ this.m_chunkTransitionContinuation = null;
+
+}
+
+XMLP.prototype._addAttribute = function(name, value) {
+ this.m_atts[this.m_atts.length] = new Array(name, value);
+}
+
+XMLP.prototype._checkStructure = function(iEvent) {
+ if(XMLP._STATE_PROLOG == this.m_iState) {
+ if((XMLP._TEXT == iEvent) || (XMLP._ENTITY == iEvent)) {
+ if(SAXStrings.indexOfNonWhitespace(this.getContent(), this.getContentBegin(), this.getContentEnd()) != -1) {
+ return this._setErr(XMLP.ERR_DOC_STRUCTURE);
+ }
+ }
+
+ if((XMLP._ELM_B == iEvent) || (XMLP._ELM_EMP == iEvent)) {
+ this.m_iState = XMLP._STATE_DOCUMENT;
+ // Don't return - fall through to next state
+ }
+ }
+ if(XMLP._STATE_DOCUMENT == this.m_iState) {
+ if((XMLP._ELM_B == iEvent) || (XMLP._ELM_EMP == iEvent)) {
+ this.m_stack.push(this.getName());
+ }
+
+ if((XMLP._ELM_E == iEvent) || (XMLP._ELM_EMP == iEvent)) {
+ var strTop = this.m_stack.pop();
+ if((strTop == null) || (strTop != this.getName())) {
+ return this._setErr(XMLP.ERR_ELM_NESTING);
+ }
+ }
+
+ if(this.m_stack.count() == 0) {
+ this.m_iState = XMLP._STATE_MISC;
+ return iEvent;
+ }
+ }
+ if(XMLP._STATE_MISC == this.m_iState) {
+ if((XMLP._ELM_B == iEvent) || (XMLP._ELM_E == iEvent) || (XMLP._ELM_EMP == iEvent) || (XMLP.EVT_DTD == iEvent)) {
+ return this._setErr(XMLP.ERR_DOC_STRUCTURE);
+ }
+
+ if((XMLP._TEXT == iEvent) || (XMLP._ENTITY == iEvent)) {
+ if(SAXStrings.indexOfNonWhitespace(this.getContent(), this.getContentBegin(), this.getContentEnd()) != -1) {
+ return this._setErr(XMLP.ERR_DOC_STRUCTURE);
+ }
+ }
+ }
+
+ return iEvent;
+
+}
+
+XMLP.prototype._clearAttributes = function() {
+ this.m_atts = new Array();
+}
+
+XMLP.prototype._findAttributeIndex = function(name) {
+ for(var i = 0; i < this.m_atts.length; i++) {
+ if(this.m_atts[i][XMLP._ATT_NAME] == name) {
+ return i;
+ }
+ }
+ return -1;
+
+}
+
+XMLP.prototype.getAttributeCount = function() {
+ return this.m_atts ? this.m_atts.length : 0;
+}
+
+XMLP.prototype.getAttributeName = function(index) {
+ return ((index < 0) || (index >= this.m_atts.length)) ? null : this.m_atts[index][XMLP._ATT_NAME];
+}
+
+XMLP.prototype.getAttributeValue = function(index) {
+ return ((index < 0) || (index >= this.m_atts.length)) ? null : __unescapeString(this.m_atts[index][XMLP._ATT_VAL]);
+}
+
+XMLP.prototype.getAttributeValueByName = function(name) {
+ return this.getAttributeValue(this._findAttributeIndex(name));
+}
+
+XMLP.prototype.getColumnNumber = function() {
+ return SAXStrings.getColumnNumber(this.m_xml, this.m_iP);
+}
+
+XMLP.prototype.getContent = function() {
+ return (this.m_cSrc == XMLP._CONT_XML) ? this.m_xml : this.m_cAlt;
+}
+
+XMLP.prototype.getContentBegin = function() {
+ return this.m_cB;
+}
+
+XMLP.prototype.getContentEnd = function() {
+ return this.m_cE;
+}
+
+XMLP.prototype.getLineNumber = function() {
+ return SAXStrings.getLineNumber(this.m_xml, this.m_iP);
+}
+
+XMLP.prototype.getName = function() {
+ return this.m_name;
+}
+
+XMLP.prototype.pause = function(){
+ this.m_pause = true;
+}
+
+XMLP.prototype.resume = function(){
+ this.m_pause = false;
+ this.m_iState = this.m_preInterruptIState;
+}
+
+XMLP.prototype.next = function() {
+ if(!this.m_pause){
+ return this._checkStructure(this._parse());
+ }
+ else{
+ //save off the current event loop state and set the state to interrupt
+ this.m_preInterruptIState = this.m_iState;
+ return XMLP._INTERRUPT;
+ }
+}
+
+XMLP.prototype._parse = function() {
+ if(this.m_iP == this.m_xml.length) {
+ return XMLP._NONE;
+ }
+
+ var fc = this.m_xml.charAt(this.m_iP);
+ if (fc !== '<' && fc !== '&') {
+ return this._parseText (this.m_iP);
+ }
+ else if(this.m_iP == this.m_xml.indexOf("<?", this.m_iP)) {
+ return this._parsePI (this.m_iP + 2);
+ }
+ else if(this.m_iP == this.m_xml.indexOf("<!DOCTYPE", this.m_iP)) {
+ return this._parseDTD (this.m_iP + 9);
+ }
+ else if(this.m_iP == this.m_xml.indexOf("<!--", this.m_iP)) {
+ return this._parseComment(this.m_iP + 4);
+ }
+ else if(this.m_iP == this.m_xml.indexOf("<![CDATA[", this.m_iP)) {
+ return this._parseCDATA (this.m_iP + 9);
+ }
+ else if(this.m_iP == this.m_xml.indexOf("<", this.m_iP)) {
+ return this._parseElement(this.m_iP + 1);
+ }
+ else if(this.m_iP == this.m_xml.indexOf("&", this.m_iP)) {
+ return this._parseEntity (this.m_iP + 1);
+ }
+ else{
+ return this._parseText (this.m_iP);
+ }
+
+
+}
+
+////////// NAMESPACE SUPPORT //////////////////////////////////////////
+XMLP.prototype._parsePrefixAndElementName = function (elementlabel){
+ splits = elementlabel.split(':',2);
+ return { prefix : ((splits.length === 1) ? '' : splits[0]), name : ((splits.length === 1) ? elementlabel : splits[1]), };
+}
+
+XMLP.prototype._parseNamespacesAndAtts = function (atts){
+ //translate namespaces into objects with "prefix","uri", "scopetag" Add them to: this.m_namespaceList
+ //The function should return a new list of tag attributes with the namespaces filtered
+ that = this;
+ var newnamespaces = [];
+ var filteredatts = [];
+ atts.map(function (item){
+ if(item[0].slice(0,5) === "xmlns"){
+ newnamespaces.push({
+ prefix : item[0].slice(6),
+ uri : item[1],
+ scopetag : that.m_name,
+ });
+ }
+ else{
+ filteredatts.push(item);
+ }
+ return "not used";
+ });
+ this.m_namespaceList = this.m_namespaceList.concat(newnamespaces);
+ return [ filteredatts, newnamespaces.map(function(item){return [item.prefix,item.uri];}) ];
+}
+
+XMLP.prototype._getContextualNamespace = function (prefix){
+ if(prefix !== ''){
+ for(item in this.m_namespaceList){
+ item = this.m_namespaceList[item];
+ if(item.prefix === prefix){
+ return item.uri;
+ }
+ }
+ }
+
+ //no match was found for the prefix so pop off the first non-prefix namespace
+ for(var i = (this.m_namespaceList.length-1); i>= 0; i--){
+ var item = this.m_namespaceList[i];
+ if(item.prefix === ''){
+ return item.uri;
+ }
+ }
+
+ //still nothing, lets just return an empty string
+ return '';
+}
+
+XMLP.prototype._removeExpiredNamesapces = function (closingtagname) {
+ //remove the expiring namespaces from the list (you can id them by scopetag)
+ var keeps = [];
+ this.m_namespaceList.map(function (item){
+ if(item.scopetag !== closingtagname){
+ keeps.push(item);
+ }
+ });
+
+ this.m_namespaceList = keeps;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+
+
+XMLP.prototype._parseAttribute = function(iB, iE) {
+ var iNB, iNE, iEq, iVB, iVE;
+ var cQuote, strN, strV;
+
+ this.m_cAlt = ""; //resets the value so we don't use an old one by accident (see testAttribute7 in the test suite)
+
+ iNB = SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iE);
+ if((iNB == -1) ||(iNB >= iE)) {
+ return iNB;
+ }
+
+ iEq = this.m_xml.indexOf("=", iNB);
+ if((iEq == -1) || (iEq > iE)) {
+ return this._setErr(XMLP.ERR_ATT_VALUES);
+ }
+
+ iNE = SAXStrings.lastIndexOfNonWhitespace(this.m_xml, iNB, iEq);
+
+ iVB = SAXStrings.indexOfNonWhitespace(this.m_xml, iEq + 1, iE);
+ if((iVB == -1) ||(iVB > iE)) {
+ return this._setErr(XMLP.ERR_ATT_VALUES);
+ }
+
+ cQuote = this.m_xml.charAt(iVB);
+ if(SAXStrings.QUOTES.indexOf(cQuote) == -1) {
+ return this._setErr(XMLP.ERR_ATT_VALUES);
+ }
+
+ iVE = this.m_xml.indexOf(cQuote, iVB + 1);
+ if((iVE == -1) ||(iVE > iE)) {
+ return this._setErr(XMLP.ERR_ATT_VALUES);
+ }
+
+ strN = this.m_xml.substring(iNB, iNE + 1);
+ strV = this.m_xml.substring(iVB + 1, iVE);
+
+ if(strN.indexOf("<") != -1) {
+ return this._setErr(XMLP.ERR_ATT_LT_NAME);
+ }
+
+ if(strV.indexOf("<") != -1) {
+ return this._setErr(XMLP.ERR_ATT_LT_VALUE);
+ }
+
+ strV = SAXStrings.replace(strV, null, null, "\n", " ");
+ strV = SAXStrings.replace(strV, null, null, "\t", " ");
+ iRet = this._replaceEntities(strV);
+ if(iRet == XMLP._ERROR) {
+ return iRet;
+ }
+
+ strV = this.m_cAlt;
+
+ if(this._findAttributeIndex(strN) == -1) {
+ this._addAttribute(strN, strV);
+ }
+ else {
+ return this._setErr(XMLP.ERR_ATT_DUP);
+ }
+
+ this.m_iP = iVE + 2;
+
+ return XMLP._ATT;
+
+}
+
+XMLP.prototype._parseCDATA = function(iB) {
+ var iE = this.m_xml.indexOf("]]>", iB);
+ if (iE == -1) {
+ //This item never closes, although it could be a malformed document, we will assume that we are mid-chunck, save the string and reurn as interrupted
+ this.m_chunkTransitionContinuation = this.m_xml.slice(iB-9);//the '-<![CDATA[ adds the '<!DOCTYPE' back into the string
+ return XMLP._INTERRUPT;
+ //return this._setErr(XMLP.ERR_CLOSE_CDATA);
+ }
+
+ this._setContent(XMLP._CONT_XML, iB, iE);
+
+ this.m_iP = iE + 3;
+
+ return XMLP._CDATA;
+
+}
+
+XMLP.prototype._parseComment = function(iB) {
+ var iE = this.m_xml.indexOf("-" + "->", iB);
+ if (iE == -1) {
+ //This item never closes, although it could be a malformed document, we will assume that we are mid-chunck, save the string and reurn as interrupted
+ this.m_chunkTransitionContinuation = this.m_xml.slice(iB-4);//the '-4' adds the '<!--' back into the string
+ return XMLP._INTERRUPT;
+ //return this._setErr(XMLP.ERR_CLOSE_COMMENT);
+ }
+
+ this._setContent(XMLP._CONT_XML, iB, iE);
+
+ this.m_iP = iE + 3;
+
+ return XMLP._COMMENT;
+
+}
+
+XMLP.prototype._parseDTD = function(iB) {
+ // Eat DTD
+ var iE, strClose, iInt, iLast;
+
+ iE = this.m_xml.indexOf(">", iB);
+ if(iE == -1) {
+ //This item never closes, although it could be a malformed document, we will assume that we are mid-chunck, save the string and reurn as interrupted
+ this.m_chunkTransitionContinuation = this.m_xml.slice(iB-9);//the '-9' adds the '<!DOCTYPE' back into the string
+ return XMLP._INTERRUPT;
+ //return this._setErr(XMLP.ERR_CLOSE_DTD);
+ }
+
+ iInt = this.m_xml.indexOf("[", iB);
+ strClose = ((iInt != -1) && (iInt < iE)) ? "]>" : ">";
+
+ while(true) {
+ // DEBUG: Remove
+ if(iE == iLast) {
+ return this._setErr(XMLP.ERR_INFINITELOOP);
+ }
+
+ iLast = iE;
+ // DEBUG: Remove End
+
+ iE = this.m_xml.indexOf(strClose, iB);
+ if(iE == -1) {
+ return this._setErr(XMLP.ERR_CLOSE_DTD);
+ }
+
+ // Make sure it is not the end of a CDATA section
+ if (this.m_xml.substring(iE - 1, iE + 2) != "]]>") {
+ break;
+ }
+ }
+
+ this.m_iP = iE + strClose.length;
+
+ return XMLP._DTD;
+
+}
+
+XMLP.prototype._parseElement = function(iB) {
+ var iE, iDE, iNE, iRet;
+ var iType, strN, iLast;
+
+ iDE = iE = this.m_xml.indexOf(">", iB);
+ if(iE == -1) {
+ //This element never closes, although it could be a malformed document, we will assume that we are mid-chunck, save the string and reurn as interrupted
+ this.m_chunkTransitionContinuation = this.m_xml.slice(iB-1);//the '-1' adds the '<' back into the string
+ return XMLP._INTERRUPT;
+ //return this._setErr(XMLP.ERR_CLOSE_ELM);
+ }
+
+ if(this.m_xml.charAt(iB) == "/") {
+ iType = XMLP._ELM_E;
+ iB++;
+ } else {
+ iType = XMLP._ELM_B;
+ }
+
+ if(this.m_xml.charAt(iE - 1) == "/") {
+ if(iType == XMLP._ELM_E) {
+ return this._setErr(XMLP.ERR_ELM_EMPTY);
+ }
+ iType = XMLP._ELM_EMP;
+ iDE--;
+ }
+
+ iDE = SAXStrings.lastIndexOfNonWhitespace(this.m_xml, iB, iDE);
+
+ //djohack
+ //hack to allow for elements with single character names to be recognized
+
+ if (iE - iB != 1 ) {
+ if(SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iDE) != iB) {
+ return this._setErr(XMLP.ERR_ELM_NAME);
+ }
+ }
+ // end hack -- original code below
+
+ /*
+ if(SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iDE) != iB)
+ return this._setErr(XMLP.ERR_ELM_NAME);
+ */
+ this._clearAttributes();
+
+ iNE = SAXStrings.indexOfWhitespace(this.m_xml, iB, iDE);
+ if(iNE == -1) {
+ iNE = iDE + 1;
+ }
+ else {
+ this.m_iP = iNE;
+ while(this.m_iP < iDE) {
+ // DEBUG: Remove
+ if(this.m_iP == iLast) return this._setErr(XMLP.ERR_INFINITELOOP);
+ iLast = this.m_iP;
+ // DEBUG: Remove End
+
+
+ iRet = this._parseAttribute(this.m_iP, iDE);
+ if(iRet == XMLP._ERROR) return iRet;
+ }
+ }
+
+ strN = this.m_xml.substring(iB, iNE);
+
+ if(strN.indexOf("<") != -1) {
+ return this._setErr(XMLP.ERR_ELM_LT_NAME);
+ }
+
+ this.m_name = strN;
+ this.m_iP = iE + 1;
+
+ return iType;
+
+}
+
+XMLP.prototype._parseEntity = function(iB) {
+ var iE = this.m_xml.indexOf(";", iB);
+ if(iE == -1) {
+ //This item never closes, although it could be a malformed document, we will assume that we are mid-chunck, save the string and reurn as interrupted
+ this.m_chunkTransitionContinuation = this.m_xml.slice(iB-1);//the '-1' adds the '&' back into the string
+ return XMLP._INTERRUPT;
+ //return this._setErr(XMLP.ERR_CLOSE_ENTITY);
+ }
+
+ this.m_iP = iE + 1;
+
+ return this._replaceEntity(this.m_xml, iB, iE);
+
+}
+
+XMLP.prototype._parsePI = function(iB) {
+ var iE, iTB, iTE, iCB, iCE;
+
+ iE = this.m_xml.indexOf("?>", iB);
+ if(iE == -1) {
+ //This item never closes, although it could be a malformed document, we will assume that we are mid-chunck, save the string and reurn as interrupted
+ this.m_chunkTransitionContinuation = this.m_xml.slice(iB-2);//the '-2' adds the '?>' back into the string
+ return XMLP._INTERRUPT;
+ return this._setErr(XMLP.ERR_CLOSE_PI);
+ }
+
+ iTB = SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iE);
+ if(iTB == -1) {
+ return this._setErr(XMLP.ERR_PI_TARGET);
+ }
+
+ iTE = SAXStrings.indexOfWhitespace(this.m_xml, iTB, iE);
+ if(iTE == -1) {
+ iTE = iE;
+ }
+
+ iCB = SAXStrings.indexOfNonWhitespace(this.m_xml, iTE, iE);
+ if(iCB == -1) {
+ iCB = iE;
+ }
+
+ iCE = SAXStrings.lastIndexOfNonWhitespace(this.m_xml, iCB, iE);
+ if(iCE == -1) {
+ iCE = iE - 1;
+ }
+
+ this.m_name = this.m_xml.substring(iTB, iTE);
+ this._setContent(XMLP._CONT_XML, iCB, iCE + 1);
+ this.m_iP = iE + 2;
+
+ return XMLP._PI;
+
+}
+
+XMLP.prototype._parseText = function(iB) {
+ var iE, ch;
+
+ for (iE=iB; iE<this.m_xml.length; ++iE) {
+ ch = this.m_xml.charAt(iE);
+ if (ch === '<' || ch === '&') {
+ break;
+ }
+ }
+
+ this._setContent(XMLP._CONT_XML, iB, iE);
+
+ this.m_iP = iE;
+
+ return XMLP._TEXT;
+
+}
+
+XMLP.prototype._replaceEntities = function(strD, iB, iE) {
+ if(SAXStrings.isEmpty(strD)) return "";
+ iB = iB || 0;
+ iE = iE || strD.length;
+
+
+ var iEB, iEE, strRet = "";
+
+ iEB = strD.indexOf("&", iB);
+ iEE = iB;
+
+ while((iEB > 0) && (iEB < iE)) {
+ strRet += strD.substring(iEE, iEB);
+
+ iEE = strD.indexOf(";", iEB) + 1;
+
+ if((iEE == 0) || (iEE > iE)) {
+ return this._setErr(XMLP.ERR_CLOSE_ENTITY);
+ }
+
+ iRet = this._replaceEntity(strD, iEB + 1, iEE - 1);
+ if(iRet == XMLP._ERROR) {
+ return iRet;
+ }
+
+ strRet += this.m_cAlt;
+
+ iEB = strD.indexOf("&", iEE);
+ }
+
+ if(iEE != iE) {
+ strRet += strD.substring(iEE, iE);
+ }
+
+ this._setContent(XMLP._CONT_ALT, strRet);
+
+ return XMLP._ENTITY;
+
+}
+
+XMLP.prototype._replaceEntity = function(strD, iB, iE) {
+ if(SAXStrings.isEmpty(strD)) return -1;
+ iB = iB || 0;
+ iE = iE || strD.length;
+
+ switch(strD.substring(iB, iE)) {
+ case "amp": strEnt = "&"; break;
+ case "lt": strEnt = "<"; break;
+ case "gt": strEnt = ">"; break;
+ case "apos": strEnt = "'"; break;
+ case "quot": strEnt = "\""; break;
+ case "nbsp":strEnt = ''; break;
+ case "lt":strEnt = '<'; break;
+ case "gt":strEnt = '>'; break;
+ case "amp":strEnt = '&'; break;
+ case "cent":strEnt = "¢"; break;
+ case "pound":strEnt = '£'; break;
+ case "yen":strEnt = '¥'; break;
+ case "euro":strEnt = ''; break;
+ case "sect":strEnt = '§'; break;
+ case "copy":strEnt = '©'; break;
+ case "reg":strEnt = '®'; break;
+ default:
+ if(strD.charAt(iB) == "#") {
+ strEnt = String.fromCharCode(parseInt(strD.substring(iB + 1, iE)));
+ } else {
+ strEnt = ' ';
+ //return this._setErr(XMLP.ERR_ENTITY_UNKNOWN);
+ }
+ break;
+ }
+ this._setContent(XMLP._CONT_ALT, strEnt);
+
+ return XMLP._ENTITY;
+}
+
+XMLP.prototype._setContent = function(iSrc) {
+ var args = arguments;
+
+ if(XMLP._CONT_XML == iSrc) {
+ this.m_cAlt = null;
+ this.m_cB = args[1];
+ this.m_cE = args[2];
+ } else {
+ this.m_cAlt = args[1];
+ this.m_cB = 0;
+ this.m_cE = args[1].length;
+ }
+ this.m_cSrc = iSrc;
+
+}
+
+XMLP.prototype._setErr = function(iErr) {
+ var strErr = XMLP._errs[iErr];
+
+ this.m_cAlt = strErr;
+ this.m_cB = 0;
+ this.m_cE = strErr.length;
+ this.m_cSrc = XMLP._CONT_ALT;
+
+ return XMLP._ERROR;
+
+} // end function _setErr
+
+
+//SaxParser is an object that basically wraps an XMLP instance, and provides an
+//event-based interface for parsing. This is the object users interact with when coding
+//with XML for <SCRIPT>
+var SaxParser = function(eventhandlerfactory) {
+
+ var eventhandler = new function(){
+
+ }
+
+ var thehandler = function() {};
+ thehandler.prototype.onStartDocument = function (funct){
+ eventhandler.onStartDocument = funct;
+ }
+ thehandler.prototype.onEndDocument = function (funct){
+ eventhandler.onEndDocument = funct;
+ }
+ thehandler.prototype.onStartElementNS = function (funct){
+ eventhandler.onStartElementNS = funct;
+ }
+ thehandler.prototype.onEndElementNS = function (funct){
+ eventhandler.onEndElementNS = funct;
+ }
+ thehandler.prototype.onCharacters = function(funct) {
+ eventhandler.onCharacters = funct;
+ }
+ thehandler.prototype.onCdata = function(funct) {
+ eventhandler.onCdata = funct;
+ }
+ thehandler.prototype.onComment = function(funct) {
+ eventhandler.onComment = funct;
+ }
+ thehandler.prototype.onWarning = function(funct) {
+ eventhandler.onWarning = funct;
+ }
+
+ thehandler.prototype.onError = function(funct) {
+ eventhandler.onError = funct;
+ }
+
+
+ eventhandlerfactory(new thehandler());
+ //eventhandler = eventhandler(eventhandler);
+ this.m_hndDoc = eventhandler;
+ this.m_hndErr = eventhandler;
+ this.m_hndLex = eventhandler;
+ this.m_interrupted = false;
+}
+
+
+// CONSTANTS (these must be below the constructor)
+SaxParser.DOC_B = 1;
+SaxParser.DOC_E = 2;
+SaxParser.ELM_B = 3;
+SaxParser.ELM_E = 4;
+SaxParser.CHARS = 5;
+SaxParser.PI = 6;
+SaxParser.CD_B = 7;
+SaxParser.CD_E = 8;
+SaxParser.CMNT = 9;
+SaxParser.DTD_B = 10;
+SaxParser.DTD_E = 11;
+
+SaxParser.prototype.parseFile = function(filename) { //This function will only work in the node.js environment.
+ var fs = require('fs');
+ var that = this;
+ fs.readFile(filename, function (err, data) {
+ that.parseString(data);
+ });
+}
+
+
+SaxParser.prototype.parseString = function(strD) {
+
+ var that = this;
+
+ var startnew = true;
+ if(!that.m_parser){
+ that.m_parser = new XMLP(strD);
+ startnew = false;
+ }
+ else{
+ that.m_parser.continueParsing(strD);
+ startnew = true;
+ }
+
+ //if(that.m_hndDoc && that.m_hndDoc.setDocumentLocator) {
+ // that.m_hndDoc.setDocumentLocator(that);
+ //}
+
+ that.m_bErr = false;
+
+ if(!that.m_bErr && !startnew) {
+ that._fireEvent(SaxParser.DOC_B);
+ }
+ that._parseLoop();
+ if(!that.m_bErr && !that.m_interrupted) {
+ that._fireEvent(SaxParser.DOC_E);
+ }
+
+ that.m_xml = null;
+ that.m_iP = 0;
+ that.m_interrupted = false;
+
+}
+
+SaxParser.prototype.pause = function() {
+ this.m_parser.pause();
+}
+
+SaxParser.prototype.resume = function() {
+ //reset the state
+ this.m_parser.resume();
+ //now start up the parse loop
+ var that = this;
+ setTimeout(function(){
+ that._parseLoop();
+ }, 0);
+}
+
+SaxParser.prototype.setDocumentHandler = function(hnd) {
+ this.m_hndDoc = hnd;
+}
+
+SaxParser.prototype.setErrorHandler = function(hnd) {
+ this.m_hndErr = hnd;
+}
+
+SaxParser.prototype.setLexicalHandler = function(hnd) {
+ this.m_hndLex = hnd;
+}
+
+SaxParser.prototype.getColumnNumber = function() {
+ return this.m_parser.getColumnNumber();
+}
+
+SaxParser.prototype.getLineNumber = function() {
+ return this.m_parser.getLineNumber();
+}
+
+SaxParser.prototype.getMessage = function() {
+ return this.m_strErrMsg;
+}
+
+SaxParser.prototype.getPublicId = function() {
+ return null;
+}
+
+SaxParser.prototype.getSystemId = function() {
+ return null;
+}
+
+SaxParser.prototype.getLength = function() {
+ return this.m_parser.getAttributeCount();
+}
+
+SaxParser.prototype.getName = function(index) {
+ return this.m_parser.getAttributeName(index);
+}
+
+SaxParser.prototype.getValue = function(index) {
+ return this.m_parser.getAttributeValue(index);
+}
+
+SaxParser.prototype.getValueByName = function(name) {
+ return this.m_parser.getAttributeValueByName(name);
+}
+
+SaxParser.prototype._fireError = function(strMsg) {
+ this.m_strErrMsg = strMsg;
+ this.m_bErr = true;
+
+ if(this.m_hndErr && this.m_hndErr.onError) {
+ this.m_hndErr.onError(this.m_strErrMsg);
+ }
+}
+
+
+
+SaxParser.prototype._fireEvent = function(iEvt) {
+ var hnd, func, args = arguments, iLen = args.length - 1;
+
+
+ if(this.m_bErr) return;
+
+ if(SaxParser.DOC_B == iEvt) {
+ func = "onStartDocument"; hnd = this.m_hndDoc;
+ }
+ else if (SaxParser.DOC_E == iEvt) {
+ func = "onEndDocument"; hnd = this.m_hndDoc;
+ }
+ else if (SaxParser.ELM_B == iEvt) {
+ func = "onStartElementNS"; hnd = this.m_hndDoc;
+ }
+ else if (SaxParser.ELM_E == iEvt) {
+ func = "onEndElementNS"; hnd = this.m_hndDoc;
+ }
+ else if (SaxParser.CHARS == iEvt) {
+ func = "onCharacters"; hnd = this.m_hndDoc;
+ }
+ else if (SaxParser.PI == iEvt) {
+ func = "processingInstruction"; hnd = this.m_hndDoc;
+ }
+ else if (SaxParser.CD_B == iEvt) {
+ func = "onCdata"; hnd = this.m_hndLex;
+ }
+ else if (SaxParser.CD_E == iEvt) {
+ func = "onEndCDATA"; hnd = this.m_hndLex;
+ }
+ else if (SaxParser.CMNT == iEvt) {
+ func = "onComment"; hnd = this.m_hndLex;
+ }
+
+ if(hnd && hnd[func]) {
+ if(0 == iLen) {
+ hnd[func]();
+ }
+ else if (1 == iLen) {
+ hnd[func](args[1]);
+ }
+ else if (2 == iLen) {
+ hnd[func](args[1], args[2]);
+ }
+ else if (3 == iLen) {
+ hnd[func](args[1], args[2], args[3]);
+ }
+ else if (4 == iLen) {
+ hnd[func](args[1], args[2], args[3], args[4]);
+ }
+ else if (5 == iLen) {
+ hnd[func](args[1], args[2], args[3], args[4], args[5]);
+ }
+ }
+
+}
+
+
+
+
+SaxParser.prototype._parseLoop = function(parser) {
+ var iEvent, parser;
+
+ parser = this.m_parser;
+ while(!this.m_bErr) {
+ iEvent = parser.next();
+
+ if(iEvent == XMLP._ELM_B) {
+ theatts = this.m_parser.m_atts;
+ nameobject = parser._parsePrefixAndElementName(parser.getName());
+ theattsandnamespace = parser._parseNamespacesAndAtts(theatts);
+ var theuri = parser._getContextualNamespace(nameobject.prefix);
+ this._fireEvent(SaxParser.ELM_B, nameobject.name, theattsandnamespace[0], (nameobject.prefix === '')? null : nameobject.prefix, (theuri === '')? null : theuri ,theattsandnamespace[1] );
+ }
+ else if(iEvent == XMLP._ELM_E) {
+ nameobject = parser._parsePrefixAndElementName(parser.getName());
+ var theuri = parser._getContextualNamespace(nameobject.prefix);
+ parser._removeExpiredNamesapces(parser.getName());
+ this._fireEvent(SaxParser.ELM_E, nameobject.name, (nameobject.prefix === '')? null : nameobject.prefix, (theuri === '')? null : theuri);
+ }
+ else if(iEvent == XMLP._ELM_EMP) {
+ //this is both a begin and end element
+ theatts = this.m_parser.m_atts;
+ nameobject = parser._parsePrefixAndElementName(parser.getName());
+ theattsandnamespace = parser._parseNamespacesAndAtts(theatts);
+ var theuri = parser._getContextualNamespace(nameobject.prefix);
+ this._fireEvent(SaxParser.ELM_B, nameobject.name, theattsandnamespace[0], (nameobject.prefix === '')? null : nameobject.prefix, (theuri === '')? null : theuri ,theattsandnamespace[1] );
+
+ parser._removeExpiredNamesapces(parser.getName());
+ this._fireEvent(SaxParser.ELM_E, nameobject.name, (nameobject.prefix === '')? null : nameobject.prefix, (theuri === '')? null : theuri);
+ //this._fireEvent(SaxParser.ELM_B, parser.getName(), this.m_parser.m_atts.map(function(item){return { name : item[0], value : item[1], };}) );
+ //this._fireEvent(SaxParser.ELM_E, parser.getName());
+ }
+ else if(iEvent == XMLP._TEXT) {
+ this._fireEvent(SaxParser.CHARS, parser.getContent().slice(parser.getContentBegin(),parser.getContentEnd()));
+ }
+ else if(iEvent == XMLP._ENTITY) {
+ this._fireEvent(SaxParser.CHARS, parser.getContent(), parser.getContentBegin(), parser.getContentEnd() - parser.getContentBegin());
+ }
+ else if(iEvent == XMLP._PI) {
+ this._fireEvent(SaxParser.PI, parser.getName(), parser.getContent().substring(parser.getContentBegin(), parser.getContentEnd()));
+ }
+ else if(iEvent == XMLP._CDATA) {
+ this._fireEvent(SaxParser.CD_B, parser.getContent().slice(parser.getContentBegin(),parser.getContentEnd()));
+ //this._fireEvent(SaxParser.CHARS, parser.getContent(), parser.getContentBegin(), parser.getContentEnd() - parser.getContentBegin());
+ //this._fireEvent(SaxParser.CD_E);
+ }
+ else if(iEvent == XMLP._COMMENT) {
+ this._fireEvent(SaxParser.CMNT, parser.getContent().slice(parser.getContentBegin(),parser.getContentEnd()));
+ }
+ else if(iEvent == XMLP._DTD) {
+ }
+ else if(iEvent == XMLP._ERROR) {
+ this._fireError(parser.getContent());
+ }
+ else if(iEvent == XMLP._INTERRUPT){
+ this.m_interrupted = true;
+ return;//just return and wait to be restarted
+ }
+ else if(iEvent == XMLP._NONE) {
+ return;
+ }
+ }
+
+}
+
+//SAXStrings: a useful object containing string manipulation functions
+var SAXStrings = function() {
+//This is the constructor of the SAXStrings object
+}
+
+
+// CONSTANTS (these must be below the constructor)
+SAXStrings.WHITESPACE = " \t\n\r";
+SAXStrings.QUOTES = "\"'";
+
+
+SAXStrings.getColumnNumber = function(strD, iP) {
+ if(SAXStrings.isEmpty(strD)) {
+ return -1;
+ }
+ iP = iP || strD.length;
+
+ var arrD = strD.substring(0, iP).split("\n");
+ var strLine = arrD[arrD.length - 1];
+ arrD.length--;
+ var iLinePos = arrD.join("\n").length;
+
+ return iP - iLinePos;
+
+}
+
+SAXStrings.getLineNumber = function(strD, iP) {
+ if(SAXStrings.isEmpty(strD)) {
+ return -1;
+ }
+ iP = iP || strD.length;
+
+ return strD.substring(0, iP).split("\n").length
+}
+
+SAXStrings.indexOfNonWhitespace = function(strD, iB, iE) {
+ if(SAXStrings.isEmpty(strD)) {
+ return -1;
+ }
+ iB = iB || 0;
+ iE = iE || strD.length;
+
+ for(var i = iB; i < iE; i++){
+ if(SAXStrings.WHITESPACE.indexOf(strD.charAt(i)) == -1) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+SAXStrings.indexOfWhitespace = function(strD, iB, iE) {
+ if(SAXStrings.isEmpty(strD)) {
+ return -1;
+ }
+ iB = iB || 0;
+ iE = iE || strD.length;
+
+ for(var i = iB; i < iE; i++) {
+ if(SAXStrings.WHITESPACE.indexOf(strD.charAt(i)) != -1) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+SAXStrings.isEmpty = function(strD) {
+ return (strD == null) || (strD.length == 0);
+}
+
+SAXStrings.lastIndexOfNonWhitespace = function(strD, iB, iE) {
+ if(SAXStrings.isEmpty(strD)) {
+ return -1;
+ }
+ iB = iB || 0;
+ iE = iE || strD.length;
+
+ for(var i = iE - 1; i >= iB; i--){
+ if(SAXStrings.WHITESPACE.indexOf(strD.charAt(i)) == -1){
+ return i;
+ }
+ }
+ return -1;
+}
+
+SAXStrings.replace = function(strD, iB, iE, strF, strR) {
+ if(SAXStrings.isEmpty(strD)) {
+ return "";
+ }
+ iB = iB || 0;
+ iE = iE || strD.length;
+
+ return strD.toString().substring(iB, iE).split(strF).join(strR);
+
+}
+
+var Stack = function() {
+ this.m_arr = new Array();
+}
+
+Stack.prototype.clear = function() {
+ this.m_arr = new Array();
+}
+
+Stack.prototype.count = function() {
+ return this.m_arr.length;
+}
+
+Stack.prototype.destroy = function() {
+ this.m_arr = null;
+}
+
+Stack.prototype.peek = function() {
+ if(this.m_arr.length == 0) {
+ return null;
+ }
+
+ return this.m_arr[this.m_arr.length - 1];
+
+}
+
+Stack.prototype.pop = function() {
+ if(this.m_arr.length == 0) {
+ return null;
+ }
+
+ var o = this.m_arr[this.m_arr.length - 1];
+ this.m_arr.length--;
+ return o;
+
+}
+
+Stack.prototype.push = function(o) {
+ this.m_arr[this.m_arr.length] = o;
+}
+
+// CONVENIENCE FUNCTIONS
+function isEmpty(str) {
+ return (str==null) || (str.length==0);
+}
+
+
+function trim(trimString, leftTrim, rightTrim) {
+ if (isEmpty(trimString)) {
+ return "";
+ }
+
+ // the general focus here is on minimal method calls - hence only one
+ // substring is done to complete the trim.
+
+ if (leftTrim == null) {
+ leftTrim = true;
+ }
+
+ if (rightTrim == null) {
+ rightTrim = true;
+ }
+
+ var left=0;
+ var right=0;
+ var i=0;
+ var k=0;
+
+
+ // modified to properly handle strings that are all whitespace
+ if (leftTrim == true) {
+ while ((i<trimString.length) && (whitespace.indexOf(trimString.charAt(i++))!=-1)) {
+ left++;
+ }
+ }
+ if (rightTrim == true) {
+ k=trimString.length-1;
+ while((k>=left) && (whitespace.indexOf(trimString.charAt(k--))!=-1)) {
+ right++;
+ }
+ }
+ return trimString.substring(left, trimString.length - right);
+}
+
+function __escapeString(str) {
+
+ var escAmpRegEx = /&/g;
+ var escLtRegEx = /</g;
+ var escGtRegEx = />/g;
+ var quotRegEx = /"/g;
+ var aposRegEx = /'/g;
+
+ str = str.replace(escAmpRegEx, "&amp;");
+ str = str.replace(escLtRegEx, "&lt;");
+ str = str.replace(escGtRegEx, "&gt;");
+ str = str.replace(quotRegEx, "&quot;");
+ str = str.replace(aposRegEx, "&apos;");
+
+ return str;
+}
+
+function __unescapeString(str) {
+
+ var escAmpRegEx = /&amp;/g;
+ var escLtRegEx = /&lt;/g;
+ var escGtRegEx = /&gt;/g;
+ var quotRegEx = /&quot;/g;
+ var aposRegEx = /&apos;/g;
+
+ str = str.replace(escAmpRegEx, "&");
+ str = str.replace(escLtRegEx, "<");
+ str = str.replace(escGtRegEx, ">");
+ str = str.replace(quotRegEx, "\"");
+ str = str.replace(aposRegEx, "'");
+
+ return str;
+}
+
+ if(typeof exports != 'undefined') exports.SaxParser = SaxParser;
+ else window.SaxParser = SaxParser;
+})()
View
256 node_modules/enml-js/lib/xml-writer.js
@@ -0,0 +1,256 @@
+function strval(s) {
+ if (typeof s == 'string') {
+ return s;
+ }
+ else if (typeof s == 'function') {
+ return s();
+ }
+ else if (s instanceof XMLWriter) {
+ return s.toString();
+ }
+ else throw Error('Bad Parameter');
+}
+
+function XMLWriter(indent, callback) {
+
+ if (!(this instanceof XMLWriter)) {
+ return new XMLWriter();
+ }
+
+ this.name_regex = /[_:A-Za-z][-._:A-Za-z0-9]*/;
+ this.output = '';
+ this.stack = [];
+ this.tags = 0;
+ this.attributes = 0;
+ this.attribute = 0;
+ this.texts = 0;
+ this.comment = 0;
+ this.pi = 0;
+ this.cdata = 0;
+ this.writer;
+ this.writer_encoding = 'UTF-8';
+
+ if (typeof callback == 'function') {
+ this.writer = callback;
+ } else {
+ this.writer = function (s, e) {
+ this.output += s;
+ }
+ }
+}
+
+XMLWriter.prototype = {
+ toString : function () {
+ this.flush();
+ return this.output;
+ },
+
+ write : function () {
+ for (var i = 0; i < arguments.length; i++) {
+ this.writer(arguments[i], this.writer_encoding);
+ }
+ },
+
+
+ flush : function () {
+ for (var i = this.tags; i > 0; i--) {
+ this.endElement();
+ }
+ this.tags = 0;
+ },
+
+ startDocument : function (version, encoding, standalone) {
+ if (this.tags || this.attributes) return this;
+
+ this.startPI('xml');
+ this.startAttribute('version');
+ this.text(typeof version == "string" ? version : "1.0");
+ this.endAttribute();
+ if (typeof encoding == "string") {
+ this.startAttribute('encoding');
+ this.text(encoding);
+ this.endAttribute();
+ writer_encoding = encoding;
+ }
+ if (standalone) {
+ this.startAttribute('standalone');
+ this.text("yes");
+ this.endAttribute();
+ }
+ this.endPI();
+ this.write('\n');
+ return this;
+ },
+
+ endDocument : function () {
+ if (this.attributes) this.endAttributes();
+ return this;
+ },
+
+ writeElement : function (name, content) {
+ return this.startElement(name).text(content).endElement();
+ },
+
+ startElement : function (name) {
+ name = strval(name);
+ if (!name.match(this.name_regex)) throw Error('Invalid Parameter');
+ if (this.attributes) this.endAttributes();
+ ++this.tags;
+ this.texts = 0;
+ this.stack.push({
+ name: name,
+ tags: this.tags
+ });
+ this.write('<', name);
+ this.startAttributes();
+ return this;
+ },
+
+ endElement : function () {
+ if (!this.tags) return this;
+ var t = this.stack.pop();
+ if (this.attributes > 0) {
+ if (this.attribute) {
+ if (this.texts) this.endAttribute();
+ this.endAttribute();
+ }
+ this.write('/');
+ this.endAttributes();
+ } else {
+ this.write('</', t.name, '>');
+ }
+ --this.tags;
+ this.texts = 0;
+ return this;
+ },
+
+ writeAttribute : function (name, content) {
+ return this.startAttribute(name).text(content).endAttribute();
+ },
+
+ startAttributes : function () {
+ this.attributes = 1;
+ return this;
+ },
+
+ endAttributes : function () {
+ if (!this.attributes) return this;
+ if (this.attribute) this.endAttribute();
+ this.attributes = 0;
+ this.attribute = 0;
+ this.texts = 0;
+ this.write('>');
+ return this;
+ },
+
+ startAttribute : function (name) {
+ name = strval(name);
+ if (!name.match(this.name_regex)) throw Error('Invalid Parameter');
+ if (!this.attributes && !this.pi) return this;
+ if (this.attribute) return this;
+ this.attribute = 1;
+ this.write(' ', name, '="');
+ return this;
+ },
+
+ endAttribute : function () {
+ if (!this.attribute) return this;
+ this.attribute = 0;
+ this.texts = 0;
+ this.write('"');
+ return this;
+ },
+
+ text : function (content) {
+ content = strval(content);
+ if (!this.tags && !this.comment && !this.pi && !this.cdata) return this;
+ if (this.attributes && this.attribute) {
+ ++this.texts;
+ this.write(content.replace('&', '&amp;').replace('"', '&quot;'));
+ return this;
+ } else if (this.attributes && !this.attribute) {
+ this.endAttributes();
+ }
+ ++this.texts;
+ this.write(content.replace('&', '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'));
+ return this;
+ },
+
+ writeComment : function (content) {
+ return this.startComment().text(content).endComment();
+ },
+
+ startComment : function () {
+ if (this.comment) return this;
+ if (this.attributes) this.endAttributes();
+ this.write('<!--');
+ this.comment = 1;
+ return this;
+ },
+
+ endComment : function () {
+ if (!this.comment) return this;
+ this.write('-->');
+ this.comment = 0;
+ return this;
+ },
+
+ writePI : function (name, content) {
+ return this.startPI(name).text(content).endPI()
+ },
+
+ startPI : function (name) {
+ name = strval(name);
+ if (!name.match(this.name_regex)) throw Error('Invalid Parameter');
+ if (this.pi) return this;
+ if (this.attributes) this.endAttributes();
+ this.write('<?', name);
+ this.pi = 1;
+ return this;
+ },
+
+ endPI : function () {
+ if (!this.pi) return this;
+ this.write('?>');
+ this.pi = 0;
+ return this;
+ },
+
+ writeCData : function (content) {
+ return this.startCData().text(content).endCData();
+ },
+
+ startCData : function () {
+ if (this.cdata) return this;
+ if (this.attributes) this.endAttributes();
+ this.write('<![CDATA[');
+ this.cdata = 1;
+ return this;
+ },
+
+ endCData : function () {
+ if (!this.cdata) return this;
+ this.write(']]>');
+ this.cdata = 0;
+ return this;
+ },
+
+ writeRaw : function(content) {
+ content = strval(content);
+ if (!this.tags && !this.comment && !this.pi && !this.cdata) return this;
+ if (this.attributes && this.attribute) {
+ ++this.texts;
+ this.write(content.replace('&', '&amp;').replace('"', '&quot;'));
+ return this;
+ } else if (this.attributes && !this.attribute) {
+ this.endAttributes();
+ }
+ ++this.texts;
+ this.write(content);
+ return this;
+ }
+
+}
+
+if(typeof module != 'undefined') module.exports = XMLWriter;
+else window.XMLWriter = XMLWriter;
View
18 node_modules/enml-js/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "enml-js",
+ "description": "Evernote's ENML library in Javascript",
+ "homepage": "https://github.com/berryboy/enml-js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/berryboy/enml-js.git"
+ },
+ "version": "0.0.1",
+ "directories": {
+ "lib": "./lib",
+ "examples": "./examples"
+ },
+ "main": "./enml",
+ "readme": "enml-js\n===========\n\n[Evernote's ENML](http://dev.evernote.com/documentation/cloud/chapters/ENML.php) library in Javascript.\n\n\nFunctions\n============\n\n* **enml.ENMLOfPlainText**(String) - Encode plain text in ENML format.\n\n\n* **enml.HTMLOfENML**(String, [ Map <String, URL> ]) - Translate ENML to HTML for viewing in browsers. Showing images you have to provide a map of images' hash and their src url.\n\n",
+ "_id": "enml-js@0.0.1",
+ "_from": "enml-js"
+}

0 comments on commit 42d3321

Please sign in to comment.