Minor refactor to stripTrailingHardline (#13695)

This commit is contained in:
fisker Cheung authored and GitHub committed 2022-10-21 23:33:33 +08:00
1 parent 14c58aafd8
commit 0e06cc4d62
2 files changed
+63 -30

No files matched your search

+43 -30
View File
@@ -203,58 +203,71 @@ function removeLines(doc) {
return mapDoc(doc, removeLinesFn);
}
const isHardline = (doc, nextDoc) =>
doc &&
doc.type === DOC_TYPE_LINE &&
doc.hard &&
nextDoc &&
nextDoc.type === DOC_TYPE_BREAK_PARENT;
function stripDocTrailingHardlineFromDoc(doc) {
if (!doc) {
return doc;
function stripTrailingHardlineFromParts(parts) {
parts = [...parts];
while (
parts.length >= 2 &&
parts.at(-2).type === DOC_TYPE_LINE &&
parts.at(-1).type === DOC_TYPE_BREAK_PARENT
) {
parts.length -= 2;
}
if (Array.isArray(doc) || doc.type === DOC_TYPE_FILL) {
const parts = getDocParts(doc);
while (parts.length > 1 && isHardline(...parts.slice(-2))) {
parts.length -= 2;
}
if (parts.length > 0) {
const lastPart = stripDocTrailingHardlineFromDoc(parts.at(-1));
parts[parts.length - 1] = lastPart;
}
return Array.isArray(doc) ? parts : { ...doc, parts };
if (parts.length > 0) {
const lastPart = stripTrailingHardlineFromDoc(parts.at(-1));
parts[parts.length - 1] = lastPart;
}
switch (doc.type) {
return parts;
}
function stripTrailingHardlineFromDoc(doc) {
switch (getDocType(doc)) {
case DOC_TYPE_ALIGN:
case DOC_TYPE_INDENT:
case DOC_TYPE_INDENT_IF_BREAK:
case DOC_TYPE_GROUP:
case DOC_TYPE_LINE_SUFFIX:
case DOC_TYPE_LABEL: {
const contents = stripDocTrailingHardlineFromDoc(doc.contents);
const contents = stripTrailingHardlineFromDoc(doc.contents);
return { ...doc, contents };
}
case DOC_TYPE_IF_BREAK: {
const breakContents = stripDocTrailingHardlineFromDoc(doc.breakContents);
const flatContents = stripDocTrailingHardlineFromDoc(doc.flatContents);
let { breakContents, flatContents } = doc;
breakContents &&= stripTrailingHardlineFromDoc(breakContents);
flatContents &&= stripTrailingHardlineFromDoc(flatContents);
return { ...doc, breakContents, flatContents };
}
case DOC_TYPE_FILL:
return { ...doc, parts: stripTrailingHardlineFromParts(doc.parts) };
case DOC_TYPE_ARRAY:
return stripTrailingHardlineFromParts(doc);
case DOC_TYPE_STRING:
return doc.replace(/[\n\r]*$/, "");
case DOC_TYPE_CURSOR:
case DOC_TYPE_TRIM:
case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
case DOC_TYPE_LINE:
case DOC_TYPE_BREAK_PARENT:
// No op
break;
default:
throw new InvalidDocError(doc);
}
return doc;
}
function stripTrailingHardline(doc) {
if (typeof doc === "string") {
return doc.replace(/(?:\r?\n)*$/, "");
}
// HACK remove ending hardline, original PR: #1984
return stripDocTrailingHardlineFromDoc(cleanDoc(doc));
return stripTrailingHardlineFromDoc(cleanDoc(doc));
}
function cleanDocFn(doc) {
+20
View File
@@ -0,0 +1,20 @@
import { hardline, fill } from "../../src/document/builders.js";
import { stripTrailingHardline } from "../../src/document/utils.js";
test("Should not mutate doc", () => {
{
const original = fill(["text", [hardline]]);
expect(stripTrailingHardline(original)).toStrictEqual(fill(["text", []]));
expect(original.parts.length).toBe(2);
}
{
const original = ["text", [hardline]];
expect(stripTrailingHardline(original)).toStrictEqual(["text"]);
expect(original.length).toBe(2);
}
});
test("Should work for strings", () => {
expect(stripTrailingHardline("\ntext\n\n\r\r\r\n\r\n")).toBe("\ntext");
});