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
78 changes: 38 additions & 40 deletions src/commonmark/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,64 +416,62 @@ function blockWrapIn(
const newlineOffset = 2; // account for two inserted newlines
return insertRawText(
insertedBlock,
formattingText.length + newlineOffset,
formattingText.length + newlineOffset, //only selects the placeholder text, not the formattingText
formattingText.length + placeholderText.length + newlineOffset,
state,
dispatch
);
}

let { from, to } = state.selection;
if (!dispatch) return true;

// check if we need to unwrap
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is already done in the calling function

if (blockUnwrapIn(formattingText, state, dispatch)) {
return true;
}
const from = state.selection.from;
let to = state.selection.to;

// wrap the selected block in code fences, prepending/appending newlines if necessary

let tr = state.tr;

// if the character immediately preceding the selection isn't a newline, add one
if (from > 0 && state.doc.textBetween(from - 1, from) !== "\n") {
tr = tr.insertText("\n", from, from);
from += 1;
to += 1;
}
const surroundingChar = "\n";

// if the character immediately postceding the selection isn't a newline, add one
if (
to + 1 < state.doc.content.size &&
state.doc.textBetween(to, to + 1) !== "\n"
) {
tr = tr.insertText("\n", to + 1, to + 1);
to += 1;
}
//always insert a newline before the selection
tr = tr.insertText(surroundingChar, from, from);
to += 1;

// add this char before and after the selection along with the formatting text
const surroundingChar = "\n";
//always insert a newline after the selection
tr = tr.insertText(surroundingChar, to, to);
to += 1;

// insert the code fences from the end first so we don't mess up our from index
tr.insertText(surroundingChar + formattingText, to);
tr.insertText(formattingText + surroundingChar, from);
//consider if we need to add the surrounding char too, if the text is not already surrounded by newline

if (dispatch) {
// adjust our new text selection based on how many characters we added
const addedTextModifier =
surroundingChar.length + formattingText.length;

tr.setSelection(
TextSelection.create(
state.apply(tr).doc,
from,
// add modifier twice, once for added leading text, once for added trailing text
to + addedTextModifier * 2
)
);
const preceedingNewlineNeeded =
from > 0 && state.doc.textBetween(from - 1, from) !== surroundingChar
? surroundingChar
: "";
const followingNewlineNeeded =
to + 1 < state.doc.content.size &&
state.doc.textBetween(to, to + 1) !== surroundingChar
? surroundingChar
: "";

tr.insertText(formattingText + followingNewlineNeeded, to);
tr.insertText(preceedingNewlineNeeded + formattingText, from);
to += formattingText.length * 2 + preceedingNewlineNeeded.length;

// set the selection to the text inside the code fences, skipping the leading newline

tr.setSelection(
TextSelection.create(
state.apply(tr).doc,
from + preceedingNewlineNeeded.length,
to
)
);

tr.scrollIntoView();
tr.scrollIntoView();

dispatch(tr);
}
dispatch(tr);

return true;
}
Expand Down
16 changes: 16 additions & 0 deletions test/commonmark/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,22 @@ some text
);
});

it("should wrap partial selection in block characters", () => {
const content = "some text";
const expectedSelection = `\`\`\`
some
\`\`\``;
const expectedContent = "\n" + expectedSelection + "\n" + " text";

const state = createState(content, 0, 4);

expect(state).transactionSuccess(
commands.blockWrapInCommand("```"),
expectedContent,
expectedSelection
);
});

it("should unwrap block", () => {
const content = `\`\`\`
some text
Expand Down