2017-10-12 01:46:44 +03:00
|
|
|
"use strict";
|
|
|
|
|
2018-02-09 15:17:48 +03:00
|
|
|
const privateUtil = require("../common/util");
|
2017-12-26 04:23:50 +03:00
|
|
|
const embed = require("./embed");
|
2018-04-08 19:10:24 +03:00
|
|
|
const pragma = require("./pragma");
|
2018-09-03 18:27:50 +03:00
|
|
|
const preprocess = require("./preprocess");
|
2018-05-27 14:36:12 +03:00
|
|
|
const {
|
|
|
|
builders: {
|
2019-01-30 20:24:21 +03:00
|
|
|
breakParent,
|
2018-05-27 14:36:12 +03:00
|
|
|
concat,
|
|
|
|
join,
|
|
|
|
line,
|
2018-06-07 19:20:25 +03:00
|
|
|
literalline,
|
|
|
|
markAsRoot,
|
2018-05-27 14:36:12 +03:00
|
|
|
hardline,
|
|
|
|
softline,
|
2019-01-30 20:24:21 +03:00
|
|
|
ifBreak,
|
2018-05-27 14:36:12 +03:00
|
|
|
fill,
|
|
|
|
align,
|
|
|
|
indent,
|
|
|
|
group
|
|
|
|
},
|
|
|
|
utils: { mapDoc },
|
|
|
|
printer: { printDocToString }
|
|
|
|
} = require("../doc");
|
2018-09-02 11:20:22 +03:00
|
|
|
const {
|
|
|
|
getFencedCodeBlockValue,
|
|
|
|
getOrderedListItemInfo,
|
|
|
|
splitText,
|
2019-01-22 07:02:30 +03:00
|
|
|
punctuationPattern,
|
|
|
|
INLINE_NODE_TYPES,
|
|
|
|
INLINE_NODE_WRAPPER_TYPES
|
2018-09-02 11:20:22 +03:00
|
|
|
} = require("./utils");
|
2018-12-08 13:28:29 +03:00
|
|
|
const { replaceEndOfLineWith } = require("../common/util");
|
2017-11-11 19:07:58 +03:00
|
|
|
|
2018-08-13 17:23:09 +03:00
|
|
|
const TRAILING_HARDLINE_NODES = ["importExport"];
|
2018-01-26 19:48:47 +03:00
|
|
|
const SINGLE_LINE_NODE_TYPES = ["heading", "tableCell", "link"];
|
2019-07-29 14:32:24 +03:00
|
|
|
const SIBLING_NODE_TYPES = [
|
|
|
|
"listItem",
|
|
|
|
"definition",
|
|
|
|
"footnoteDefinition",
|
|
|
|
"jsx"
|
|
|
|
];
|
2017-10-12 01:46:44 +03:00
|
|
|
|
|
|
|
function genericPrint(path, options, print) {
|
|
|
|
const node = path.getValue();
|
|
|
|
|
|
|
|
if (shouldRemainTheSameContent(path)) {
|
|
|
|
return concat(
|
2018-09-02 11:20:22 +03:00
|
|
|
splitText(
|
|
|
|
options.originalText.slice(
|
|
|
|
node.position.start.offset,
|
|
|
|
node.position.end.offset
|
|
|
|
),
|
|
|
|
options
|
2018-11-07 04:12:25 +03:00
|
|
|
).map(node =>
|
|
|
|
node.type === "word"
|
|
|
|
? node.value
|
|
|
|
: node.value === ""
|
|
|
|
? ""
|
|
|
|
: printLine(path, node.value, options)
|
2018-09-02 11:20:22 +03:00
|
|
|
)
|
2017-10-12 01:46:44 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (node.type) {
|
|
|
|
case "root":
|
2018-04-27 10:01:14 +03:00
|
|
|
if (node.children.length === 0) {
|
|
|
|
return "";
|
|
|
|
}
|
2018-08-13 17:23:09 +03:00
|
|
|
return concat([
|
|
|
|
normalizeDoc(printRoot(path, options, print)),
|
|
|
|
TRAILING_HARDLINE_NODES.indexOf(getLastDescendantNode(node).type) === -1
|
|
|
|
? hardline
|
|
|
|
: ""
|
|
|
|
]);
|
2017-10-12 01:46:44 +03:00
|
|
|
case "paragraph":
|
|
|
|
return printChildren(path, options, print, {
|
|
|
|
postprocessor: fill
|
|
|
|
});
|
|
|
|
case "sentence":
|
|
|
|
return printChildren(path, options, print);
|
|
|
|
case "word":
|
2017-11-11 19:29:59 +03:00
|
|
|
return node.value
|
2018-09-05 16:07:37 +03:00
|
|
|
.replace(/[*$]/g, "\\$&") // escape all `*` and `$` (math)
|
2017-11-11 19:29:59 +03:00
|
|
|
.replace(
|
|
|
|
new RegExp(
|
2017-11-12 19:09:04 +03:00
|
|
|
[
|
2018-09-02 11:20:22 +03:00
|
|
|
`(^|${punctuationPattern})(_+)`,
|
|
|
|
`(_+)(${punctuationPattern}|$)`
|
2017-11-12 19:09:04 +03:00
|
|
|
].join("|"),
|
2017-11-11 19:29:59 +03:00
|
|
|
"g"
|
|
|
|
),
|
|
|
|
(_, text1, underscore1, underscore2, text2) =>
|
|
|
|
(underscore1
|
|
|
|
? `${text1}${underscore1}`
|
|
|
|
: `${underscore2}${text2}`
|
|
|
|
).replace(/_/g, "\\_")
|
|
|
|
); // escape all `_` except concating with non-punctuation, e.g. `1_2_3` is not considered emphasis
|
2017-11-07 12:40:09 +03:00
|
|
|
case "whitespace": {
|
|
|
|
const parentNode = path.getParentNode();
|
|
|
|
const index = parentNode.children.indexOf(node);
|
|
|
|
const nextNode = parentNode.children[index + 1];
|
|
|
|
|
2017-12-02 01:48:40 +03:00
|
|
|
const proseWrap =
|
|
|
|
// leading char that may cause different syntax
|
|
|
|
nextNode && /^>|^([-+*]|#{1,6}|[0-9]+[.)])$/.test(nextNode.value)
|
|
|
|
? "never"
|
|
|
|
: options.proseWrap;
|
2017-11-07 12:40:09 +03:00
|
|
|
|
2017-12-02 01:48:40 +03:00
|
|
|
return printLine(path, node.value, { proseWrap });
|
2017-11-07 12:40:09 +03:00
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
case "emphasis": {
|
|
|
|
const parentNode = path.getParentNode();
|
|
|
|
const index = parentNode.children.indexOf(node);
|
|
|
|
const prevNode = parentNode.children[index - 1];
|
|
|
|
const nextNode = parentNode.children[index + 1];
|
|
|
|
const hasPrevOrNextWord = // `1*2*3` is considered emphais but `1_2_3` is not
|
|
|
|
(prevNode &&
|
|
|
|
prevNode.type === "sentence" &&
|
|
|
|
prevNode.children.length > 0 &&
|
2018-02-09 15:17:48 +03:00
|
|
|
privateUtil.getLast(prevNode.children).type === "word" &&
|
|
|
|
!privateUtil.getLast(prevNode.children).hasTrailingPunctuation) ||
|
2017-10-12 01:46:44 +03:00
|
|
|
(nextNode &&
|
|
|
|
nextNode.type === "sentence" &&
|
|
|
|
nextNode.children.length > 0 &&
|
2017-11-07 15:33:29 +03:00
|
|
|
nextNode.children[0].type === "word" &&
|
2017-11-16 08:59:01 +03:00
|
|
|
!nextNode.children[0].hasLeadingPunctuation);
|
2017-10-12 01:46:44 +03:00
|
|
|
const style =
|
|
|
|
hasPrevOrNextWord || getAncestorNode(path, "emphasis") ? "*" : "_";
|
|
|
|
return concat([style, printChildren(path, options, print), style]);
|
|
|
|
}
|
|
|
|
case "strong":
|
|
|
|
return concat(["**", printChildren(path, options, print), "**"]);
|
|
|
|
case "delete":
|
|
|
|
return concat(["~~", printChildren(path, options, print), "~~"]);
|
|
|
|
case "inlineCode": {
|
2019-05-14 18:51:31 +03:00
|
|
|
const backtickCount = privateUtil.getMinNotPresentContinuousCount(
|
|
|
|
node.value,
|
|
|
|
"`"
|
|
|
|
);
|
|
|
|
const style = "`".repeat(backtickCount || 1);
|
2017-11-11 19:29:59 +03:00
|
|
|
const gap = backtickCount ? " " : "";
|
|
|
|
return concat([style, gap, node.value, gap, style]);
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
case "link":
|
2017-10-14 14:49:12 +03:00
|
|
|
switch (options.originalText[node.position.start.offset]) {
|
2018-06-27 03:36:51 +03:00
|
|
|
case "<": {
|
|
|
|
const mailto = "mailto:";
|
|
|
|
const url =
|
|
|
|
// <hello@example.com> is parsed as { url: "mailto:hello@example.com" }
|
|
|
|
node.url.startsWith(mailto) &&
|
|
|
|
options.originalText.slice(
|
|
|
|
node.position.start.offset + 1,
|
|
|
|
node.position.start.offset + 1 + mailto.length
|
|
|
|
) !== mailto
|
|
|
|
? node.url.slice(mailto.length)
|
|
|
|
: node.url;
|
|
|
|
return concat(["<", url, ">"]);
|
|
|
|
}
|
2017-10-14 14:49:12 +03:00
|
|
|
case "[":
|
|
|
|
return concat([
|
2017-10-12 01:46:44 +03:00
|
|
|
"[",
|
|
|
|
printChildren(path, options, print),
|
|
|
|
"](",
|
|
|
|
printUrl(node.url, ")"),
|
2017-12-24 17:44:38 +03:00
|
|
|
printTitle(node.title, options),
|
2017-10-12 01:46:44 +03:00
|
|
|
")"
|
|
|
|
]);
|
2017-10-14 14:49:12 +03:00
|
|
|
default:
|
|
|
|
return options.originalText.slice(
|
|
|
|
node.position.start.offset,
|
|
|
|
node.position.end.offset
|
|
|
|
);
|
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
case "image":
|
|
|
|
return concat([
|
|
|
|
"![",
|
|
|
|
node.alt || "",
|
|
|
|
"](",
|
|
|
|
printUrl(node.url, ")"),
|
2017-12-24 17:44:38 +03:00
|
|
|
printTitle(node.title, options),
|
2017-10-12 01:46:44 +03:00
|
|
|
")"
|
|
|
|
]);
|
|
|
|
case "blockquote":
|
|
|
|
return concat(["> ", align("> ", printChildren(path, options, print))]);
|
|
|
|
case "heading":
|
|
|
|
return concat([
|
|
|
|
"#".repeat(node.depth) + " ",
|
|
|
|
printChildren(path, options, print)
|
|
|
|
]);
|
|
|
|
case "code": {
|
2018-07-27 04:48:09 +03:00
|
|
|
if (node.isIndented) {
|
2017-10-12 01:46:44 +03:00
|
|
|
// indented code block
|
2017-11-11 10:05:07 +03:00
|
|
|
const alignment = " ".repeat(4);
|
2017-10-12 01:46:44 +03:00
|
|
|
return align(
|
2017-11-11 10:05:07 +03:00
|
|
|
alignment,
|
2018-12-08 13:28:29 +03:00
|
|
|
concat([
|
|
|
|
alignment,
|
|
|
|
concat(replaceEndOfLineWith(node.value, hardline))
|
|
|
|
])
|
2017-10-12 01:46:44 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// fenced code block
|
|
|
|
const styleUnit = options.__inJsTemplate ? "~" : "`";
|
|
|
|
const style = styleUnit.repeat(
|
2018-02-09 15:17:48 +03:00
|
|
|
Math.max(
|
|
|
|
3,
|
|
|
|
privateUtil.getMaxContinuousCount(node.value, styleUnit) + 1
|
|
|
|
)
|
2017-10-12 01:46:44 +03:00
|
|
|
);
|
|
|
|
return concat([
|
|
|
|
style,
|
|
|
|
node.lang || "",
|
|
|
|
hardline,
|
2018-12-08 13:28:29 +03:00
|
|
|
concat(
|
|
|
|
replaceEndOfLineWith(
|
|
|
|
getFencedCodeBlockValue(node, options.originalText),
|
|
|
|
hardline
|
|
|
|
)
|
2018-09-01 08:35:29 +03:00
|
|
|
),
|
2017-10-12 01:46:44 +03:00
|
|
|
hardline,
|
|
|
|
style
|
|
|
|
]);
|
|
|
|
}
|
2018-07-03 04:54:40 +03:00
|
|
|
case "yaml":
|
|
|
|
case "toml":
|
|
|
|
return options.originalText.slice(
|
|
|
|
node.position.start.offset,
|
|
|
|
node.position.end.offset
|
|
|
|
);
|
2017-10-12 01:46:44 +03:00
|
|
|
case "html": {
|
|
|
|
const parentNode = path.getParentNode();
|
2018-06-07 19:20:25 +03:00
|
|
|
const value =
|
2018-03-07 19:06:22 +03:00
|
|
|
parentNode.type === "root" &&
|
2018-02-09 15:17:48 +03:00
|
|
|
privateUtil.getLast(parentNode.children) === node
|
2018-03-07 19:06:22 +03:00
|
|
|
? node.value.trimRight()
|
2018-06-07 19:20:25 +03:00
|
|
|
: node.value;
|
|
|
|
const isHtmlComment = /^<!--[\s\S]*-->$/.test(value);
|
2018-12-08 13:28:29 +03:00
|
|
|
return concat(
|
|
|
|
replaceEndOfLineWith(
|
|
|
|
value,
|
|
|
|
isHtmlComment ? hardline : markAsRoot(literalline)
|
|
|
|
)
|
2018-03-07 19:06:22 +03:00
|
|
|
);
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
case "list": {
|
2017-10-14 14:41:25 +03:00
|
|
|
const nthSiblingIndex = getNthListSiblingIndex(
|
|
|
|
node,
|
|
|
|
path.getParentNode()
|
2017-10-12 01:46:44 +03:00
|
|
|
);
|
2017-10-14 14:53:58 +03:00
|
|
|
|
|
|
|
const isGitDiffFriendlyOrderedList =
|
|
|
|
node.ordered &&
|
|
|
|
node.children.length > 1 &&
|
2018-07-27 04:48:09 +03:00
|
|
|
+getOrderedListItemInfo(node.children[1], options.originalText)
|
|
|
|
.numberText === 1;
|
2017-10-14 14:53:58 +03:00
|
|
|
|
2017-10-12 01:46:44 +03:00
|
|
|
return printChildren(path, options, print, {
|
|
|
|
processor: (childPath, index) => {
|
2018-02-26 03:52:49 +03:00
|
|
|
const prefix = getPrefix();
|
2017-11-11 10:05:07 +03:00
|
|
|
return concat([
|
|
|
|
prefix,
|
2018-01-10 10:45:22 +03:00
|
|
|
align(
|
|
|
|
" ".repeat(prefix.length),
|
|
|
|
printListItem(childPath, options, print, prefix)
|
|
|
|
)
|
2017-11-11 10:05:07 +03:00
|
|
|
]);
|
2018-02-26 03:52:49 +03:00
|
|
|
|
|
|
|
function getPrefix() {
|
|
|
|
const rawPrefix = node.ordered
|
|
|
|
? (index === 0
|
|
|
|
? node.start
|
2018-04-12 07:39:13 +03:00
|
|
|
: isGitDiffFriendlyOrderedList
|
2018-11-07 04:12:25 +03:00
|
|
|
? 1
|
|
|
|
: node.start + index) +
|
2018-02-26 03:52:49 +03:00
|
|
|
(nthSiblingIndex % 2 === 0 ? ". " : ") ")
|
2018-04-12 07:39:13 +03:00
|
|
|
: nthSiblingIndex % 2 === 0
|
2018-11-07 04:12:25 +03:00
|
|
|
? "- "
|
|
|
|
: "* ";
|
2018-02-26 03:52:49 +03:00
|
|
|
|
2018-07-27 04:48:09 +03:00
|
|
|
return node.isAligned ||
|
|
|
|
/* workaround for https://github.com/remarkjs/remark/issues/315 */ node.hasIndentedCodeblock
|
2018-02-26 03:52:49 +03:00
|
|
|
? alignListPrefix(rawPrefix, options)
|
|
|
|
: rawPrefix;
|
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-10-14 14:41:25 +03:00
|
|
|
case "thematicBreak": {
|
|
|
|
const counter = getAncestorCounter(path, "list");
|
|
|
|
if (counter === -1) {
|
2017-11-05 12:50:10 +03:00
|
|
|
return "---";
|
2017-10-14 14:41:25 +03:00
|
|
|
}
|
|
|
|
const nthSiblingIndex = getNthListSiblingIndex(
|
|
|
|
path.getParentNode(counter),
|
|
|
|
path.getParentNode(counter + 1)
|
|
|
|
);
|
2018-05-10 09:32:52 +03:00
|
|
|
return nthSiblingIndex % 2 === 0 ? "***" : "---";
|
2017-10-14 14:41:25 +03:00
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
case "linkReference":
|
|
|
|
return concat([
|
|
|
|
"[",
|
|
|
|
printChildren(path, options, print),
|
|
|
|
"]",
|
|
|
|
node.referenceType === "full"
|
|
|
|
? concat(["[", node.identifier, "]"])
|
2018-04-12 07:39:13 +03:00
|
|
|
: node.referenceType === "collapsed"
|
2018-11-07 04:12:25 +03:00
|
|
|
? "[]"
|
|
|
|
: ""
|
2017-10-12 01:46:44 +03:00
|
|
|
]);
|
|
|
|
case "imageReference":
|
|
|
|
switch (node.referenceType) {
|
|
|
|
case "full":
|
2018-01-03 19:54:53 +03:00
|
|
|
return concat(["![", node.alt || "", "][", node.identifier, "]"]);
|
2017-10-12 01:46:44 +03:00
|
|
|
default:
|
|
|
|
return concat([
|
|
|
|
"![",
|
|
|
|
node.alt,
|
|
|
|
"]",
|
|
|
|
node.referenceType === "collapsed" ? "[]" : ""
|
|
|
|
]);
|
|
|
|
}
|
2018-05-14 13:17:37 +03:00
|
|
|
case "definition": {
|
|
|
|
const lineOrSpace = options.proseWrap === "always" ? line : " ";
|
|
|
|
return group(
|
|
|
|
concat([
|
|
|
|
concat(["[", node.identifier, "]:"]),
|
|
|
|
indent(
|
|
|
|
concat([
|
|
|
|
lineOrSpace,
|
|
|
|
printUrl(node.url),
|
|
|
|
node.title === null
|
|
|
|
? ""
|
|
|
|
: concat([lineOrSpace, printTitle(node.title, options, false)])
|
|
|
|
])
|
|
|
|
)
|
|
|
|
])
|
|
|
|
);
|
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
case "footnote":
|
|
|
|
return concat(["[^", printChildren(path, options, print), "]"]);
|
|
|
|
case "footnoteReference":
|
|
|
|
return concat(["[^", node.identifier, "]"]);
|
2018-01-26 19:48:47 +03:00
|
|
|
case "footnoteDefinition": {
|
|
|
|
const nextNode = path.getParentNode().children[path.getName() + 1];
|
2018-09-01 08:14:22 +03:00
|
|
|
const shouldInlineFootnote =
|
|
|
|
node.children.length === 1 &&
|
|
|
|
node.children[0].type === "paragraph" &&
|
|
|
|
(options.proseWrap === "never" ||
|
|
|
|
(options.proseWrap === "preserve" &&
|
|
|
|
node.children[0].position.start.line ===
|
|
|
|
node.children[0].position.end.line));
|
2017-10-12 01:46:44 +03:00
|
|
|
return concat([
|
|
|
|
"[^",
|
|
|
|
node.identifier,
|
|
|
|
"]: ",
|
2018-09-01 08:14:22 +03:00
|
|
|
shouldInlineFootnote
|
|
|
|
? printChildren(path, options, print)
|
|
|
|
: group(
|
|
|
|
concat([
|
|
|
|
align(
|
|
|
|
" ".repeat(options.tabWidth),
|
|
|
|
printChildren(path, options, print, {
|
|
|
|
processor: (childPath, index) =>
|
|
|
|
index === 0
|
|
|
|
? group(
|
|
|
|
concat([softline, softline, childPath.call(print)])
|
|
|
|
)
|
|
|
|
: childPath.call(print)
|
|
|
|
})
|
|
|
|
),
|
|
|
|
nextNode && nextNode.type === "footnoteDefinition"
|
|
|
|
? softline
|
|
|
|
: ""
|
|
|
|
])
|
|
|
|
)
|
2017-10-12 01:46:44 +03:00
|
|
|
]);
|
2018-01-26 19:48:47 +03:00
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
case "table":
|
|
|
|
return printTable(path, options, print);
|
|
|
|
case "tableCell":
|
|
|
|
return printChildren(path, options, print);
|
|
|
|
case "break":
|
2018-06-07 19:20:25 +03:00
|
|
|
return /\s/.test(options.originalText[node.position.start.offset])
|
|
|
|
? concat([" ", markAsRoot(literalline)])
|
|
|
|
: concat(["\\", hardline]);
|
2018-05-15 20:22:41 +03:00
|
|
|
case "liquidNode":
|
2018-12-08 13:28:29 +03:00
|
|
|
return concat(replaceEndOfLineWith(node.value, hardline));
|
2018-08-13 17:23:09 +03:00
|
|
|
// MDX
|
|
|
|
case "importExport":
|
|
|
|
case "jsx":
|
|
|
|
return node.value; // fallback to the original text if multiparser failed
|
2018-09-05 16:07:37 +03:00
|
|
|
case "math":
|
|
|
|
return concat([
|
|
|
|
"$$",
|
|
|
|
hardline,
|
|
|
|
node.value
|
2018-12-08 13:28:29 +03:00
|
|
|
? concat([
|
|
|
|
concat(replaceEndOfLineWith(node.value, hardline)),
|
|
|
|
hardline
|
|
|
|
])
|
2018-09-05 16:07:37 +03:00
|
|
|
: "",
|
|
|
|
"$$"
|
|
|
|
]);
|
2018-10-10 04:46:58 +03:00
|
|
|
case "inlineMath": {
|
2018-11-15 19:17:20 +03:00
|
|
|
// remark-math trims content but we don't want to remove whitespaces
|
|
|
|
// since it's very possible that it's recognized as math accidentally
|
|
|
|
return options.originalText.slice(
|
|
|
|
options.locStart(node),
|
|
|
|
options.locEnd(node)
|
|
|
|
);
|
2018-10-10 04:46:58 +03:00
|
|
|
}
|
2018-08-13 17:23:09 +03:00
|
|
|
|
2017-10-12 01:46:44 +03:00
|
|
|
case "tableRow": // handled in "table"
|
2018-01-10 10:45:22 +03:00
|
|
|
case "listItem": // handled in "list"
|
2017-10-12 01:46:44 +03:00
|
|
|
default:
|
|
|
|
throw new Error(`Unknown markdown type ${JSON.stringify(node.type)}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-10 10:45:22 +03:00
|
|
|
function printListItem(path, options, print, listPrefix) {
|
|
|
|
const node = path.getValue();
|
|
|
|
const prefix = node.checked === null ? "" : node.checked ? "[x] " : "[ ] ";
|
|
|
|
return concat([
|
|
|
|
prefix,
|
|
|
|
printChildren(path, options, print, {
|
|
|
|
processor: (childPath, index) => {
|
|
|
|
if (index === 0 && childPath.getValue().type !== "list") {
|
|
|
|
return align(" ".repeat(prefix.length), childPath.call(print));
|
|
|
|
}
|
|
|
|
|
|
|
|
const alignment = " ".repeat(
|
2018-02-26 03:53:09 +03:00
|
|
|
clamp(options.tabWidth - listPrefix.length, 0, 3) // 4+ will cause indented code block
|
2018-01-10 10:45:22 +03:00
|
|
|
);
|
|
|
|
return concat([alignment, align(alignment, childPath.call(print))]);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2018-02-24 11:13:02 +03:00
|
|
|
function alignListPrefix(prefix, options) {
|
|
|
|
const additionalSpaces = getAdditionalSpaces();
|
|
|
|
return (
|
|
|
|
prefix +
|
|
|
|
" ".repeat(
|
2018-02-26 03:53:09 +03:00
|
|
|
additionalSpaces >= 4 ? 0 : additionalSpaces // 4+ will cause indented code block
|
2018-02-24 11:13:02 +03:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
function getAdditionalSpaces() {
|
|
|
|
const restSpaces = prefix.length % options.tabWidth;
|
|
|
|
return restSpaces === 0 ? 0 : options.tabWidth - restSpaces;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-14 14:41:25 +03:00
|
|
|
function getNthListSiblingIndex(node, parentNode) {
|
|
|
|
return getNthSiblingIndex(
|
|
|
|
node,
|
|
|
|
parentNode,
|
|
|
|
siblingNode => siblingNode.ordered === node.ordered
|
|
|
|
);
|
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
|
2017-10-14 14:41:25 +03:00
|
|
|
function getNthSiblingIndex(node, parentNode, condition) {
|
|
|
|
condition = condition || (() => true);
|
2017-10-12 01:46:44 +03:00
|
|
|
|
|
|
|
let index = -1;
|
|
|
|
|
|
|
|
for (const childNode of parentNode.children) {
|
|
|
|
if (childNode.type === node.type && condition(childNode)) {
|
|
|
|
index++;
|
|
|
|
} else {
|
|
|
|
index = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (childNode === node) {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-14 14:41:25 +03:00
|
|
|
function getAncestorCounter(path, typeOrTypes) {
|
2017-10-12 01:46:44 +03:00
|
|
|
const types = [].concat(typeOrTypes);
|
|
|
|
|
2017-10-14 14:41:25 +03:00
|
|
|
let counter = -1;
|
2017-10-12 01:46:44 +03:00
|
|
|
let ancestorNode;
|
|
|
|
|
2017-10-14 14:41:25 +03:00
|
|
|
while ((ancestorNode = path.getParentNode(++counter))) {
|
2017-10-12 01:46:44 +03:00
|
|
|
if (types.indexOf(ancestorNode.type) !== -1) {
|
2017-10-14 14:41:25 +03:00
|
|
|
return counter;
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-14 14:41:25 +03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getAncestorNode(path, typeOrTypes) {
|
|
|
|
const counter = getAncestorCounter(path, typeOrTypes);
|
|
|
|
return counter === -1 ? null : path.getParentNode(counter);
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
|
2017-12-02 01:48:40 +03:00
|
|
|
function printLine(path, value, options) {
|
|
|
|
if (options.proseWrap === "preserve" && value === "\n") {
|
|
|
|
return hardline;
|
|
|
|
}
|
|
|
|
|
2017-11-08 13:01:06 +03:00
|
|
|
const isBreakable =
|
2017-12-02 01:48:40 +03:00
|
|
|
options.proseWrap === "always" &&
|
|
|
|
!getAncestorNode(path, SINGLE_LINE_NODE_TYPES);
|
|
|
|
return value !== ""
|
2018-04-12 07:39:13 +03:00
|
|
|
? isBreakable
|
|
|
|
? line
|
|
|
|
: " "
|
|
|
|
: isBreakable
|
2018-11-07 04:12:25 +03:00
|
|
|
? softline
|
|
|
|
: "";
|
2017-11-07 13:10:41 +03:00
|
|
|
}
|
|
|
|
|
2017-10-12 01:46:44 +03:00
|
|
|
function printTable(path, options, print) {
|
2019-01-30 20:24:21 +03:00
|
|
|
const hardlineWithoutBreakParent = hardline.parts[0];
|
2017-10-12 01:46:44 +03:00
|
|
|
const node = path.getValue();
|
|
|
|
const contents = []; // { [rowIndex: number]: { [columnIndex: number]: string } }
|
|
|
|
|
|
|
|
path.map(rowPath => {
|
|
|
|
const rowContents = [];
|
|
|
|
|
|
|
|
rowPath.map(cellPath => {
|
|
|
|
rowContents.push(
|
|
|
|
printDocToString(cellPath.call(print), options).formatted
|
|
|
|
);
|
|
|
|
}, "children");
|
|
|
|
|
|
|
|
contents.push(rowContents);
|
|
|
|
}, "children");
|
|
|
|
|
2019-01-30 20:24:21 +03:00
|
|
|
// Get the width of each column
|
2017-10-12 01:46:44 +03:00
|
|
|
const columnMaxWidths = contents.reduce(
|
|
|
|
(currentWidths, rowContents) =>
|
|
|
|
currentWidths.map((width, columnIndex) =>
|
2018-02-09 15:17:48 +03:00
|
|
|
Math.max(width, privateUtil.getStringWidth(rowContents[columnIndex]))
|
2017-10-12 01:46:44 +03:00
|
|
|
),
|
|
|
|
contents[0].map(() => 3) // minimum width = 3 (---, :--, :-:, --:)
|
|
|
|
);
|
2019-01-30 20:24:21 +03:00
|
|
|
const alignedTable = join(hardlineWithoutBreakParent, [
|
2017-10-12 01:46:44 +03:00
|
|
|
printRow(contents[0]),
|
|
|
|
printSeparator(),
|
2019-01-30 20:24:21 +03:00
|
|
|
join(
|
|
|
|
hardlineWithoutBreakParent,
|
|
|
|
contents.slice(1).map(rowContents => printRow(rowContents))
|
|
|
|
)
|
|
|
|
]);
|
|
|
|
|
|
|
|
if (options.proseWrap !== "never") {
|
|
|
|
return concat([breakParent, alignedTable]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only if the --prose-wrap never is set and it exceeds the print width.
|
|
|
|
const compactTable = join(hardlineWithoutBreakParent, [
|
|
|
|
printRow(contents[0], /* isCompact */ true),
|
|
|
|
printSeparator(/* isCompact */ true),
|
|
|
|
join(
|
|
|
|
hardlineWithoutBreakParent,
|
|
|
|
contents
|
|
|
|
.slice(1)
|
|
|
|
.map(rowContents => printRow(rowContents, /* isCompact */ true))
|
|
|
|
)
|
2017-10-12 01:46:44 +03:00
|
|
|
]);
|
|
|
|
|
2019-01-30 20:24:21 +03:00
|
|
|
return concat([breakParent, group(ifBreak(compactTable, alignedTable))]);
|
|
|
|
|
|
|
|
function printSeparator(isCompact) {
|
2017-10-12 01:46:44 +03:00
|
|
|
return concat([
|
|
|
|
"| ",
|
|
|
|
join(
|
|
|
|
" | ",
|
|
|
|
columnMaxWidths.map((width, index) => {
|
2019-01-30 20:24:21 +03:00
|
|
|
const spaces = isCompact ? 3 : width;
|
2017-10-12 01:46:44 +03:00
|
|
|
switch (node.align[index]) {
|
|
|
|
case "left":
|
2019-01-30 20:24:21 +03:00
|
|
|
return ":" + "-".repeat(spaces - 1);
|
2017-10-12 01:46:44 +03:00
|
|
|
case "right":
|
2019-01-30 20:24:21 +03:00
|
|
|
return "-".repeat(spaces - 1) + ":";
|
2017-10-12 01:46:44 +03:00
|
|
|
case "center":
|
2019-01-30 20:24:21 +03:00
|
|
|
return ":" + "-".repeat(spaces - 2) + ":";
|
2017-10-12 01:46:44 +03:00
|
|
|
default:
|
2019-01-30 20:24:21 +03:00
|
|
|
return "-".repeat(spaces);
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
),
|
|
|
|
" |"
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2019-01-30 20:24:21 +03:00
|
|
|
function printRow(rowContents, isCompact) {
|
2017-10-12 01:46:44 +03:00
|
|
|
return concat([
|
|
|
|
"| ",
|
|
|
|
join(
|
|
|
|
" | ",
|
2019-01-30 20:24:21 +03:00
|
|
|
isCompact
|
|
|
|
? rowContents
|
|
|
|
: rowContents.map((rowContent, columnIndex) => {
|
|
|
|
switch (node.align[columnIndex]) {
|
|
|
|
case "right":
|
|
|
|
return alignRight(rowContent, columnMaxWidths[columnIndex]);
|
|
|
|
case "center":
|
|
|
|
return alignCenter(rowContent, columnMaxWidths[columnIndex]);
|
|
|
|
default:
|
|
|
|
return alignLeft(rowContent, columnMaxWidths[columnIndex]);
|
|
|
|
}
|
|
|
|
})
|
2017-10-12 01:46:44 +03:00
|
|
|
),
|
|
|
|
" |"
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function alignLeft(text, width) {
|
2019-01-30 20:24:21 +03:00
|
|
|
const spaces = width - privateUtil.getStringWidth(text);
|
|
|
|
return concat([text, " ".repeat(spaces)]);
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function alignRight(text, width) {
|
2019-01-30 20:24:21 +03:00
|
|
|
const spaces = width - privateUtil.getStringWidth(text);
|
|
|
|
return concat([" ".repeat(spaces), text]);
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function alignCenter(text, width) {
|
2018-02-09 15:17:48 +03:00
|
|
|
const spaces = width - privateUtil.getStringWidth(text);
|
2017-10-12 01:46:44 +03:00
|
|
|
const left = Math.floor(spaces / 2);
|
|
|
|
const right = spaces - left;
|
|
|
|
return concat([" ".repeat(left), text, " ".repeat(right)]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-26 19:03:28 +03:00
|
|
|
function printRoot(path, options, print) {
|
|
|
|
/** @typedef {{ index: number, offset: number }} IgnorePosition */
|
|
|
|
/** @type {Array<{start: IgnorePosition, end: IgnorePosition}>} */
|
|
|
|
const ignoreRanges = [];
|
|
|
|
|
|
|
|
/** @type {IgnorePosition | null} */
|
|
|
|
let ignoreStart = null;
|
|
|
|
|
|
|
|
const children = path.getValue().children;
|
|
|
|
children.forEach((childNode, index) => {
|
|
|
|
switch (isPrettierIgnore(childNode)) {
|
|
|
|
case "start":
|
|
|
|
if (ignoreStart === null) {
|
|
|
|
ignoreStart = { index, offset: childNode.position.end.offset };
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "end":
|
|
|
|
if (ignoreStart !== null) {
|
|
|
|
ignoreRanges.push({
|
|
|
|
start: ignoreStart,
|
|
|
|
end: { index, offset: childNode.position.start.offset }
|
|
|
|
});
|
|
|
|
ignoreStart = null;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// do nothing
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return printChildren(path, options, print, {
|
|
|
|
processor: (childPath, index) => {
|
|
|
|
if (ignoreRanges.length !== 0) {
|
|
|
|
const ignoreRange = ignoreRanges[0];
|
|
|
|
|
|
|
|
if (index === ignoreRange.start.index) {
|
|
|
|
return concat([
|
|
|
|
children[ignoreRange.start.index].value,
|
|
|
|
options.originalText.slice(
|
|
|
|
ignoreRange.start.offset,
|
|
|
|
ignoreRange.end.offset
|
|
|
|
),
|
|
|
|
children[ignoreRange.end.index].value
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ignoreRange.start.index < index && index < ignoreRange.end.index) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index === ignoreRange.end.index) {
|
|
|
|
ignoreRanges.shift();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return childPath.call(print);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-10-12 01:46:44 +03:00
|
|
|
function printChildren(path, options, print, events) {
|
|
|
|
events = events || {};
|
|
|
|
|
|
|
|
const postprocessor = events.postprocessor || concat;
|
|
|
|
const processor = events.processor || (childPath => childPath.call(print));
|
|
|
|
|
|
|
|
const node = path.getValue();
|
|
|
|
const parts = [];
|
|
|
|
|
|
|
|
let lastChildNode;
|
|
|
|
|
|
|
|
path.map((childPath, index) => {
|
|
|
|
const childNode = childPath.getValue();
|
|
|
|
|
2018-04-06 19:19:26 +03:00
|
|
|
const result = processor(childPath, index);
|
2017-10-12 01:46:44 +03:00
|
|
|
if (result !== false) {
|
|
|
|
const data = {
|
|
|
|
parts,
|
|
|
|
prevNode: lastChildNode,
|
|
|
|
parentNode: node,
|
|
|
|
options
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!shouldNotPrePrintHardline(childNode, data)) {
|
|
|
|
parts.push(hardline);
|
|
|
|
|
|
|
|
if (
|
2018-08-13 17:23:09 +03:00
|
|
|
lastChildNode &&
|
|
|
|
TRAILING_HARDLINE_NODES.indexOf(lastChildNode.type) !== -1
|
2017-10-12 01:46:44 +03:00
|
|
|
) {
|
2018-08-13 17:23:09 +03:00
|
|
|
if (shouldPrePrintTripleHardline(childNode, data)) {
|
|
|
|
parts.push(hardline);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (
|
|
|
|
shouldPrePrintDoubleHardline(childNode, data) ||
|
|
|
|
shouldPrePrintTripleHardline(childNode, data)
|
|
|
|
) {
|
|
|
|
parts.push(hardline);
|
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
|
2018-08-13 17:23:09 +03:00
|
|
|
if (shouldPrePrintTripleHardline(childNode, data)) {
|
|
|
|
parts.push(hardline);
|
|
|
|
}
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
parts.push(result);
|
|
|
|
|
|
|
|
lastChildNode = childNode;
|
|
|
|
}
|
|
|
|
}, "children");
|
|
|
|
|
|
|
|
return postprocessor(parts);
|
|
|
|
}
|
|
|
|
|
2018-08-13 17:23:09 +03:00
|
|
|
function getLastDescendantNode(node) {
|
|
|
|
let current = node;
|
|
|
|
while (current.children && current.children.length !== 0) {
|
|
|
|
current = current.children[current.children.length - 1];
|
|
|
|
}
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
|
2018-03-26 19:03:28 +03:00
|
|
|
/** @return {false | 'next' | 'start' | 'end'} */
|
2017-10-12 01:46:44 +03:00
|
|
|
function isPrettierIgnore(node) {
|
2018-03-26 19:03:28 +03:00
|
|
|
if (node.type !== "html") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const match = node.value.match(
|
|
|
|
/^<!--\s*prettier-ignore(?:-(start|end))?\s*-->$/
|
2017-10-12 01:46:44 +03:00
|
|
|
);
|
2018-03-26 19:03:28 +03:00
|
|
|
return match === null ? false : match[1] ? match[1] : "next";
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function shouldNotPrePrintHardline(node, data) {
|
|
|
|
const isFirstNode = data.parts.length === 0;
|
|
|
|
const isInlineNode = INLINE_NODE_TYPES.indexOf(node.type) !== -1;
|
|
|
|
|
|
|
|
const isInlineHTML =
|
|
|
|
node.type === "html" &&
|
|
|
|
INLINE_NODE_WRAPPER_TYPES.indexOf(data.parentNode.type) !== -1;
|
|
|
|
|
|
|
|
return isFirstNode || isInlineNode || isInlineHTML;
|
|
|
|
}
|
|
|
|
|
|
|
|
function shouldPrePrintDoubleHardline(node, data) {
|
|
|
|
const isSequence = (data.prevNode && data.prevNode.type) === node.type;
|
|
|
|
const isSiblingNode =
|
|
|
|
isSequence && SIBLING_NODE_TYPES.indexOf(node.type) !== -1;
|
|
|
|
|
|
|
|
const isInTightListItem =
|
|
|
|
data.parentNode.type === "listItem" && !data.parentNode.loose;
|
|
|
|
|
|
|
|
const isPrevNodeLooseListItem =
|
|
|
|
data.prevNode && data.prevNode.type === "listItem" && data.prevNode.loose;
|
|
|
|
|
2018-03-26 19:03:28 +03:00
|
|
|
const isPrevNodePrettierIgnore = isPrettierIgnore(data.prevNode) === "next";
|
2017-10-12 01:46:44 +03:00
|
|
|
|
2018-05-31 19:33:37 +03:00
|
|
|
const isBlockHtmlWithoutBlankLineBetweenPrevHtml =
|
|
|
|
node.type === "html" &&
|
|
|
|
data.prevNode &&
|
|
|
|
data.prevNode.type === "html" &&
|
|
|
|
data.prevNode.position.end.line + 1 === node.position.start.line;
|
|
|
|
|
2017-10-12 01:46:44 +03:00
|
|
|
return (
|
|
|
|
isPrevNodeLooseListItem ||
|
2018-05-31 19:33:37 +03:00
|
|
|
!(
|
|
|
|
isSiblingNode ||
|
|
|
|
isInTightListItem ||
|
|
|
|
isPrevNodePrettierIgnore ||
|
|
|
|
isBlockHtmlWithoutBlankLineBetweenPrevHtml
|
|
|
|
)
|
2017-10-12 01:46:44 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function shouldPrePrintTripleHardline(node, data) {
|
|
|
|
const isPrevNodeList = data.prevNode && data.prevNode.type === "list";
|
2018-07-27 04:48:09 +03:00
|
|
|
const isIndentedCode = node.type === "code" && node.isIndented;
|
2017-10-12 01:46:44 +03:00
|
|
|
|
|
|
|
return isPrevNodeList && isIndentedCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
function shouldRemainTheSameContent(path) {
|
|
|
|
const ancestorNode = getAncestorNode(path, [
|
|
|
|
"linkReference",
|
|
|
|
"imageReference"
|
|
|
|
]);
|
|
|
|
|
|
|
|
return (
|
|
|
|
ancestorNode &&
|
|
|
|
(ancestorNode.type !== "linkReference" ||
|
|
|
|
ancestorNode.referenceType !== "full")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function normalizeDoc(doc) {
|
2018-05-27 14:36:12 +03:00
|
|
|
return mapDoc(doc, currentDoc => {
|
2017-10-12 01:46:44 +03:00
|
|
|
if (!currentDoc.parts) {
|
|
|
|
return currentDoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentDoc.type === "concat" && currentDoc.parts.length === 1) {
|
|
|
|
return currentDoc.parts[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
const parts = [];
|
|
|
|
|
|
|
|
currentDoc.parts.forEach(part => {
|
|
|
|
if (part.type === "concat") {
|
|
|
|
parts.push.apply(parts, part.parts);
|
|
|
|
} else if (part !== "") {
|
|
|
|
parts.push(part);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return Object.assign({}, currentDoc, {
|
|
|
|
parts: normalizeParts(parts)
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function printUrl(url, dangerousCharOrChars) {
|
|
|
|
const dangerousChars = [" "].concat(dangerousCharOrChars || []);
|
|
|
|
return new RegExp(dangerousChars.map(x => `\\${x}`).join("|")).test(url)
|
|
|
|
? `<${url}>`
|
|
|
|
: url;
|
|
|
|
}
|
|
|
|
|
2018-05-14 13:17:37 +03:00
|
|
|
function printTitle(title, options, printSpace) {
|
|
|
|
if (printSpace == null) {
|
|
|
|
printSpace = true;
|
|
|
|
}
|
|
|
|
|
2017-12-24 17:44:38 +03:00
|
|
|
if (!title) {
|
|
|
|
return "";
|
|
|
|
}
|
2018-05-14 13:17:37 +03:00
|
|
|
if (printSpace) {
|
|
|
|
return " " + printTitle(title, options, false);
|
|
|
|
}
|
2017-12-24 17:44:38 +03:00
|
|
|
if (title.includes('"') && title.includes("'") && !title.includes(")")) {
|
2018-05-14 13:17:37 +03:00
|
|
|
return `(${title})`; // avoid escaped quotes
|
2017-12-24 17:44:38 +03:00
|
|
|
}
|
|
|
|
// faster than using RegExps: https://jsperf.com/performance-of-match-vs-split
|
|
|
|
const singleCount = title.split("'").length - 1;
|
|
|
|
const doubleCount = title.split('"').length - 1;
|
|
|
|
const quote =
|
|
|
|
singleCount > doubleCount
|
|
|
|
? '"'
|
2018-04-12 07:39:13 +03:00
|
|
|
: doubleCount > singleCount
|
2018-11-07 04:12:25 +03:00
|
|
|
? "'"
|
|
|
|
: options.singleQuote
|
|
|
|
? "'"
|
|
|
|
: '"';
|
2017-12-24 17:44:38 +03:00
|
|
|
title = title.replace(new RegExp(`(${quote})`, "g"), "\\$1");
|
2018-05-14 13:17:37 +03:00
|
|
|
return `${quote}${title}${quote}`;
|
2017-10-12 01:46:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function normalizeParts(parts) {
|
|
|
|
return parts.reduce((current, part) => {
|
2018-02-09 15:17:48 +03:00
|
|
|
const lastPart = privateUtil.getLast(current);
|
2017-10-12 01:46:44 +03:00
|
|
|
|
|
|
|
if (typeof lastPart === "string" && typeof part === "string") {
|
|
|
|
current.splice(-1, 1, lastPart + part);
|
|
|
|
} else {
|
|
|
|
current.push(part);
|
|
|
|
}
|
|
|
|
|
|
|
|
return current;
|
|
|
|
}, []);
|
|
|
|
}
|
|
|
|
|
2018-01-10 10:45:22 +03:00
|
|
|
function clamp(value, min, max) {
|
|
|
|
return value < min ? min : value > max ? max : value;
|
|
|
|
}
|
|
|
|
|
2018-04-08 19:10:24 +03:00
|
|
|
function clean(ast, newObj, parent) {
|
2018-05-08 05:48:29 +03:00
|
|
|
delete newObj.position;
|
2018-07-03 04:54:40 +03:00
|
|
|
delete newObj.raw; // front-matter
|
2018-05-08 05:48:29 +03:00
|
|
|
|
2018-04-08 19:10:24 +03:00
|
|
|
// for codeblock
|
2018-08-13 17:23:09 +03:00
|
|
|
if (
|
|
|
|
ast.type === "code" ||
|
|
|
|
ast.type === "yaml" ||
|
2018-09-03 18:27:50 +03:00
|
|
|
ast.type === "import" ||
|
|
|
|
ast.type === "export" ||
|
2018-08-13 17:23:09 +03:00
|
|
|
ast.type === "jsx"
|
|
|
|
) {
|
2017-12-30 13:30:09 +03:00
|
|
|
delete newObj.value;
|
|
|
|
}
|
2018-07-27 04:48:09 +03:00
|
|
|
|
|
|
|
if (ast.type === "list") {
|
|
|
|
delete newObj.isAligned;
|
|
|
|
}
|
|
|
|
|
2018-09-03 18:27:50 +03:00
|
|
|
// texts can be splitted or merged
|
|
|
|
if (ast.type === "text") {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ast.type === "inlineCode") {
|
|
|
|
newObj.value = ast.value.replace(/[ \t\n]+/g, " ");
|
2017-12-30 13:30:09 +03:00
|
|
|
}
|
2018-09-03 18:27:50 +03:00
|
|
|
|
2018-04-08 19:10:24 +03:00
|
|
|
// for insert pragma
|
|
|
|
if (
|
|
|
|
parent &&
|
|
|
|
parent.type === "root" &&
|
2018-04-27 10:01:14 +03:00
|
|
|
parent.children.length > 0 &&
|
2018-04-08 19:10:24 +03:00
|
|
|
(parent.children[0] === ast ||
|
2018-07-03 04:54:40 +03:00
|
|
|
((parent.children[0].type === "yaml" ||
|
|
|
|
parent.children[0].type === "toml") &&
|
2018-04-08 19:10:24 +03:00
|
|
|
parent.children[1] === ast)) &&
|
|
|
|
ast.type === "html" &&
|
|
|
|
pragma.startWithPragma(ast.value)
|
|
|
|
) {
|
|
|
|
return null;
|
|
|
|
}
|
2017-12-30 13:30:09 +03:00
|
|
|
}
|
|
|
|
|
2018-04-06 19:19:26 +03:00
|
|
|
function hasPrettierIgnore(path) {
|
|
|
|
const index = +path.getName();
|
|
|
|
|
|
|
|
if (index === 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const prevNode = path.getParentNode().children[index - 1];
|
|
|
|
return isPrettierIgnore(prevNode) === "next";
|
|
|
|
}
|
|
|
|
|
2017-12-26 04:23:50 +03:00
|
|
|
module.exports = {
|
2018-09-03 18:27:50 +03:00
|
|
|
preprocess,
|
2017-12-26 04:23:50 +03:00
|
|
|
print: genericPrint,
|
|
|
|
embed,
|
2017-12-30 13:30:09 +03:00
|
|
|
massageAstNode: clean,
|
2018-04-08 19:10:24 +03:00
|
|
|
hasPrettierIgnore,
|
|
|
|
insertPragma: pragma.insertPragma
|
2017-12-26 04:23:50 +03:00
|
|
|
};
|