Skip to content

Commit

Permalink
fix: many text related issues
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanPiercey committed Feb 16, 2022
1 parent 6290b71 commit d099009
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 107 deletions.
14 changes: 4 additions & 10 deletions src/core/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ export class Parser {
*/
htmlEOF() {
this.endText();

while (this.blockStack.length) {
const curBlock = peek(this.blockStack)!;
if (curBlock.type === "tag") {
Expand Down Expand Up @@ -426,7 +427,7 @@ export class Parser {
});
}

if (lastTag.beginMixedMode) {
if ((lastTag as OpenTagPart).beginMixedMode) {
this.endingMixedModeAtEOL = true;
}
}
Expand Down Expand Up @@ -513,7 +514,8 @@ export class Parser {
this.htmlBlockIndent! + this.htmlBlockDelimiter;

if (this.lookAheadFor(endHtmlBlockLookahead, this.pos + newLine.length)) {
this.endText();
this.startText(); // we want to at least include the newline as text.
this.endText(newLine.length);
this.skip(endHtmlBlockLookahead.length + newLine.length);

if (this.consumeWhitespaceOnLine(0)) {
Expand Down Expand Up @@ -570,14 +572,6 @@ export class Parser {
}
}

enterJsContentState() {
this.enterParsedTextContentState();
}

enterCssContentState() {
this.enterParsedTextContentState();
}

enterStaticTextContentState() {
const last =
this.blockStack.length && this.blockStack[this.blockStack.length - 1];
Expand Down
5 changes: 4 additions & 1 deletion src/states/CLOSE_TAG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export interface CloseTagPart extends Part {
export const CLOSE_TAG: StateDefinition<CloseTagPart> = {
name: "CLOSE_TAG",

enter() {
this.endText();
},

eof(closeTag) {
this.notifyError(
closeTag,
Expand Down Expand Up @@ -50,7 +54,6 @@ export function checkForClosingTag(parser: Parser) {
parser.endText();
parser.closeTag({ pos: parser.pos, endPos: parser.skip(match.length + 1) });
parser.forward = false;
parser.startText();
return true;
}

Expand Down
4 changes: 1 addition & 3 deletions src/states/CONCISE_HTML_CONTENT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export const CONCISE_HTML_CONTENT: StateDefinition = {
name: "CONCISE_HTML_CONTENT",

eol() {
this.startText();
this.indent = "";
},

Expand Down Expand Up @@ -49,7 +48,7 @@ export const CONCISE_HTML_CONTENT: StateDefinition = {

if (
childState === STATE.JS_COMMENT_BLOCK &&
!this.consumeWhitespaceOnLine()
!this.consumeWhitespaceOnLine(0)
) {
// Make sure there is only whitespace on the line
// after the ending "*/" sequence
Expand Down Expand Up @@ -129,7 +128,6 @@ export const CONCISE_HTML_CONTENT: StateDefinition = {
} else {
parent.nestedIndent = this.indent;
}

}

switch (code) {
Expand Down
4 changes: 4 additions & 0 deletions src/states/DECLARATION.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { CODE, Parser, Part, StateDefinition } from "../internal";
export const DECLARATION: StateDefinition = {
name: "DECLARATION",

enter() {
this.endText();
},

eof(declaration) {
this.notifyError(
declaration,
Expand Down
4 changes: 4 additions & 0 deletions src/states/DTD.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { CODE, StateDefinition } from "../internal";
export const DTD: StateDefinition = {
name: "DTD",

enter() {
this.endText();
},

exit(documentType) {
this.notifiers.notifyDocumentType({
pos: documentType.pos,
Expand Down
4 changes: 4 additions & 0 deletions src/states/HTML_COMMENT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { CODE, StateDefinition } from "../internal";
export const HTML_COMMENT: StateDefinition = {
name: "HTML_COMMENT",

enter() {
this.endText();
},

exit(comment) {
this.notifiers.notifyComment({
pos: comment.pos,
Expand Down
26 changes: 3 additions & 23 deletions src/states/HTML_CONTENT.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
checkForCDATA,
checkForEscapedEscapedPlaceholder,
checkForEscapedPlaceholder,
checkForPlaceholder,
} from ".";
import { checkForCDATA, checkForPlaceholder } from ".";
import {
Parser,
CODE,
Expand All @@ -21,18 +16,15 @@ export const HTML_CONTENT: StateDefinition = {
this.textParseMode = "html";
this.isConcise = false; // Back into non-concise HTML parsing
},
exit() {
this.endText();
},

eol(newLine) {
if (this.beginMixedMode) {
this.beginMixedMode = false;
this.endText();
this.endText(newLine.length);
this.endHtmlBlock();
} else if (this.endingMixedModeAtEOL) {
this.endText();
this.endingMixedModeAtEOL = false;
this.endText();
this.endHtmlBlock();
} else if (this.isWithinSingleLineHtmlBlock) {
// We are parsing "HTML" and we reached the end of the line. If we are within a single
Expand Down Expand Up @@ -60,26 +52,22 @@ export const HTML_CONTENT: StateDefinition = {
const nextCode = this.lookAtCharCodeAhead(1);

if (this.lookAheadFor("!--")) {
this.endText();
this.enterState(STATE.HTML_COMMENT);
this.skip(3);
} else if (nextCode === CODE.EXCLAMATION) {
// something like:
// <!DOCTYPE html>
// NOTE: We already checked for CDATA earlier and <!--
this.endText();
this.enterState(STATE.DTD);
this.skip(1);
} else if (nextCode === CODE.QUESTION) {
// something like:
// <?xml version="1.0"?>
this.endText();
this.enterState(STATE.DECLARATION);
this.skip(1);
} else if (nextCode === CODE.FORWARD_SLASH) {
// something like:
// </html>
this.endText();
this.enterState(STATE.CLOSE_TAG);
this.skip(1);
} else if (
Expand All @@ -94,16 +82,8 @@ export const HTML_CONTENT: StateDefinition = {
// We'll treat this left angle bracket as text
this.startText();
} else {
this.endText();
this.enterState(STATE.OPEN_TAG);
}
} else if (
checkForEscapedEscapedPlaceholder(this, code) ||
checkForEscapedPlaceholder(this, code)
) {
this.endText();
this.skip(1); // TODO: skip based on escaped helper return value.
this.startText();
} else if (
code === CODE.DOLLAR &&
isWhitespaceCode(this.lookAtCharCodeAhead(1)) &&
Expand Down
8 changes: 4 additions & 4 deletions src/states/OPEN_TAG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const OPEN_TAG: StateDefinition<OpenTagPart> = {
this.endingMixedModeAtEOL = false;
this.currentOpenTag = tag;
this.blockStack.push(tag);
this.endText();
},

exit(tag) {
Expand All @@ -72,11 +73,10 @@ export const OPEN_TAG: StateDefinition<OpenTagPart> = {
this.closeTag();
} else {
switch (literalTagName) {
case "script":
this.enterJsContentState();
break;
case "style":
this.enterCssContentState();
case "script":
case "textarea":
this.enterParsedTextContentState();
break;
}
}
Expand Down
20 changes: 2 additions & 18 deletions src/states/PARSED_TEXT_CONTENT.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
checkForCDATA,
checkForClosingTag,
checkForEscapedEscapedPlaceholder,
checkForEscapedPlaceholder,
checkForPlaceholder,
} from ".";
import { checkForCDATA, checkForClosingTag, checkForPlaceholder } from ".";
import { Parser, STATE, CODE, StateDefinition } from "../internal";

// We enter STATE.PARSED_TEXT_CONTENT when we are parsing
Expand Down Expand Up @@ -62,17 +56,7 @@ export const PARSED_TEXT_CONTENT: StateDefinition = {
this.enterState(STATE.TEMPLATE_STRING);
break;
default:
if (
checkForEscapedEscapedPlaceholder(this, code) ||
checkForEscapedPlaceholder(this, code)
) {
this.endText(-1);
this.skip(1);
this.startText();
} else if (!checkForPlaceholder(this, code)) {
this.startText();
}

if (!checkForPlaceholder(this, code)) this.startText();
break;
}
},
Expand Down
70 changes: 28 additions & 42 deletions src/states/PLACEHOLDER.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const PLACEHOLDER: StateDefinition<PlaceholderPart> = {

enter(placeholder) {
placeholder.escape = placeholder.escape !== false;
this.endText();
this.skip(placeholder.escape ? 2 : 3); // skip ${ or $!{
this.enterState(STATE.EXPRESSION, { terminator: "}" });
this.rewind(1);
Expand Down Expand Up @@ -39,58 +40,43 @@ export const PLACEHOLDER: StateDefinition<PlaceholderPart> = {
};

export function checkForPlaceholder(parser: Parser, code: number) {
if (code === CODE.DOLLAR) {
let nextCode = parser.lookAtCharCodeAhead(1);
let escape = true;
let ahead = 0;
let curCode = code;

if (nextCode === CODE.EXCLAMATION) {
escape = false;
nextCode = parser.lookAtCharCodeAhead(2);
}

if (nextCode === CODE.OPEN_CURLY_BRACE) {
parser.endText();
parser.enterState(STATE.PLACEHOLDER, { escape });
return true;
}
while (curCode === CODE.BACK_SLASH) {
curCode = parser.lookAtCharCodeAhead(++ahead);
}

return false;
}
if (curCode === CODE.DOLLAR) {
let escape = true;
curCode = parser.lookAtCharCodeAhead(ahead + 1);

export function checkForEscapedPlaceholder(parser: Parser, code: number) {
// Look for \${ and \$!{
if (code === CODE.BACK_SLASH) {
if (parser.lookAtCharCodeAhead(1) === CODE.DOLLAR) {
if (parser.lookAtCharCodeAhead(2) === CODE.OPEN_CURLY_BRACE) {
return true;
} else if (parser.lookAtCharCodeAhead(2) === CODE.EXCLAMATION) {
if (parser.lookAtCharCodeAhead(3) === CODE.OPEN_CURLY_BRACE) {
return true;
}
}
if (curCode === CODE.EXCLAMATION) {
escape = false;
curCode = parser.lookAtCharCodeAhead(ahead + 2);
}
}

return false;
}
if (curCode === CODE.OPEN_CURLY_BRACE) {
if (ahead) {
const remainder = ahead % 2;
const extra = (ahead + remainder) / 2; // Number of backslashes to omit from output.

export function checkForEscapedEscapedPlaceholder(
parser: Parser,
code: number
) {
// Look for \\${ and \\$!{
if (code === CODE.BACK_SLASH) {
if (parser.lookAtCharCodeAhead(1) === CODE.BACK_SLASH) {
if (parser.lookAtCharCodeAhead(2) === CODE.DOLLAR) {
if (parser.lookAtCharCodeAhead(3) === CODE.OPEN_CURLY_BRACE) {
if (remainder) {
parser.endText();
parser.skip(extra);
parser.startText();
parser.skip(escape ? 2 : 3); // skip the ${ or $!{
return true;
} else if (parser.lookAtCharCodeAhead(3) === CODE.EXCLAMATION) {
if (parser.lookAtCharCodeAhead(4) === CODE.OPEN_CURLY_BRACE) {
return true;
}
} else {
parser.startText();
parser.skip(extra); // include half of the backslashes.
parser.endText();
parser.skip(extra);
}
}

parser.enterState(STATE.PLACEHOLDER, { escape });
return true;
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/states/STATIC_TEXT_CONTENT.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { checkForClosingTag } from ".";
import { Parser, CODE, StateDefinition } from "../internal";
import { Parser, CODE, StateDefinition, isWhitespaceCode } from "../internal";

// We enter STATE.STATIC_TEXT_CONTENT when a listener manually chooses
// to enter this state after seeing an openTag event for a tag
Expand All @@ -10,7 +10,6 @@ export const STATIC_TEXT_CONTENT: StateDefinition = {

enter() {
this.textParseMode = "static-text";
this.startText();
},

exit() {
Expand All @@ -30,17 +29,18 @@ export const STATIC_TEXT_CONTENT: StateDefinition = {
this.endHtmlBlock();
} else if (this.htmlBlockDelimiter) {
this.handleDelimitedBlockEOL(newLine);
} else {
this.startText();
}
},

eof: Parser.prototype.htmlEOF,

char(_, code) {
// See if we need to see if we reached the closing tag.
if (!this.isConcise && code === CODE.OPEN_ANGLE_BRACKET) {
checkForClosingTag(this);
if (
this.isConcise ||
!(code === CODE.OPEN_ANGLE_BRACKET && checkForClosingTag(this))
) {
this.startText();
}
},
};

0 comments on commit d099009

Please sign in to comment.