/[suikacvs]/markup/html/scripting-parser/parser.html
Suika

Diff of /markup/html/scripting-parser/parser.html

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

<
revision 1.9 by wakaba, Sun Apr 27 09:16:11 2008 UTC revision 1.14 by wakaba, Tue Apr 29 02:50:00 2008 UTC
# Line 2  Line 2 
2  <html lang=en>  <html lang=en>
3  <head>  <head>
4  <title>Live Scripting HTML Parser</title>  <title>Live Scripting HTML Parser</title>
5    <link rel=author href="http://suika.fam.cx/~wakaba/who?">
6    <link rel=license href="http://suika.fam.cx/c/gnu/gpl"
7        title="GNU GPL2 or later">
8  <style>  <style>
9    h1, h2 {    h1 {
10        margin: 0;
11        font-size: 150%;
12      }
13      h2 {
14      margin: 0;      margin: 0;
15      font-size: 100%;      font-size: 100%;
16    }    }
17    p, pre {    p {
18      margin: 0;      margin: 0 1em;
19    }    }
20    textarea {    textarea {
21      width: 100%;      width: 100%;
# Line 47  Line 54 
54        var p = new Parser (new InputStream (v));        var p = new Parser (new InputStream (v));
55        var doc = p.doc;        var doc = p.doc;
56        p.parse ();        p.parse ();
57          
58        log (dumpTree (doc, ''));        log (dumpTree (doc, ''));
59          
60          if (p.hasAsyncScript) {
61            log ('Some script codes are executed asynchronously; it means that the document might be rendered in different ways depending on the network condition and other factors');
62          }
63      }      }
64    } // update2    } // update2
65    
# Line 73  Line 85 
85      this.openElements = [doc];      this.openElements = [doc];
86      this.input = i;      this.input = i;
87      this.scriptsExecutedAfterParsing = [];      this.scriptsExecutedAfterParsing = [];
88        this.scriptsExecutedSoon = [];
89        this.scriptsExecutedAsynchronously = [];
90    } // Parser    } // Parser
91    
92    Parser.prototype.getNextToken = function () {    Parser.prototype.getNextToken = function () {
93      var p = this;      var p = this;
94      var i = this.input;      var i = this.input;
95      if (this.parseMode == 'script') {      if (this.parseMode == 'cdata') {
96          var tagName = this.endTagName;
97        var token;        var token;
98        if (p.insertionPoint <= 0) {        if (p.insertionPoint <= 0) {
99          return {type: 'abort'};          return {type: 'abort'};
# Line 96  Line 111 
111          return '';          return '';
112        });        });
113        if (token) return token;        if (token) return token;
114        i.s = i.s.replace (/^<\/[Ss][Cc][Rr][Ii][Pp][Tt]>/, function (s) {        var pattern = new RegExp ('^</' + tagName + '>', 'i');
115          i.s = i.s.replace (pattern, function (s) {
116          if (p.insertionPoint < s.length) {          if (p.insertionPoint < s.length) {
117            token = {type: 'abort'};            token = {type: 'abort'};
118            return s;            return s;
119          }          }
120          token = {type: 'end-tag', value: 'script'};          token = {type: 'end-tag', value: tagName};
121          p.insertionPoint -= s.length;          p.insertionPoint -= s.length;
122          return '';          return '';
123        });        });
124        if (token) return token;        if (token) return token;
125        var m;        var m;
126        if ((p.insertionPoint < '</script'.length) &&        if ((p.insertionPoint < ('</' + tagName).length) &&
127            (m = i.s.match (/^<\/([SCRIPTscript]+)/))) {            (m = i.s.match (/^<\/([A-Za-z]+)/))) {
128          var v = m[1].substring (0, p.insertionPoint).toLowerCase ();          var v = m[1].substring (0, p.insertionPoint).toLowerCase ();
129          if (v == 'script'.substring (0, p.insertionPoint - '</'.length)) {          if (v == tagName.substring (0, p.insertionPoint - '</'.length)) {
130            return {type: 'abort'};            return {type: 'abort'};
131          }          }
132        }        }
# Line 215  Line 231 
231            el.manakaiParserInserted = true;            el.manakaiParserInserted = true;
232    
233            // 3. Switch the tokeniser's content model flag to the CDATA state.            // 3. Switch the tokeniser's content model flag to the CDATA state.
234            this.parseMode = 'script';            this.parseMode = 'cdata';
235              this.endTagName = 'script';
236    
237            // 4.1. Collect all the character tokens.            // 4.1. Collect all the character tokens.
238            while (true) {            while (true) {
# Line 229  Line 246 
246              // 4.2. Until it returns a token that is not a character token, or              // 4.2. Until it returns a token that is not a character token, or
247              // until it stops tokenising.              // until it stops tokenising.
248              } else if (token.type == 'eof' ||              } else if (token.type == 'eof' ||
249                         (token.type == 'end-tag' && token.value == 'script') ||                         token.type == 'end-tag' ||
250                         token.type == 'abort') {                         token.type == 'abort') {
251                // 6. Switched back to the PCDATA state.                // 6. Switched back to the PCDATA state.
252                this.parseMode = 'pcdata';                this.parseMode = 'pcdata';
253