--- markup/html/scripting-parser/parser.html 2008/04/25 11:40:56 1.5
+++ markup/html/scripting-parser/parser.html 2008/09/20 13:32:45 1.20
@@ -1,14 +1,26 @@
-Demo of HTML5 Parsing Algorithm with Scripting Enabled
+Live Scripting HTML Parser
+
+
]+)(?:>|$)/, function (s, e) {
if (p.insertionPoint < s.length ||
(p.insertionPoint <= s.length &&
- s.substring (s.length - 1, 1) != '>')) {
+ s.substring (s.length - 1, s.length) != '>')) {
token = {type: 'abort'};
return s;
}
@@ -111,7 +163,7 @@
i.s = i.s.replace (/^<([^>]+)(?:>|$)/, function (s, e) {
if (p.insertionPoint < s.length ||
(p.insertionPoint <= s.length &&
- s.substring (s.length - 1, 1) != '>')) {
+ s.substring (s.length - 1, s.length) != '>')) {
token = {type: 'abort'};
return s;
}
@@ -121,11 +173,22 @@
tagName = v.toLowerCase ();
return '';
});
- e = e.replace (/^\s*(\S+)\s*(?:=\s*"([^"]*)"|'([^']*)'|([^"']+))?/,
- function (x, attrName, attrValue1, attrValue2, attrValue3) {
- attrs[attrName] = attrValue1 || attrValue2 || attrValue3;
- return '';
- });
+ while (true) {
+ var m = false;
+ e = e.replace (/^\s*([^\s=]+)\s*(?:=\s*(?:"([^"]*)"|'([^']*)'|([^"'\s]*)))?/,
+ function (x, attrName, attrValue1, attrValue2, attrValue3) {
+ v = attrValue1 || attrValue2 || attrValue3;
+ v = v.replace (/"/g, '"').replace (/'/g, "'")
+ .replace (/&/g, '&');
+ attrs[attrName.toLowerCase ()] = v;
+ m = true;
+ return '';
+ });
+ if (!m) break;
+ }
+ if (e.length) {
+ log ('Broken start tag: "' + e + '"');
+ }
token = {type: 'start-tag', value: tagName, attrs: attrs};
p.insertionPoint -= s.length;
return '';
@@ -156,12 +219,31 @@
} // getNextToken
Parser.prototype.parse = function () {
- log ('start parsing');
+ logIndentLevel++;
+ log ('parse: start');
while (true) {
var token = this.getNextToken ();
log ('token: ' + token.type + ' "' + token.value + '"');
+ if (this.cdataEndTagRequired) {
+ // Generic CDATA parsing algorithm
+
+ if (token.type != 'abort') {
+ // 7.
+ if (token.type == 'end-tag' && token.value == this.endTagName) {
+ // 7.1. Ignores it.
+ //
+ } else {
+ // 7.2. Parse error.
+ log ('Parse error: no ' + this.endTagName + '>');
+ this.nextToken.unshift (token);
+ }
+ this.cdataEndTagRequired = false;
+ continue;
+ }
+ }
+
if (token.type == 'start-tag') {
if (token.value == 'script') {
// 1. Create an element for the token in the HTML namespace.
@@ -174,7 +256,8 @@
el.manakaiParserInserted = true;
// 3. Switch the tokeniser's content model flag to the CDATA state.
- this.parseMode = 'script';
+ this.parseMode = 'cdata';
+ this.endTagName = 'script';
// 4.1. Collect all the character tokens.
while (true) {
@@ -188,15 +271,16 @@
// 4.2. Until it returns a token that is not a character token, or
// until it stops tokenising.
} else if (token.type == 'eof' ||
- (token.type == 'end-tag' && token.value == 'script') ||
+ token.type == 'end-tag' ||
token.type == 'abort') {
// 6. Switched back to the PCDATA state.
this.parseMode = 'pcdata';
// 7.1. If the next token is not an end tag token with ...
- if (token.type != 'end-tag') {
+ if (!(token.type == 'end-tag' && token.value == 'script')) {
// 7.2. This is a parse error.
log ('Parse error: no ' + 'script>');
+ this.nextToken.unshift (token);
// 7.3. Mark the script elemen