securityos/node_modules/@prettier/plugin-xml/dist/embed.js

103 lines
4.0 KiB
JavaScript
Raw Normal View History

2024-09-06 15:32:35 +00:00
"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;