Skip to content

Commit

Permalink
feature: Add ability to use HTML fragments (#4812)
Browse files Browse the repository at this point in the history
  • Loading branch information
BenSouchet committed Jun 1, 2022
1 parent d2446d6 commit 5c35ca8
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
31 changes: 23 additions & 8 deletions lib/ace/mode/html/saxparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4949,7 +4949,9 @@ TreeBuilder.prototype.startTokenization = function(tokenizer) {
this.openElements = new ElementStack();
this.activeFormattingElements = [];
this.start();
if (this.context) {
if (this.context) {
// This means user want to setup an HTML fragment

switch(this.context) {
case 'title':
case 'textarea':
Expand All @@ -4973,7 +4975,16 @@ TreeBuilder.prototype.startTokenization = function(tokenizer) {
this.tokenizer.setState(Tokenizer.PLAINTEXT);
break;
}
this.insertHtmlElement();
this.insertHtmlElement();

if (this.context === 'head') {
// In case it's an 'head' fragment, we insert a head DOM element
this.insertHeadElement();
} else {
// Else a body DOM element
this.insertBodyElement();
}

this.resetInsertionMode();
// todo form pointer
} else {
Expand Down Expand Up @@ -5320,13 +5331,14 @@ TreeBuilder.prototype.parseError = function(code, args) {
* Resets the insertion mode (http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#reset-the-insertion-mode-appropriately)
*/
TreeBuilder.prototype.resetInsertionMode = function() {
var last = false;
var fragmentAssigned = false;
var node = null;
for (var i = this.openElements.length - 1; i >= 0; i--) {
node = this.openElements.item(i);
if (i === 0) {
if (i === 0) {
// Normally we enter here if a fragment context has been set
assert.ok(this.context);
last = true;
fragmentAssigned = true;
node = new StackItem("http://www.w3.org/1999/xhtml", this.context, [], null);
}

Expand All @@ -5347,7 +5359,7 @@ TreeBuilder.prototype.resetInsertionMode = function() {
return this.setInsertionMode('inColumnGroup');
if (node.localName === 'table')
return this.setInsertionMode('inTable');
if (node.localName === 'head' && !last)
if (node.localName === 'head')
return this.setInsertionMode('inHead');
if (node.localName === 'body')
return this.setInsertionMode('inBody');
Expand All @@ -5360,7 +5372,7 @@ TreeBuilder.prototype.resetInsertionMode = function() {
return this.setInsertionMode('afterHead');
}

if (last)
if (fragmentAssigned)
return this.setInsertionMode('inBody');
}
};
Expand Down Expand Up @@ -5823,7 +5835,10 @@ function SAXParser() {
this._scriptingEnabled = false;
}

SAXParser.prototype.parse = function(source) {
SAXParser.prototype.parse = function(source, context) {
if (context) {
this._treeBuilder.setFragmentContext(context);
}
this._tokenizer.tokenize(source);
var document = this._treeBuilder.document;
if (document) {
Expand Down
12 changes: 8 additions & 4 deletions lib/ace/mode/html_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ var errorTypes = {
var Worker = exports.Worker = function(sender) {
Mirror.call(this, sender);
this.setTimeout(400);

// The context is currently only used for Fragment
// It's format is an object: {fragmentContext: "body"}
// %Value% need to be a string of a DOM Element type:
// "head" | "body" | "footer" | ...
this.context = null;
};

Expand Down Expand Up @@ -80,10 +85,9 @@ oop.inherits(Worker, Mirror);
});
}
};
if (this.context)
parser.parseFragment(value, this.context);
else
parser.parse(value);

parser.parse(value, this.context);

this.sender.emit("error", errors);
};

Expand Down

0 comments on commit 5c35ca8

Please sign in to comment.