Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@microsoft/tsdoc",
"comment": "Fix an issue where `TSDocEmitter` dropped a line break that appeared before an inline node such as a code span, `{@link}` tag, or HTML element, joining the adjacent words.",
"type": "patch"
}
],
"packageName": "@microsoft/tsdoc",
"email": "109114+spencerbeggs@users.noreply.github.com"
}
51 changes: 51 additions & 0 deletions tsdoc/src/emitters/__tests__/TSDocEmitter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,54 @@ test('04 TSDocEmitter.renderDeclarationReference()', () => {
});
expect(htmlTag.emitAsTsdoc()).toMatchInlineSnapshot(`"my-package#(MyClass:class)"`);
});

test('05 Emit soft breaks before inline nodes', () => {
const input: string = `
/**
* The policy is
* \`fail\`.
*
* See the
* {@link Foo} thing.
*
* This is an
* <b>element</b>.
*
* The policy is
* fail now.
*
* Then \`x\`
* then b.
*
* See {@link Foo}
* \`x\` too.
*/
`;

expect(createSnapshot(input)).toMatchInlineSnapshot(`
Object {
"errors": Array [],
"output": "
/**
* The policy is
* \`fail\`.
*
* See the
* {@link Foo} thing.
*
* This is an
* <b>element</b>.
*
* The policy is
* fail now.
*
* Then \`x\`
* then b.
*
* See {@link Foo}
* \`x\` too.
*/
",
}
`);
});
18 changes: 14 additions & 4 deletions tsdoc/src/transforms/TrimSpacesTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,21 @@ export class TrimSpacesTransform {
// as soon as nonempty content is encountered.
let finishedSkippingLeadingSpaces: boolean = false;

function pushAccumulatedText(): void {
function pushAccumulatedText(followedByInlineNode: boolean): void {
const lines: string[] = accumulatedTextChunks.join('').split('\n');
for (let i: number = 0; i < lines.length; i++) {
const line: string = lines[i];
if (line.length !== 0) {
if (line.length === 0) {
// If the text ended with a line break and an inline node (e.g. a code span or {@link}) comes next,
// preserve the soft break; otherwise the text and the node would be joined without any separator.
if (followedByInlineNode && i !== 0 && i === lines.length - 1) {
transformedNodes.push(
new DocSoftBreak({
configuration: docParagraph.configuration
})
);
}
} else {
if (i !== 0) {
transformedNodes.push(
new DocSoftBreak({
Expand Down Expand Up @@ -90,7 +100,7 @@ export class TrimSpacesTransform {
if (accumulatedTextChunks.length > 0) {
// TODO: We should probably track the accumulatedNodes somehow, e.g. so we can map them back to the
// original excerpts. But we need a developer scenario before we can design this API.
pushAccumulatedText();
pushAccumulatedText(true);
}

transformedNodes.push(node);
Expand All @@ -100,7 +110,7 @@ export class TrimSpacesTransform {

// Push the accumulated text
if (accumulatedTextChunks.length > 0) {
pushAccumulatedText();
pushAccumulatedText(false);
}

const transformedParagraph: DocParagraph = new DocParagraph({
Expand Down
Loading