--- markup/html/scripting-parser/parser.html 2008/04/20 10:02:43 1.3
+++ markup/html/scripting-parser/parser.html 2008/04/27 11:27:04 1.13
@@ -1,30 +1,73 @@
-Demo of HTML5 Parsing Algorithm with Scripting Enabled
+Live Scripting HTML Parser
+
+
]+)>/, function (s, e) {
- if (p.insertionPoint < s.length) {
+ i.s = i.s.replace (/^<\/([^>]+)(?:>|$)/, function (s, e) {
+ if (p.insertionPoint < s.length ||
+ (p.insertionPoint <= s.length &&
+ s.substring (s.length - 1, 1) != '>')) {
token = {type: 'abort'};
return s;
}
@@ -85,12 +151,36 @@
return '';
});
if (token) return token;
- i.s = i.s.replace (/^<([^>]+)>/, function (s, e) {
- if (p.insertionPoint < s.length) {
+ i.s = i.s.replace (/^<([^>]+)(?:>|$)/, function (s, e) {
+ if (p.insertionPoint < s.length ||
+ (p.insertionPoint <= s.length &&
+ s.substring (s.length - 1, 1) != '>')) {
token = {type: 'abort'};
return s;
}
- token = {type: 'start-tag', value: e.toLowerCase ()};
+ var tagName;
+ var attrs = {};
+ e = e.replace (/^[\S]+/, function (v) {
+ tagName = v.toLowerCase ();
+ 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 '';
});
@@ -120,7 +210,8 @@
} // getNextToken
Parser.prototype.parse = function () {
- log ('start parsing');
+ logIndentLevel++;
+ log ('parse: start');
while (true) {
var token = this.getNextToken ();
@@ -130,6 +221,9 @@
if (token.value == 'script') {
// 1. Create an element for the token in the HTML namespace.
var el = new JSElement (this.doc, token.value);
+ if (token.attrs.async != null) el.async = true;
+ if (token.attrs.defer != null) el.defer = true;
+ if (token.attrs.src != null) el.src = token.attrs.src;
// 2. Mark the element as being "parser-inserted".
el.manakaiParserInserted = true;
@@ -185,11 +279,40 @@
this.openElements[this.openElements.length - 1].appendChild (el);
// 11. Let the insertion point have the value of the old ...
+
+ oldInsertionPoint += this.insertionPoint;
this.setInsertionPoint (oldInsertionPoint);
// 12. If there is a script that will execute as soon as ...
-
+ while (this.scriptExecutedWhenParserResumes) {
+ // 12.1. If the tree construction stage is being called reentrantly
+ if (this.reentrant) {
+ log ('parse: abort (reentrance)');
+ logIndentLevel--;
+ return;
+
+ // 12.2. Otherwise
+ } else {
+ // 1.
+ var script = this.scriptExecutedWhenParserResumes;
+ this.scriptExecutedWhenParserResumes = null;
+
+ // 2. Pause until the script has comp