feat: Add text wrap option for code blocks (#11614)

This commit is contained in:
Tom Moor
2026-03-02 07:08:12 -05:00
committed by GitHub
parent 1ceb476a04
commit 8dc4f8b422
8 changed files with 53 additions and 9 deletions
+11 -1
View File
@@ -1,4 +1,4 @@
import { CopyIcon, EditIcon, ExpandedIcon } from "outline-icons";
import { CopyIcon, EditIcon, ExpandedIcon, TextWrapIcon } from "outline-icons";
import type { Node as ProseMirrorNode } from "prosemirror-model";
import { NodeSelection } from "prosemirror-state";
import type { EditorState } from "prosemirror-state";
@@ -72,6 +72,16 @@ export default function codeMenuItems(
{
name: "separator",
},
{
name: "toggleCodeBlockWrap",
icon: <TextWrapIcon />,
tooltip: dictionary.wrapText,
active: () => node.attrs.wrap,
visible: !readOnly,
},
{
name: "separator",
},
{
name: "code_block",
label: getLabelForLanguage(node.attrs.language ?? "none"),
+1
View File
@@ -123,6 +123,7 @@ export default function useDictionary() {
uploadImage: t("Upload an image"),
formattingControls: t("Formatting controls"),
distributeColumns: t("Distribute columns"),
wrapText: t("Wrap text"),
}),
[t]
);
+1 -1
View File
@@ -178,7 +178,7 @@
"node-fetch": "2.7.0",
"nodemailer": "^7.0.11",
"octokit": "^3.2.2",
"outline-icons": "^4.0.0",
"outline-icons": "^4.1.0",
"oy-vey": "^0.12.1",
"pako": "^2.1.0",
"passport": "^0.7.0",
+7
View File
@@ -1809,6 +1809,13 @@ mark {
}
}
.code-block.with-line-wrap {
pre {
white-space: pre-wrap;
word-break: break-all;
}
}
.code-block.with-line-numbers {
pre {
padding-left: calc(var(--line-number-gutter-width, 0) * 1em + 1.5em);
+1 -1
View File
@@ -110,7 +110,7 @@ function getDecorations({
const lineDecorations = [];
if (!cache[block.pos] || !cache[block.pos].node.eq(block.node)) {
if (lineNumbers) {
if (lineNumbers && !block.node.attrs.wrap) {
const lineCount =
(block.node.textContent.match(/\n/g) || []).length + 1;
const gutterWidth = String(lineCount).length;
+26 -1
View File
@@ -74,6 +74,10 @@ export default class CodeFence extends Node {
default: DEFAULT_LANGUAGE,
validate: "string",
},
wrap: {
default: false,
validate: "boolean",
},
},
content: "text*",
marks: "comment",
@@ -89,6 +93,7 @@ export default class CodeFence extends Node {
node.querySelector("code") || node,
getAttrs: (dom: HTMLDivElement) => ({
language: dom.dataset.language,
wrap: dom.classList.contains("with-line-wrap"),
}),
},
{
@@ -108,7 +113,11 @@ export default class CodeFence extends Node {
"div",
{
class: `code-block ${
this.showLineNumbers ? "with-line-numbers" : ""
node.attrs.wrap
? "with-line-wrap"
: this.showLineNumbers
? "with-line-numbers"
: ""
}`,
"data-language": node.attrs.language,
},
@@ -128,6 +137,22 @@ export default class CodeFence extends Node {
...attrs,
});
},
toggleCodeBlockWrap: (): Command => (state, dispatch) => {
const codeBlock = findParentNode(isCode)(state.selection);
if (!codeBlock) {
return false;
}
if (dispatch) {
dispatch(
state.tr.setNodeMarkup(codeBlock.pos, undefined, {
...codeBlock.node.attrs,
wrap: !codeBlock.node.attrs.wrap,
})
);
}
return true;
},
edit_mermaid: (): Command => (state, dispatch) => {
const codeBlock =
state.selection instanceof NodeSelection &&
@@ -650,6 +650,7 @@
"Delete embed": "Delete embed",
"Formatting controls": "Formatting controls",
"Distribute columns": "Distribute columns",
"Wrap text": "Wrap text",
"Delete Emoji": "Delete Emoji",
"Emoji deleted": "Emoji deleted",
"I'm sure Delete": "I'm sure Delete",
+5 -5
View File
@@ -17508,12 +17508,12 @@ __metadata:
languageName: node
linkType: hard
"outline-icons@npm:^4.0.0":
version: 4.0.0
resolution: "outline-icons@npm:4.0.0"
"outline-icons@npm:^4.1.0":
version: 4.1.0
resolution: "outline-icons@npm:4.1.0"
peerDependencies:
react: ^17.0.0 || ^18.0.0
checksum: 10c0/45cf01b202b82353ee0b53131bb706db1813ea30a5beaa862a4e4c9ab5be392500f0653e16b137b8521b6881ab487c7bc21b5c748ccc17685a83a6b29fda0daf
checksum: 10c0/883c72d53b3b81e71748c0abd60f164034e86f9723b538c211fc437aa2c8efbfce3b1fe1d41bc608ed402f09142ad8383b1bde2506266a7116a949b575664d04
languageName: node
linkType: hard
@@ -17737,7 +17737,7 @@ __metadata:
nodemailer: "npm:^7.0.11"
nodemon: "npm:^3.1.11"
octokit: "npm:^3.2.2"
outline-icons: "npm:^4.0.0"
outline-icons: "npm:^4.1.0"
oxlint: "npm:1.11.2"
oxlint-tsgolint: "npm:^0.1.6"
oy-vey: "npm:^0.12.1"