Skip to content

Commit 5190cf7

Browse files
committed
fix: preserve AST source mapping consistency when merging paragraphs
1 parent 059d863 commit 5190cf7

File tree

2 files changed

+49
-25
lines changed

2 files changed

+49
-25
lines changed

src/typstToTextlintAst.ts

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,19 @@ const splitNodesByUnsupportedParagraphContent = (
370370
return results;
371371
};
372372

373-
const mergeAdjacentParagraphNodes = (nodes: Content[]): Content[] => {
373+
const mergeAdjacentParagraphNodes = (
374+
nodes: Content[],
375+
sourceRaw: string,
376+
sourceRangeStart: number,
377+
): Content[] => {
374378
const merged: Content[] = [];
375379

380+
const offsetToLoc = (offset: number): TxtNodePosition => {
381+
const text = sourceRaw.slice(0, offset - sourceRangeStart);
382+
const lines = text.split("\n");
383+
return { line: lines.length, column: lines[lines.length - 1].length };
384+
};
385+
376386
for (const node of nodes) {
377387
const previous = merged[merged.length - 1];
378388
if (
@@ -386,28 +396,35 @@ const mergeAdjacentParagraphNodes = (nodes: Content[]): Content[] => {
386396
) {
387397
const previousLastChild = previous.children[previous.children.length - 1];
388398
const currentFirstChild = node.children[0];
389-
const needsSeparator =
399+
const gapStart = previousLastChild.range[1];
400+
const gapEnd = currentFirstChild.range[0];
401+
const gapText = sourceRaw.slice(
402+
gapStart - sourceRangeStart,
403+
gapEnd - sourceRangeStart,
404+
);
405+
406+
const trailingWsMatch = gapText.match(/(\s+)$/);
407+
const separatorNode: Content[] =
390408
previous.children.length > 0 &&
391409
node.children.length > 0 &&
392-
!previousLastChild.raw.endsWith(" ") &&
393-
!previousLastChild.raw.endsWith("\n") &&
394-
!currentFirstChild.raw.startsWith(" ") &&
395-
!currentFirstChild.raw.startsWith("\n");
396-
397-
const separatorNode: Content[] = needsSeparator
398-
? [
399-
{
400-
type: ASTNodeTypes.Str,
401-
raw: " ",
402-
value: " ",
403-
loc: {
404-
start: previousLastChild.loc.end,
405-
end: currentFirstChild.loc.start,
406-
},
407-
range: [previousLastChild.range[1], currentFirstChild.range[0]],
408-
} as Content,
409-
]
410-
: [];
410+
trailingWsMatch
411+
? (() => {
412+
const ws = trailingWsMatch[1];
413+
const wsOffset = gapEnd - ws.length;
414+
return [
415+
{
416+
type: ASTNodeTypes.Str,
417+
raw: ws,
418+
value: ws,
419+
loc: {
420+
start: offsetToLoc(wsOffset),
421+
end: currentFirstChild.loc.start,
422+
},
423+
range: [wsOffset, gapEnd],
424+
} as Content,
425+
];
426+
})()
427+
: [];
411428

412429
merged[merged.length - 1] = createParagraphNode([
413430
...previous.children,
@@ -1715,7 +1732,14 @@ export const paragraphizeTextlintAstObject = (
17151732
}
17161733
}
17171734

1718-
return { ...rootNode, children: mergeAdjacentParagraphNodes(children) };
1735+
return {
1736+
...rootNode,
1737+
children: mergeAdjacentParagraphNodes(
1738+
children,
1739+
rootNode.raw,
1740+
rootNode.range[0],
1741+
),
1742+
};
17191743
};
17201744

17211745
/**

test/unit/fixtures/inline-content-block-with-non-inline/output.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,11 @@
382382
"line": 8
383383
},
384384
"start": {
385-
"column": 15,
386-
"line": 7
385+
"column": 1,
386+
"line": 8
387387
}
388388
},
389-
"range": [81, 84],
389+
"range": [83, 84],
390390
"raw": " ",
391391
"type": "Str",
392392
"value": " "

0 commit comments

Comments
 (0)