feat(html): support ie conditional start/end comment (#5470)

master
Ika 2018-11-15 12:35:28 +08:00 committed by GitHub
parent 4f63be05e8
commit 668e049a5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 496 additions and 44 deletions

View File

@ -0,0 +1,80 @@
"use strict";
// https://css-tricks.com/how-to-create-an-ie-only-stylesheet
// <!--[if ... ]> ... <![endif]-->
const IE_CONDITIONAL_START_END_COMMENT_REGEX = /^(\[if([^\]]*?)\]>)([\s\S]*?)<!\s*\[endif\]$/;
// <!--[if ... ]><!-->
const IE_CONDITIONAL_START_COMMENT_REGEX = /^\[if([^\]]*?)\]><!$/;
// <!--<![endif]-->
const IE_CONDITIONAL_END_COMMENT_REGEX = /^<!\s*\[endif\]$/;
const REGEX_PARSE_TUPLES = [
[IE_CONDITIONAL_START_END_COMMENT_REGEX, parseIeConditionalStartEndComment],
[IE_CONDITIONAL_START_COMMENT_REGEX, parseIeConditionalStartComment],
[IE_CONDITIONAL_END_COMMENT_REGEX, parseIeConditionalEndComment]
];
function parseIeConditionalComment(node, parseHtml) {
if (node.value) {
let match;
for (const [regex, parse] of REGEX_PARSE_TUPLES) {
if ((match = node.value.match(regex))) {
return parse(node, parseHtml, match);
}
}
}
return null;
}
function parseIeConditionalStartEndComment(node, parseHtml, match) {
const [, openingTagSuffix, condition, data] = match;
const offset = "<!--".length + openingTagSuffix.length;
const contentStartSpan = node.sourceSpan.start.moveBy(offset);
const contentEndSpan = contentStartSpan.moveBy(data.length);
const ParseSourceSpan = node.sourceSpan.constructor;
const [complete, children] = (() => {
try {
return [true, parseHtml(data, contentStartSpan).children];
} catch (e) {
const text = {
type: "text",
value: data,
sourceSpan: new ParseSourceSpan(contentStartSpan, contentEndSpan)
};
return [false, [text]];
}
})();
return {
type: "ieConditionalComment",
complete,
children,
condition: condition.trim().replace(/\s+/g, " "),
sourceSpan: node.sourceSpan,
startSourceSpan: new ParseSourceSpan(
node.sourceSpan.start,
contentStartSpan
),
endSourceSpan: new ParseSourceSpan(contentEndSpan, node.sourceSpan.end)
};
}
function parseIeConditionalStartComment(node, parseHtml, match) {
const [, condition] = match;
return {
type: "ieConditionalStartComment",
condition: condition.trim().replace(/\s+/g, " "),
sourceSpan: node.sourceSpan
};
}
function parseIeConditionalEndComment(node /*, parseHtml, match */) {
return {
type: "ieConditionalEndComment",
sourceSpan: node.sourceSpan
};
}
module.exports = {
parseIeConditionalComment
};

View File

@ -5,6 +5,7 @@ const { HTML_ELEMENT_ATTRIBUTES, HTML_TAGS } = require("./utils");
const { hasPragma } = require("./pragma");
const createError = require("../common/parser-create-error");
const { Node } = require("./ast");
const { parseIeConditionalComment } = require("./conditional-comment");
function ngHtmlParser(input, canSelfClose) {
const parser = require("angular-html-parser");
@ -240,50 +241,6 @@ function _parse(
});
}
function parseIeConditionalComment(node, parseHtml) {
if (!node.value) {
return null;
}
const match = node.value.match(
/^(\[if([^\]]*?)\]>)([\s\S]*?)<!\s*\[endif\]$/
);
if (!match) {
return null;
}
const [, openingTagSuffix, condition, data] = match;
const offset = "<!--".length + openingTagSuffix.length;
const contentStartSpan = node.sourceSpan.start.moveBy(offset);
const contentEndSpan = contentStartSpan.moveBy(data.length);
const ParseSourceSpan = node.sourceSpan.constructor;
const [complete, children] = (() => {
try {
return [true, parseHtml(data, contentStartSpan).children];
} catch (e) {
const text = {
type: "text",
value: data,
sourceSpan: new ParseSourceSpan(contentStartSpan, contentEndSpan)
};
return [false, [text]];
}
})();
return {
type: "ieConditionalComment",
complete,
children,
condition: condition.trim().replace(/\s+/g, " "),
sourceSpan: node.sourceSpan,
startSourceSpan: new ParseSourceSpan(
node.sourceSpan.start,
contentStartSpan
),
endSourceSpan: new ParseSourceSpan(contentEndSpan, node.sourceSpan.end)
};
}
function locStart(node) {
return node.sourceSpan.start.offset;
}

View File

@ -12,6 +12,7 @@ const {
const PREPROCESS_PIPELINE = [
removeIgnorableFirstLf,
mergeIeConditonalStartEndCommentIntoElementOpeningTag,
mergeCdataIntoText,
extractInterpolation,
extractWhitespaces,
@ -52,6 +53,70 @@ function removeIgnorableFirstLf(ast /*, options */) {
});
}
function mergeIeConditonalStartEndCommentIntoElementOpeningTag(
ast /*, options */
) {
/**
* <!--[if ...]><!--><target><!--<![endif]-->
*/
const isTarget = node =>
node.type === "element" &&
node.prev &&
node.prev.type === "ieConditionalStartComment" &&
node.prev.sourceSpan.end.offset === node.startSourceSpan.start.offset &&
node.firstChild &&
node.firstChild.type === "ieConditionalEndComment" &&
node.firstChild.sourceSpan.start.offset === node.startSourceSpan.end.offset;
return ast.map(node => {
if (node.children) {
const isTargetResults = node.children.map(isTarget);
if (isTargetResults.some(Boolean)) {
const newChildren = [];
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if (isTargetResults[i + 1]) {
// ieConditionalStartComment
continue;
}
if (isTargetResults[i]) {
const ieConditionalStartComment = child.prev;
const ieConditionalEndComment = child.firstChild;
const ParseSourceSpan = child.sourceSpan.constructor;
const startSourceSpan = new ParseSourceSpan(
ieConditionalStartComment.sourceSpan.start,
ieConditionalEndComment.sourceSpan.end
);
const sourceSpan = new ParseSourceSpan(
startSourceSpan.start,
child.sourceSpan.end
);
newChildren.push(
child.clone({
condition: ieConditionalStartComment.condition,
sourceSpan,
startSourceSpan,
children: child.children.slice(1)
})
);
continue;
}
newChildren.push(child);
}
return node.clone({ children: newChildren });
}
}
return node;
});
}
function mergeNodeIntoText(ast, shouldMerge, getValue) {
return ast.map(node => {
if (node.children) {

View File

@ -248,6 +248,9 @@ function genericPrint(path, options, print) {
printClosingTag(node)
]);
}
case "ieConditionalStartComment":
case "ieConditionalEndComment":
return concat([printOpeningTagStart(node), printClosingTagEnd(node)]);
case "interpolation":
return concat([
printOpeningTagStart(node),
@ -765,11 +768,19 @@ function printOpeningTagStartMarker(node) {
case "comment":
return "<!--";
case "ieConditionalComment":
case "ieConditionalStartComment":
return `<!--[if ${node.condition}`;
case "ieConditionalEndComment":
return `<!--<!`;
case "interpolation":
return "{{";
case "docType":
return "<!DOCTYPE";
case "element":
if (node.condition) {
return `<!--[if ${node.condition}]><!--><${node.rawName}`;
}
// fall through
default:
return `<${node.rawName}`;
}
@ -780,6 +791,11 @@ function printOpeningTagEndMarker(node) {
switch (node.type) {
case "ieConditionalComment":
return "]>";
case "element":
if (node.condition) {
return `><!--<![endif]-->`;
}
// fall through
default:
return `>`;
}
@ -806,7 +822,10 @@ function printClosingTagEndMarker(node) {
case "comment":
return "-->";
case "ieConditionalComment":
case "ieConditionalEndComment":
return `[endif]-->`;
case "ieConditionalStartComment":
return `]><!-->`;
case "interpolation":
return "}}";
case "element":

View File

@ -99,6 +99,35 @@ exports[`conditional.html - html-verify 1`] = `
<!--[if (gte mso 9)|(IE)]></td></tr></table><![endif]-->
</center >
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!--><html><head><!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9
]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<!DOCTYPE html>
<html>
@ -140,6 +169,37 @@ exports[`conditional.html - html-verify 1`] = `
</center>
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!-->
<html>
<head>
<!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
`;
exports[`conditional.html - html-verify 2`] = `
@ -184,6 +244,35 @@ exports[`conditional.html - html-verify 2`] = `
<!--[if (gte mso 9)|(IE)]></td></tr></table><![endif]-->
</center >
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!--><html><head><!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9
]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
~
<!DOCTYPE html>
<html>
@ -259,6 +348,39 @@ exports[`conditional.html - html-verify 2`] = `
</center>
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html
hello
><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!-->
<html>
<head>
<!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
`;
exports[`conditional.html - html-verify 3`] = `
@ -303,6 +425,35 @@ exports[`conditional.html - html-verify 3`] = `
<!--[if (gte mso 9)|(IE)]></td></tr></table><![endif]-->
</center >
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!--><html><head><!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9
]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<!DOCTYPE html>
<html>
@ -344,6 +495,37 @@ exports[`conditional.html - html-verify 3`] = `
</center>
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!-->
<html>
<head>
<!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
`;
exports[`conditional.html - html-verify 4`] = `
@ -388,6 +570,35 @@ exports[`conditional.html - html-verify 4`] = `
<!--[if (gte mso 9)|(IE)]></td></tr></table><![endif]-->
</center >
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!--><html><head><!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9
]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<!DOCTYPE html>
<html>
@ -429,6 +640,37 @@ exports[`conditional.html - html-verify 4`] = `
</center>
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9
]><!--><html
><head
><!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
`;
exports[`conditional.html - html-verify 5`] = `
@ -473,6 +715,35 @@ exports[`conditional.html - html-verify 5`] = `
<!--[if (gte mso 9)|(IE)]></td></tr></table><![endif]-->
</center >
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!--><html><head><!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9
]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<!DOCTYPE html>
<html>
@ -529,6 +800,37 @@ exports[`conditional.html - html-verify 5`] = `
</center>
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!-->
<html>
<head>
<!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
`;
exports[`for_debugging.html - html-verify 1`] = `

View File

@ -39,3 +39,32 @@
<!--[if (gte mso 9)|(IE)]></td></tr></table><![endif]-->
</center >
</body>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9]><!--><html hello><!--<![endif]-->
<head></head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><head><![endif]-->
<!--[if gte IE 9]><!--><html><head><!--<![endif]-->
</head>
<body></body>
</html>
<!DOCTYPE html>
<!--[if lt IE 9]><html class="legacy-ie"><![endif]-->
<!--[if gte IE 9
]><!--><html><!--<![endif]-->
<head></head>
<body></body>
</html>