1 goog.provide('xrx.richxml.mode'); 2 3 4 5 goog.require('xrx.label'); 6 goog.require('xrx.richxml'); 7 goog.require('xrx.token'); 8 9 10 11 /** 12 * CodeMirror mode for xrx.richxml. 13 * @return {!Object} 14 */ 15 xrx.richxml.mode = CodeMirror.defineMode('richxml', function() { 16 17 18 19 function nextToken(state, className) { 20 var previousToken = state.context.token; 21 var previousLabel = previousToken.label(); 22 var newToken; 23 var newLabel = previousLabel.clone(); 24 25 switch(className) { 26 case xrx.richxml.className.notTag: 27 if (previousToken.type() === xrx.token.START_TAG) { 28 newLabel.push0(); 29 } 30 newToken = new xrx.token.NotTag(newLabel); 31 break; 32 case xrx.richxml.className.startTag: 33 if (previousToken.type() === xrx.token.START_TAG) { 34 newLabel.child(); 35 } else { 36 newLabel.nextSibling(); 37 } 38 newToken = new xrx.token.StartTag(newLabel); 39 break; 40 case xrx.richxml.className.emptyTag: 41 if (previousToken.type() === xrx.token.START_TAG) { 42 newLabel.child(); 43 } else { 44 newLabel.nextSibling(); 45 } 46 newToken = new xrx.token.EmptyTag(newLabel); 47 break; 48 case xrx.richxml.className.endTag: 49 if (previousToken.type() === xrx.token.START_TAG) { 50 // do nothing 51 } else { 52 newLabel.parent() 53 } 54 newToken = new xrx.token.EndTag(newLabel); 55 break; 56 default: 57 throw Error('Unknown token.'); 58 break; 59 } 60 return newToken; 61 } 62 63 64 65 function changeContext(state, className) { 66 var token = (!state.context) ? new xrx.token.StartTag(new xrx.label([1])) : 67 nextToken(state, className); 68 var newContext = { 69 token: token, 70 prev: state.context, 71 next: null 72 }; 73 74 state.context = newContext; 75 } 76 77 78 /** 79 * Parses the place-holder string. 80 * @return {!xrx.richxml.className} Class name of the token type. 81 */ 82 function parse(stream, state) { 83 var ch = stream.next(); 84 85 if (ch === xrx.richxml.placeholder.startTag) { 86 changeContext(state, xrx.richxml.className.startTag); 87 return xrx.richxml.className.startTag; 88 } else if (ch === xrx.richxml.placeholder.endTag) { 89 changeContext(state, xrx.richxml.className.endTag); 90 return xrx.richxml.className.endTag; 91 } else if (ch === xrx.richxml.placeholder.emptyTag) { 92 changeContext(state, xrx.richxml.className.emptyTag); 93 return xrx.richxml.className.emptyTag; 94 } else { 95 while(true) { 96 ch = stream.next(); 97 if(!ch) break; 98 if(ch === xrx.richxml.placeholder.startTag || ch === xrx.richxml.placeholder.endTag 99 || ch === xrx.richxml.placeholder.emptyTag) { 100 stream.backUp(1); 101 break; 102 } 103 }; 104 changeContext(state, xrx.richxml.className.notTag); 105 return xrx.richxml.className.notTag; 106 } 107 } 108 109 110 111 return { 112 startState: function() { 113 return { 114 tokenize: parse, 115 context: null 116 }; 117 }, 118 token: function(stream, state) { 119 var style = state.tokenize(stream, state); 120 return style; 121 } 122 }; 123 }); 124 125 126 /** 127 * 128 */ 129 CodeMirror.defineMIME('text/richxml', 'richxml');