diff --git a/src/__snapshots__/attach.test.ts.snap b/src/__snapshots__/attach.test.ts.snap
index 86dad92e..15ee7e11 100644
--- a/src/__snapshots__/attach.test.ts.snap
+++ b/src/__snapshots__/attach.test.ts.snap
@@ -203,11 +203,11 @@ comment (24:5 ~ 24:11)
| ^^^^^^
25 | ··#·Flow·style¶
26 | ··Numbers:·!!omap·[·one:·1,·two:·2,·three·:·3·]¶
-mappingItem (26:3 ~ 26:48)
-
-
-
-
+sequence (21:5 ~ 23:57)
+
+
+
+
`;
exports[`"\\n---\\n# Collection Types ################################# 8`] = `
@@ -220,7 +220,6 @@ comment (25:3 ~ 25:15)
27 | ¶
mappingItem (26:3 ~ 26:48)
-
`;
@@ -1294,6 +1293,91 @@ mappingItem (204:1 ~ 206:14)
`;
+exports[`"\\n---\\n- Mark McGwire\\n- Sammy Sosa\\n- Ken Griffey\\n\\n# Tea 1`] = `
+comment (7:1 ~ 7:15)
+ 5 | -·Ken·Griffey¶
+ 6 | ¶
+ 7 | #·Team·ranking¶
+ | ^^^^^^^^^^^^^^
+ 8 | ---¶
+ 9 | -·Chicago·Cubs¶
+documentBody (3:1 ~ 7:15)
+
+
+
+`;
+
+exports[`"\\n---\\n- Mark McGwire\\n- Sammy Sosa\\n- Ken Griffey\\n\\n# Tea 2`] = `
+comment (7:1 ~ 7:15)
+ 5 | -·Ken·Griffey¶
+ 6 | ¶
+ 7 | #·Team·ranking¶
+ | ^^^^^^^^^^^^^^
+ 8 | ...¶
+ 9 | -·Chicago·Cubs¶
+documentBody (3:1 ~ 8:4)
+
+
+
+`;
+
+exports[`"\\na:\\n b:\\n #b\\n #a\\n\\nA:\\n B:\\n #A\\n #A\\n" 1`] = `
+comment (4:4 ~ 4:6)
+ 2 | a:¶
+ 3 | ··b:¶
+ 4 | ···#b¶
+ | ^^
+ 5 | ·#a¶
+ 6 | ¶
+mappingValue (3:4 ~ 3:5)
+
+
+
+`;
+
+exports[`"\\na:\\n b:\\n #b\\n #a\\n\\nA:\\n B:\\n #A\\n #A\\n" 2`] = `
+comment (5:2 ~ 5:4)
+ 3 | ··b:¶
+ 4 | ···#b¶
+ 5 | ·#a¶
+ | ^^
+ 6 | ¶
+ 7 | A:¶
+mappingValue (2:2 ~ 4:6)
+
+
+
+`;
+
+exports[`"\\na:\\n b:\\n #b\\n #a\\n\\nA:\\n B:\\n #A\\n #A\\n" 3`] = `
+comment (9:2 ~ 9:4)
+ 7 | A:¶
+ 8 | ··B:¶
+ 9 | ·#A¶
+ | ^^
+10 | ···#A¶
+11 | ¶
+mappingValue (7:2 ~ 8:5)
+
+
+
+
+`;
+
+exports[`"\\na:\\n b:\\n #b\\n #a\\n\\nA:\\n B:\\n #A\\n #A\\n" 4`] = `
+comment (10:4 ~ 10:6)
+ 8 | ··B:¶
+ 9 | ·#A¶
+10 | ···#A¶
+ | ^^
+11 | ¶
+mappingValue (7:2 ~ 8:5)
+
+
+
+
+`;
+
exports[`"\\naaa\\n# 123\\n---\\n# 789\\nbbb\\n" 1`] = `
comment (3:1 ~ 3:6)
1 | ¶
@@ -1419,6 +1503,19 @@ sequenceItem (3:3 ~ 3:8)
`;
+exports[`"\\nparent:\\n one: 1\\n # two: 2\\n" 1`] = `
+comment (4:3 ~ 4:11)
+2 | parent:¶
+3 | ··one:·1¶
+4 | ··#·two:·2¶
+ | ^^^^^^^^
+5 | ¶
+mappingValue (2:7 ~ 3:9)
+
+
+
+`;
+
exports[`"a:\\n 123\\n # impicitMappginValue\\n" 1`] = `
comment (3:3 ~ 3:24)
1 | a:¶
diff --git a/src/attach.test.ts b/src/attach.test.ts
index fb418537..2c0f8d84 100644
--- a/src/attach.test.ts
+++ b/src/attach.test.ts
@@ -266,6 +266,44 @@ d:
# 3
# 4
# 5
+`,
+ `
+parent:
+ one: 1
+ # two: 2
+`,
+ `
+a:
+ b:
+ #b
+ #a
+
+A:
+ B:
+ #A
+ #A
+`,
+ `
+---
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+
+# Team ranking
+---
+- Chicago Cubs
+- St Louis Cardinals
+`,
+ `
+---
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+
+# Team ranking
+...
+- Chicago Cubs
+- St Louis Cardinals
`,
];
diff --git a/src/attach.ts b/src/attach.ts
index 644f9c15..50bfc3ec 100644
--- a/src/attach.ts
+++ b/src/attach.ts
@@ -5,15 +5,11 @@ import {
Document,
EndCommentAttachable,
MappingItem,
- MappingKey,
- MappingValue,
Root,
- Sequence,
- SequenceItem,
YamlUnistNode,
} from "./types";
import {
- defineCommentParent,
+ defineParent,
getLast,
getStartPoint,
isBlockValue,
@@ -22,28 +18,14 @@ import {
} from "./utils";
type NodeTable = Array<{
- leadingNode: null | Extract;
- trailingNode: null | Extract;
- collectionNode: null | {
- node: SequenceItem | MappingKey | MappingValue;
- column: number;
- cases: NodeTableCollectionNodeCase[];
- };
+ leadingAttachableNode: null | Extract;
+ trailingAttachableNode: null | Extract;
+ trailingNode: null | YamlUnistNode;
+ comment: null | Comment;
}>;
-interface NodeTableCollectionNodeCase {
- mode: "gt" | "gte";
- attachee: Extract;
-}
-
export function attachComments(root: Root, context: Context): void {
- const nodeTable: NodeTable = context.text.split("\n").map(() => ({
- leadingNode: null,
- trailingNode: null,
- collectionNode: null,
- }));
-
- initNodeTable(root, nodeTable, context);
+ const nodeTable = createNodeTable(root, context);
const restDocuments = root.children.slice();
context.comments
@@ -62,26 +44,44 @@ export function attachComments(root: Root, context: Context): void {
updateEndPoints(root);
}
+function createNodeTable(root: Root, context: Context) {
+ const nodeTable: NodeTable = context.text.split("\n").map(() => ({
+ leadingAttachableNode: null,
+ trailingAttachableNode: null,
+ trailingNode: null,
+ comment: null,
+ }));
+
+ for (const comment of context.comments) {
+ nodeTable[comment.position.start.line - 1].comment = comment;
+ }
+
+ initNodeTable(root, nodeTable, context);
+
+ return nodeTable;
+}
+
function initNodeTable(
node: YamlUnistNode,
nodeTable: NodeTable,
context: Context,
- parentStack: YamlUnistNode[] = [],
): void {
if ("leadingComments" in node) {
const start = getStartPoint(node);
- const { end } = node.position;
-
- const currentStartNode = nodeTable[start.line - 1].leadingNode;
- const currentEndNode = nodeTable[end.line - 1].trailingNode;
+ const currentStartNode = nodeTable[start.line - 1].leadingAttachableNode;
if (
node.type !== "document" &&
(!currentStartNode ||
start.column < currentStartNode.position.start.column)
) {
- nodeTable[start.line - 1].leadingNode = node;
+ nodeTable[start.line - 1].leadingAttachableNode = node;
}
+ }
+
+ if ("trailingComments" in node) {
+ const { end } = node.position;
+ const currentEndNode = nodeTable[end.line - 1].trailingAttachableNode;
if (
!(
@@ -93,50 +93,33 @@ function initNodeTable(
) &&
(!currentEndNode || end.column >= currentEndNode.position.end.column)
) {
- nodeTable[end.line - 1].trailingNode = node;
+ nodeTable[end.line - 1].trailingAttachableNode = node;
}
}
- const parent = getLast(parentStack);
-
if (
- node.type === "sequenceItem" ||
- ((node.type === "mappingValue" ||
- (node.type === "mappingKey" &&
- isExplicitMappingItem(parent as MappingItem))) &&
- !isBlockValue(node.children[0]))
+ node.type !== "null" &&
+ node.type !== "root" &&
+ node.type !== "document" &&
+ node.type !== "documentHead" &&
+ node.type !== "documentBody"
) {
- const column =
- node.type === "mappingValue" &&
- !isExplicitMappingItem(parent as MappingItem)
- ? parent!.position.start.column
- : node.position.start.column;
-
- const cases: NodeTableCollectionNodeCase[] = [
- { mode: "gt", attachee: node },
- ];
-
- if (node.type === "sequenceItem") {
- const parentParent = parentStack[parentStack.length - 2];
- if (parentParent.type !== "documentBody") {
- const sequence = parent as Sequence;
- if (node === getLast(sequence.children)) {
- cases.push({ mode: "gte", attachee: sequence });
- }
+ const { start, end } = node.position;
+ const lines = [end.line].concat(start.line === end.line ? [] : start.line);
+
+ for (const line of lines) {
+ const currentEndNode = nodeTable[line - 1].trailingNode;
+ if (!currentEndNode || end.column >= currentEndNode.position.end.column) {
+ nodeTable[line - 1].trailingNode = node;
}
}
-
- nodeTable[node.position.start.line - 1].collectionNode = {
- node,
- column,
- cases,
- };
}
if ("children" in node) {
- (node.children as YamlUnistNode[]).forEach(child =>
- initNodeTable(child, nodeTable, context, parentStack.concat(node)),
- );
+ (node.children as YamlUnistNode[]).forEach(child => {
+ defineParent(child, node);
+ initNodeTable(child, nodeTable, context);
+ });
}
}
@@ -147,49 +130,103 @@ function attachComment(
) {
const commentLine = comment.position.start.line;
- const trailingNode = nodeTable[commentLine - 1].trailingNode;
+ const { trailingAttachableNode } = nodeTable[commentLine - 1];
if (
- trailingNode !== null &&
- trailingNode.type !== "blockFolded" &&
- trailingNode.type !== "blockLiteral"
+ trailingAttachableNode !== null &&
+ trailingAttachableNode.type !== "blockFolded" &&
+ trailingAttachableNode.type !== "blockLiteral"
) {
- defineCommentParent(comment, trailingNode);
- trailingNode.trailingComments.push(comment);
+ defineParent(comment, trailingAttachableNode);
+ trailingAttachableNode.trailingComments.push(comment);
return;
}
for (let line = commentLine; line >= document.position.start.line; line--) {
- const { collectionNode } = nodeTable[line - 1];
-
- if (collectionNode === null) {
- continue;
+ const { trailingNode } = nodeTable[line - 1];
+
+ let currentNode: YamlUnistNode;
+
+ if (trailingNode === null) {
+ /**
+ * a:
+ * b:
+ * #b
+ * #a
+ *
+ * a:
+ * b:
+ * #a
+ * #a
+ */
+ if (line !== commentLine && nodeTable[line - 1].comment !== null) {
+ currentNode = nodeTable[line - 1].comment!.parent!;
+ } else {
+ continue;
+ }
+ } else {
+ currentNode = trailingNode;
}
- const { cases, node, column } = collectionNode;
-
- for (const { mode, attachee } of cases) {
- if (
- node.position.end.offset <= comment.position.start.offset &&
- column + (mode === "gt" ? 1 : 0) <= comment.position.start.column
- ) {
- defineCommentParent(comment, attachee);
- attachee.endComments.push(comment);
+ while (true) {
+ if (ownEndComment(currentNode, comment)) {
+ defineParent(comment, currentNode);
+ currentNode.endComments.push(comment);
return;
}
+
+ if (currentNode.parent === undefined) {
+ break;
+ }
+
+ currentNode = currentNode.parent;
}
break;
}
for (let line = commentLine + 1; line <= document.position.end.line; line++) {
- const leadingNode = nodeTable[line - 1].leadingNode;
- if (leadingNode !== null) {
- defineCommentParent(comment, leadingNode);
- leadingNode.leadingComments.push(comment);
+ const { leadingAttachableNode } = nodeTable[line - 1];
+ if (leadingAttachableNode !== null) {
+ defineParent(comment, leadingAttachableNode);
+ leadingAttachableNode.leadingComments.push(comment);
return;
}
}
- defineCommentParent(comment, document.children[1]);
+ defineParent(comment, document.children[1]);
document.children[1].children.push(comment);
}
+
+function ownEndComment(
+ node: YamlUnistNode,
+ comment: Comment,
+): node is Extract {
+ if (comment.position.end.offset < node.position.end.offset) {
+ return false;
+ }
+
+ switch (node.type) {
+ case "sequence":
+ return (
+ node.parent!.type !== "documentBody" &&
+ comment.position.start.column >= node.position.start.column &&
+ comment.position.start.offset >
+ getLast(node.children)!.position.end.offset
+ );
+ case "sequenceItem":
+ return comment.position.start.column > node.position.start.column;
+ case "mappingValue":
+ return (
+ comment.position.start.column > node.parent!.position.start.column &&
+ !isBlockValue(node.children[0])
+ );
+ case "mappingKey":
+ return (
+ comment.position.start.column > node.parent!.position.start.column &&
+ !isBlockValue(node.children[0]) &&
+ isExplicitMappingItem(node.parent as MappingItem)
+ );
+ default:
+ return false;
+ }
+}
diff --git a/src/transform.ts b/src/transform.ts
index b05c5163..52e05fe6 100644
--- a/src/transform.ts
+++ b/src/transform.ts
@@ -41,7 +41,7 @@ import {
SequenceItem,
YamlUnistNode,
} from "./types";
-import { defineCommentParent } from "./utils";
+import { defineParent } from "./utils";
export type YamlNode =
| null
@@ -148,7 +148,7 @@ export function transformNode(node: YamlNode, context: Context): YamlUnistNode {
newStartOffset <= start &&
transformedNode.position.start.offset >= end
) {
- defineCommentParent(comment, transformedNode);
+ defineParent(comment, transformedNode);
transformedNode.middleComments.push(comment);
} else if (
(transformedNode.type === "blockFolded" ||
@@ -156,7 +156,7 @@ export function transformNode(node: YamlNode, context: Context): YamlUnistNode {
(transformedNode.position.start.offset < start &&
transformedNode.position.end.offset > end)
) {
- defineCommentParent(comment, transformedNode);
+ defineParent(comment, transformedNode);
transformedNode.trailingComments.push(comment);
}
context.comments.push(comment);
diff --git a/src/transforms/document.ts b/src/transforms/document.ts
index e1c60169..6e4265f2 100644
--- a/src/transforms/document.ts
+++ b/src/transforms/document.ts
@@ -1,11 +1,7 @@
import assert = require("assert");
import { Context } from "../transform";
import { Document, DocumentHead, Position } from "../types";
-import {
- createCommentAttachableNode,
- defineCommentParent,
- getLast,
-} from "../utils";
+import { createCommentAttachableNode, defineParent, getLast } from "../utils";
export function transformDocument(
document: yaml.Document,
@@ -91,7 +87,7 @@ export function transformDocument(
directive => {
if (directive.type === "comment") {
context.comments.push(directive);
- defineCommentParent(directive, documentHead);
+ defineParent(directive, documentHead);
}
return directive;
},
diff --git a/src/types.ts b/src/types.ts
index 6f84d8f9..2e30a1a6 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -15,6 +15,8 @@ export interface Position {
export interface Node {
type: string;
position: Position;
+ /** @internal non-enumerable */
+ parent?: YamlUnistNode;
}
export interface Parent extends Node {
@@ -100,8 +102,6 @@ export interface Null extends Node {
export interface Comment extends Node {
type: "comment";
value: string;
- /** @internal non-enumerable */
- parent?: Extract;
}
export interface Anchor extends Node {
diff --git a/src/utils.ts b/src/utils.ts
index 879c32d3..ed746c01 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -26,8 +26,8 @@ export function getLast(array: T[]) {
return array[array.length - 1] as T | undefined;
}
-export function defineCommentParent(comment: Comment, parent: YamlUnistNode) {
- Object.defineProperty(comment, "parent", {
+export function defineParent(node: YamlUnistNode, parent: YamlUnistNode) {
+ Object.defineProperty(node, "parent", {
value: parent,
enumerable: false,
});
diff --git a/tsconfig.build.json b/tsconfig.build.json
index b48eaafd..101ad79f 100644
--- a/tsconfig.build.json
+++ b/tsconfig.build.json
@@ -3,7 +3,6 @@
"include": ["src/index.ts"],
"compilerOptions": {
"rootDir": "src",
- "outDir": "lib",
- "inlineSourceMap": false
+ "outDir": "lib"
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 89ea5bd7..78562f60 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,8 +6,7 @@
"declaration": true,
"importHelpers": true,
"noUnusedLocals": true,
- "noUnusedParameters": true,
- "inlineSourceMap": true
+ "noUnusedParameters": true
},
"include": ["src/**/*.ts", "tests/**/*.ts"]
}