@shopify/prettier-plugin-liquid
Version:
Prettier Liquid/HTML plugin by Shopify
271 lines • 12.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLastDescendant = exports.hasMeaningfulLackOfDanglingWhitespace = exports.hasMeaningfulLackOfTrailingWhitespace = exports.hasMeaningfulLackOfLeadingWhitespace = exports.preferHardlineAsTrailingSpaces = exports.preferHardlineAsLeadingSpaces = exports.preferHardlineAsSurroundingSpaces = exports.forceBreakChildren = exports.forceBreakContent = exports.forceNextEmptyLine = exports.isPrettierIgnoreAttributeNode = exports.hasPrettierIgnore = exports.isPrettierIgnoreNode = exports.isPrettierIgnoreLiquidNode = exports.isPrettierIgnoreHtmlNode = exports.shouldPreserveContent = exports.hasNonTextChild = exports.isAttributeNode = exports.isHtmlNode = exports.isMultilineLiquidTag = exports.isLiquidNode = exports.isTextLikeNode = exports.isHtmlElement = exports.isVoidElement = exports.isSelfClosing = exports.isHtmlComment = exports.isHtmlDanglingMarkerClose = exports.isHtmlDanglingMarkerOpen = exports.hasNoChildren = exports.hasNoCloseMarker = exports.isPreLikeNode = exports.isScriptLikeTag = void 0;
const liquid_html_parser_1 = require("@shopify/liquid-html-parser");
const array_1 = require("./array");
function isScriptLikeTag(node) {
return node.type === liquid_html_parser_1.NodeTypes.HtmlRawNode;
}
exports.isScriptLikeTag = isScriptLikeTag;
function isPreLikeNode(node) {
return node.cssWhitespace.startsWith('pre');
}
exports.isPreLikeNode = isPreLikeNode;
// A bit like self-closing except we distinguish between them.
// Comments are also considered self-closing.
function hasNoCloseMarker(node) {
return hasNoChildren(node) || isHtmlDanglingMarkerOpen(node);
}
exports.hasNoCloseMarker = hasNoCloseMarker;
function hasNoChildren(node) {
return (isSelfClosing(node) ||
isVoidElement(node) ||
isHtmlComment(node) ||
isHtmlDanglingMarkerClose(node));
}
exports.hasNoChildren = hasNoChildren;
function isHtmlDanglingMarkerOpen(node) {
return (node.type === liquid_html_parser_1.NodeTypes.HtmlElement && node.blockEndPosition.start === node.blockEndPosition.end);
}
exports.isHtmlDanglingMarkerOpen = isHtmlDanglingMarkerOpen;
function isHtmlDanglingMarkerClose(node) {
return node.type === liquid_html_parser_1.NodeTypes.HtmlDanglingMarkerClose;
}
exports.isHtmlDanglingMarkerClose = isHtmlDanglingMarkerClose;
function isHtmlComment(node) {
return node.type === liquid_html_parser_1.NodeTypes.HtmlComment;
}
exports.isHtmlComment = isHtmlComment;
function isSelfClosing(node) {
return node.type === liquid_html_parser_1.NodeTypes.HtmlSelfClosingElement;
}
exports.isSelfClosing = isSelfClosing;
function isVoidElement(node) {
return node.type === liquid_html_parser_1.NodeTypes.HtmlVoidElement;
}
exports.isVoidElement = isVoidElement;
function isHtmlElement(node) {
return node.type === liquid_html_parser_1.NodeTypes.HtmlElement;
}
exports.isHtmlElement = isHtmlElement;
function isTextLikeNode(node) {
return !!node && node.type === liquid_html_parser_1.NodeTypes.TextNode;
}
exports.isTextLikeNode = isTextLikeNode;
function isLiquidNode(node) {
return !!node && liquid_html_parser_1.LiquidNodeTypes.includes(node.type);
}
exports.isLiquidNode = isLiquidNode;
function isMultilineLiquidTag(node) {
return !!node && node.type === liquid_html_parser_1.NodeTypes.LiquidTag && !!node.children && !(0, array_1.isEmpty)(node.children);
}
exports.isMultilineLiquidTag = isMultilineLiquidTag;
function isHtmlNode(node) {
return !!node && liquid_html_parser_1.HtmlNodeTypes.includes(node.type);
}
exports.isHtmlNode = isHtmlNode;
function isAttributeNode(node) {
return (isHtmlNode(node.parentNode) &&
'attributes' in node.parentNode &&
node.parentNode.attributes.indexOf(node) !== -1);
}
exports.isAttributeNode = isAttributeNode;
function hasNonTextChild(node) {
return (node.children &&
node.children.some((child) => child.type !== liquid_html_parser_1.NodeTypes.TextNode));
}
exports.hasNonTextChild = hasNonTextChild;
function shouldPreserveContent(node) {
// // unterminated node in ie conditional comment
// // e.g. <!--[if lt IE 9]><html><![endif]-->
// if (
// node.type === "ieConditionalComment" &&
// node.lastChild &&
// !node.lastChild.isSelfClosing &&
// !node.lastChild.endSourceSpan
// ) {
// return true;
// }
// // incomplete html in ie conditional comment
// // e.g. <!--[if lt IE 9]></div><![endif]-->
// if (node.type === "ieConditionalComment" && !node.complete) {
// return true;
// }
// TODO: Handle pre correctly?
if (isPreLikeNode(node)) {
return true;
}
return false;
}
exports.shouldPreserveContent = shouldPreserveContent;
function isPrettierIgnoreHtmlNode(node) {
return (!!node && node.type === liquid_html_parser_1.NodeTypes.HtmlComment && /^\s*prettier-ignore(?=\s|$)/m.test(node.body));
}
exports.isPrettierIgnoreHtmlNode = isPrettierIgnoreHtmlNode;
function isPrettierIgnoreLiquidNode(node) {
return (!!node &&
node.type === liquid_html_parser_1.NodeTypes.LiquidTag &&
node.name === '#' &&
/^\s*prettier-ignore(?=\s|$)/m.test(node.markup));
}
exports.isPrettierIgnoreLiquidNode = isPrettierIgnoreLiquidNode;
function isPrettierIgnoreNode(node) {
return isPrettierIgnoreLiquidNode(node) || isPrettierIgnoreHtmlNode(node);
}
exports.isPrettierIgnoreNode = isPrettierIgnoreNode;
function hasPrettierIgnore(node) {
return isPrettierIgnoreNode(node) || isPrettierIgnoreNode(node.prev);
}
exports.hasPrettierIgnore = hasPrettierIgnore;
function getPrettierIgnoreAttributeCommentData(value) {
const match = value.trim().match(/prettier-ignore-attribute(?:s?)(?:\s+(.+))?$/s);
if (!match) {
return false;
}
if (!match[1]) {
return true;
}
// TODO We should support 'prettier-ignore-attribute a,b,c' and allow users to not
// format the insides of some attributes.
//
// But since we don't reformat the insides of attributes yet (because of
// issue #4), that feature doesn't really make sense.
//
// For now, we'll only support `prettier-ignore-attribute`
//
// https://github.com/Shopify/prettier-plugin-liquid/issues/4
//
// return match[1].split(/\s+/);
return true;
}
function isPrettierIgnoreAttributeNode(node) {
if (!node)
return false;
if (node.type === liquid_html_parser_1.NodeTypes.HtmlComment) {
return getPrettierIgnoreAttributeCommentData(node.body);
}
if (node.type === liquid_html_parser_1.NodeTypes.LiquidTag && node.name === '#') {
return getPrettierIgnoreAttributeCommentData(node.markup);
}
return false;
}
exports.isPrettierIgnoreAttributeNode = isPrettierIgnoreAttributeNode;
function forceNextEmptyLine(node) {
if (!node)
return false;
if (!node.next)
return false;
const source = node.source;
// Current implementation: force next empty line when two consecutive
// lines exist between nodes.
let tmp;
tmp = source.indexOf('\n', node.position.end);
if (tmp === -1)
return false;
tmp = source.indexOf('\n', tmp + 1);
if (tmp === -1)
return false;
return tmp < node.next.position.start;
}
exports.forceNextEmptyLine = forceNextEmptyLine;
/** firstChild leadingSpaces and lastChild trailingSpaces */
function forceBreakContent(node) {
return (forceBreakChildren(node) ||
(node.type === liquid_html_parser_1.NodeTypes.HtmlElement &&
node.children.length > 0 &&
(isTagNameIncluded(['body', 'script', 'style'], node.name) ||
node.children.some((child) => hasNonTextChild(child)))) ||
(node.firstChild &&
node.firstChild === node.lastChild &&
node.firstChild.type !== liquid_html_parser_1.NodeTypes.TextNode &&
hasLeadingLineBreak(node.firstChild) &&
(!node.lastChild.isTrailingWhitespaceSensitive || hasTrailingLineBreak(node.lastChild))));
}
exports.forceBreakContent = forceBreakContent;
/** spaces between children */
function forceBreakChildren(node) {
return (node.type === liquid_html_parser_1.NodeTypes.HtmlElement &&
node.children.length > 0 &&
(isTagNameIncluded(['html', 'head', 'ul', 'ol', 'select'], node.name) ||
(node.cssDisplay.startsWith('table') && node.cssDisplay !== 'table-cell')));
}
exports.forceBreakChildren = forceBreakChildren;
function preferHardlineAsSurroundingSpaces(node) {
switch (node.type) {
// case 'ieConditionalComment':
case liquid_html_parser_1.NodeTypes.HtmlComment:
return true;
case liquid_html_parser_1.NodeTypes.HtmlElement:
return isTagNameIncluded(['script', 'select'], node.name);
case liquid_html_parser_1.NodeTypes.LiquidTag:
if ((node.prev && isTextLikeNode(node.prev)) || (node.next && isTextLikeNode(node.next))) {
return false;
}
return node.children && node.children.length > 0;
}
return false;
}
exports.preferHardlineAsSurroundingSpaces = preferHardlineAsSurroundingSpaces;
function preferHardlineAsLeadingSpaces(node) {
return (preferHardlineAsSurroundingSpaces(node) ||
(isLiquidNode(node) && node.prev && isLiquidNode(node.prev)) ||
(node.prev && preferHardlineAsTrailingSpaces(node.prev)) ||
hasSurroundingLineBreak(node));
}
exports.preferHardlineAsLeadingSpaces = preferHardlineAsLeadingSpaces;
function preferHardlineAsTrailingSpaces(node) {
return (preferHardlineAsSurroundingSpaces(node) ||
(isLiquidNode(node) && node.next && (isLiquidNode(node.next) || isHtmlNode(node.next))) ||
(node.type === liquid_html_parser_1.NodeTypes.HtmlElement && isTagNameIncluded(['br'], node.name)) ||
hasSurroundingLineBreak(node));
}
exports.preferHardlineAsTrailingSpaces = preferHardlineAsTrailingSpaces;
function hasMeaningfulLackOfLeadingWhitespace(node) {
return node.isLeadingWhitespaceSensitive && !node.hasLeadingWhitespace;
}
exports.hasMeaningfulLackOfLeadingWhitespace = hasMeaningfulLackOfLeadingWhitespace;
function hasMeaningfulLackOfTrailingWhitespace(node) {
return node.isTrailingWhitespaceSensitive && !node.hasTrailingWhitespace;
}
exports.hasMeaningfulLackOfTrailingWhitespace = hasMeaningfulLackOfTrailingWhitespace;
function hasMeaningfulLackOfDanglingWhitespace(node) {
return node.isDanglingWhitespaceSensitive && !node.hasDanglingWhitespace;
}
exports.hasMeaningfulLackOfDanglingWhitespace = hasMeaningfulLackOfDanglingWhitespace;
function hasSurroundingLineBreak(node) {
return hasLeadingLineBreak(node) && hasTrailingLineBreak(node);
}
function hasLeadingLineBreak(node) {
if (node.type === liquid_html_parser_1.NodeTypes.Document)
return false;
return (node.hasLeadingWhitespace &&
hasLineBreakInRange(node.source, node.prev
? node.prev.position.end
: node.parentNode.blockStartPosition
? node.parentNode.blockStartPosition.end
: node.parentNode.position.start, node.position.start));
}
function hasTrailingLineBreak(node) {
if (node.type === liquid_html_parser_1.NodeTypes.Document)
return false;
return (node.hasTrailingWhitespace &&
hasLineBreakInRange(node.source, node.position.end, node.next
? node.next.position.start
: node.parentNode.blockEndPosition
? node.parentNode.blockEndPosition.start
: node.parentNode.position.end));
}
function hasLineBreakInRange(source, start, end) {
const index = source.indexOf('\n', start);
return index !== -1 && index < end;
}
function getLastDescendant(node) {
return node.lastChild ? getLastDescendant(node.lastChild) : node;
}
exports.getLastDescendant = getLastDescendant;
function isTagNameIncluded(collection, name) {
if (name.length !== 1 || name[0].type !== liquid_html_parser_1.NodeTypes.TextNode)
return false;
return collection.includes(name[0].value);
}
//# sourceMappingURL=node.js.map