103 lines
4.0 KiB
JavaScript
103 lines
4.0 KiB
JavaScript
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
const doc_1 = require("prettier/doc");
|
||
|
const { dedentToRoot, group, hardline, indent, join, line, literalline, softline } = doc_1.builders;
|
||
|
// Replace the string content newlines within a doc tree with literallines so
|
||
|
// that all of the indentation lines up appropriately
|
||
|
function replaceNewlines(doc) {
|
||
|
return doc_1.utils.mapDoc(doc, (currentDoc) => typeof currentDoc === "string" && currentDoc.includes("\n")
|
||
|
? currentDoc.split(/(\n)/g).map((v, i) => (i % 2 === 0 ? v : literalline))
|
||
|
: currentDoc);
|
||
|
}
|
||
|
// Get the start and end element tags from the current node on the tree
|
||
|
function getElementTags(path, opts, print) {
|
||
|
const node = path.getValue();
|
||
|
const { OPEN, Name, attribute, START_CLOSE, SLASH_OPEN, END_NAME, END } = node.children;
|
||
|
const parts = [OPEN[0].image, Name[0].image];
|
||
|
if (attribute) {
|
||
|
parts.push(indent([line, join(line, path.map(print, "children", "attribute"))]));
|
||
|
}
|
||
|
if (!opts.bracketSameLine) {
|
||
|
parts.push(softline);
|
||
|
}
|
||
|
return {
|
||
|
openTag: group([...parts, START_CLOSE[0].image]),
|
||
|
closeTag: group([SLASH_OPEN[0].image, END_NAME[0].image, END[0].image])
|
||
|
};
|
||
|
}
|
||
|
// Get the name of the parser that is represented by the given element node,
|
||
|
// return null if a matching parser cannot be found
|
||
|
function getParser(node, opts) {
|
||
|
const { Name, attribute } = node.children;
|
||
|
const parser = Name[0].image.toLowerCase();
|
||
|
// We don't want to deal with some weird recursive parser situation, so we
|
||
|
// need to explicitly call out the XML parser here and just return null
|
||
|
if (parser === "xml") {
|
||
|
return null;
|
||
|
}
|
||
|
// If this is a style tag with a text/css type, then we can skip straight to
|
||
|
// saying that this needs a CSS parser
|
||
|
if (parser === "style" &&
|
||
|
attribute &&
|
||
|
attribute.some((attr) => attr.children.Name[0].image === "type" &&
|
||
|
attr.children.STRING[0].image === '"text/css"')) {
|
||
|
return "css";
|
||
|
}
|
||
|
// If there is a plugin that has a parser that matches the name of this
|
||
|
// element, then we're going to assume that's correct for embedding and go
|
||
|
// ahead and switch to that parser
|
||
|
if (opts.plugins.some((plugin) => typeof plugin !== "string" &&
|
||
|
plugin.parsers &&
|
||
|
Object.prototype.hasOwnProperty.call(plugin.parsers, parser))) {
|
||
|
return parser;
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
// Get the source string that will be passed into the embedded parser from the
|
||
|
// content of the inside of the element node
|
||
|
function getSource(content) {
|
||
|
return content.chardata
|
||
|
.map((node) => {
|
||
|
const { SEA_WS, TEXT } = node.children;
|
||
|
const [{ image }] = SEA_WS || TEXT;
|
||
|
return {
|
||
|
offset: node.location.startOffset,
|
||
|
printed: image
|
||
|
};
|
||
|
})
|
||
|
.sort(({ offset }) => offset)
|
||
|
.map(({ printed }) => printed)
|
||
|
.join("");
|
||
|
}
|
||
|
const embed = (path, print, textToDoc, opts) => {
|
||
|
const node = path.getValue();
|
||
|
// If the node isn't an element node, then skip
|
||
|
if (node.name !== "element") {
|
||
|
return null;
|
||
|
}
|
||
|
// If the name of the node does not correspond to the name of a parser that
|
||
|
// prettier knows about, then skip
|
||
|
const parser = getParser(node, opts);
|
||
|
if (!parser) {
|
||
|
return null;
|
||
|
}
|
||
|
// If the node does not actually contain content, or it contains any content
|
||
|
// that is not just plain text, then skip
|
||
|
const content = node.children.content[0].children;
|
||
|
if (Object.keys(content).length !== 1 || !content.chardata) {
|
||
|
return null;
|
||
|
}
|
||
|
// Get the open and close tags of this element, then return the properly
|
||
|
// formatted content enclosed within them
|
||
|
const nodePath = path;
|
||
|
const { openTag, closeTag } = getElementTags(nodePath, opts, print);
|
||
|
return group([
|
||
|
openTag,
|
||
|
literalline,
|
||
|
dedentToRoot(replaceNewlines(doc_1.utils.stripTrailingHardline(textToDoc(getSource(content), { ...opts, parser })))),
|
||
|
hardline,
|
||
|
closeTag
|
||
|
]);
|
||
|
};
|
||
|
exports.default = embed;
|