Parent Directory
|
Revision Log
|
Patch
| revision 1.1 by wakaba, Sun Apr 20 06:07:24 2008 UTC | revision 1.5 by wakaba, Fri Apr 25 11:40:56 2008 UTC | |
|---|---|---|
| # | Line 13 | Line 13 |
| 13 | output { | output { |
| 14 | display: block; | display: block; |
| 15 | font-family: monospace; | font-family: monospace; |
| 16 | white-space: pre; | white-space: -moz-pre-wrap; |
| 17 | white-space: pre-wrap; | |
| 18 | } | } |
| 19 | </style> | </style> |
| 20 | <script> | <script> |
| 21 | function update () { | function update () { |
| 22 | document.logElement.textContent = ''; | document.logElement.textContent = ''; |
| 23 | var p = new Parser (); | var p = new Parser (new InputStream (document.sourceElement.value)); |
| 24 | p.parse (new InputStream (document.sourceElement.value)); | var doc = p.doc; |
| 25 | log (dumpTree (p.doc, '')); | p.parse (); |
| 26 | log (dumpTree (doc, '')); | |
| 27 | } // update | } // update |
| 28 | ||
| 29 | function log (s) { | function log (s) { |
| # | Line 32 | Line 34 |
| 34 | this.s = s; | this.s = s; |
| 35 | } // InputStream | } // InputStream |
| 36 | ||
| 37 | function Parser () { | function Parser (i, doc) { |
| 38 | this.parseMode = 'pcdata'; | this.parseMode = 'pcdata'; |
| 39 | this.doc = new JSDocument (); | if (!doc) { |
| 40 | this.openElements = [this.doc]; | doc = new JSDocument (this); |
| 41 | doc.manakaiIsHTML = true; | |
| 42 | } | |
| 43 | this.doc = doc; | |
| 44 | this.openElements = [doc]; | |
| 45 | this.in = i; | |
| 46 | this.scriptsExecutedAfterParsing = []; | |
| 47 | } // Parser | } // Parser |
| 48 | ||
| 49 | Parser.prototype.getNextToken = function (i) { | Parser.prototype.getNextToken = function () { |
| 50 | var p = this; | |
| 51 | var i = this.in; | |
| 52 | if (this.parseMode == 'script') { | if (this.parseMode == 'script') { |
| 53 | var token; | var token; |
| 54 | i.s = i.s.replace (/^([\s\S]+?)<\/[Ss][Cc][Rr][Ii][Pp][Tt]>/, | if (p.insertionPoint <= 0) { |
| 55 | return {type: 'abort'}; | |
| 56 | } | |
| 57 | i.s = i.s.replace (/^([^<]+)/, | |
| 58 | function (s, t) { | function (s, t) { |
| 59 | if (0 < p.insertionPoint && p.insertionPoint < t.length) { | |
| 60 | token = {type: 'char', value: t.substring (0, p.insertionPoint)}; | |
| 61 | var ip = p.insertionPoint; | |
| 62 | p.insertionPoint = 0; | |
| 63 | return t.substring (ip, t.length); | |
| 64 | } | |
| 65 | token = {type: 'char', value: t}; | token = {type: 'char', value: t}; |
| 66 | return '<' + '/script>'; | p.insertionPoint -= t.length; |
| 67 | return ''; | |
| 68 | }); | }); |
| 69 | if (token) return token; | if (token) return token; |
| 70 | i.s = i.s.replace (/^<\/[Ss][Cc][Rr][Ii][Pp][Tt]>/, function () { | i.s = i.s.replace (/^<\/[Ss][Cc][Rr][Ii][Pp][Tt]>/, function (s) { |
| 71 | if (p.insertionPoint < s.length) { | |
| 72 | token = {type: 'abort'}; | |
| 73 | return s; | |
| 74 | } | |
| 75 | token = {type: 'end-tag', value: 'script'}; | token = {type: 'end-tag', value: 'script'}; |
| 76 | p.insertionPoint -= s.length; | |
| 77 | return ''; | |
| 78 | }); | |
| 79 | if (token) return token; | |
| 80 | var m; | |
| 81 | if ((p.insertionPoint < '</script'.length) && | |
| 82 | (m = i.s.match (/^<\/([SCRIPTscript]+)/))) { | |
| 83 | var v = m[1].substring (0, p.insertionPoint).toLowerCase (); | |
| 84 | if (v == 'script'.substring (0, p.insertionPoint - '</'.length)) { | |
| 85 | return {type: 'abort'}; | |
| 86 | } | |
| 87 | } | |
| 88 | i.s = i.s.replace (/^</, | |
| 89 | function (s) { | |
| 90 | token = {type: 'char', value: s}; | |
| 91 | p.insertionPoint -= s.length; | |
| 92 | return ''; | return ''; |
| 93 | }); | }); |
| 94 | if (token) return token; | if (token) return token; |
| # | Line 56 | Line 96 |
| 96 | } | } |
| 97 | ||
| 98 | var token; | var token; |
| 99 | i.s = i.s.replace (/^<\/([^>]+)>/, function (s, e) { | i.s = i.s.replace (/^<\/([^>]+)(?:>|$)/, function (s, e) { |
| 100 | if (p.insertionPoint < s.length || | |
| 101 | (p.insertionPoint <= s.length && | |
| 102 | s.substring (s.length - 1, 1) != '>')) { | |
| 103 | token = {type: 'abort'}; | |
| 104 | return s; | |
| 105 | } | |
| 106 | token = {type: 'end-tag', value: e.toLowerCase ()}; | token = {type: 'end-tag', value: e.toLowerCase ()}; |
| 107 | p.insertionPoint -= s.length; | |
| 108 | return ''; | return ''; |
| 109 | }); | }); |
| 110 | if (token) return token; | if (token) return token; |
| 111 | i.s = i.s.replace (/^<([^>]+)>/, function (s, e) { | i.s = i.s.replace (/^<([^>]+)(?:>|$)/, function (s, e) { |
| 112 | token = {type: 'start-tag', value: e.toLowerCase ()}; | if (p.insertionPoint < s.length || |
| 113 | (p.insertionPoint <= s.length && | |
| 114 | s.substring (s.length - 1, 1) != '>')) { | |
| 115 | token = {type: 'abort'}; | |
| 116 | return s; | |
| 117 | } | |
| 118 | var tagName; | |
| 119 | var attrs = {}; | |
| 120 | e = e.replace (/^[\S]+/, function (v) { | |
| 121 | tagName = v.toLowerCase (); | |
| 122 | return ''; | |
| 123 | }); | |
| 124 | e = e.replace (/^\s*(\S+)\s*(?:=\s*"([^"]*)"|'([^']*)'|([^"']+))?/, | |
| 125 | function (x, attrName, attrValue1, attrValue2, attrValue3) { | |
| 126 | attrs[attrName] = attrValue1 || attrValue2 || attrValue3; | |
| 127 | return ''; | |
| 128 | }); | |
| 129 | token = {type: 'start-tag', value: tagName, attrs: attrs}; | |
| 130 | p.insertionPoint -= s.length; | |
| 131 | return ''; | return ''; |
| 132 | }); | }); |
| 133 | if (token) return token; | if (token) return token; |
| 134 | if (p.insertionPoint <= 0) { | |
| 135 | return {type: 'abort'}; | |
| 136 | } | |
| 137 | i.s = i.s.replace (/^[^<]+/, function (s) { | i.s = i.s.replace (/^[^<]+/, function (s) { |