Files
OJ2/apps/web/src/shared/extensions/hangIndent.ts
T
xuyueandClaude Opus 5.5 395be1a19b fix(自学): 手机上代码折行看着像另起了一行,改回整行横着滑
正文的代码块、填空、排序、找错四处都不折行了,和桌面一样。排序和找错是整组一起滑,
每行卡片一样宽(= 最长那行)。题目页编辑器的折行不动。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:39:27 +08:00

74 lines
2.4 KiB
TypeScript

import { RangeSetBuilder } from "@codemirror/state"
import {
Decoration,
type DecorationSet,
EditorView,
ViewPlugin,
type ViewUpdate,
} from "@codemirror/view"
/**
* 手机上代码折行(题目页的编辑器)。原来是横着滚,可没有滚动条也看不出右边还有。
* 折下来的那截缩到这一行的代码下面再进两格,一眼看得出还是同一行。
* 自学的代码块和练一练也这么折过,用户嫌不好看,又改回横着滚了。
*/
/** 行首空白占几格,tab 按 4 */
function leadingWidth(text: string): number {
let width = 0
for (const ch of text) {
if (ch === " ") width++
else if (ch === "\t") width += 4
else break
}
return width
}
const glue = Decoration.mark({ attributes: { style: "white-space: nowrap" } })
function hangDecorations(view: EditorView): DecorationSet {
const builder = new RangeSetBuilder<Decoration>()
for (const { from, to } of view.visibleRanges) {
for (let pos = from; pos <= to;) {
const line = view.state.doc.lineAt(pos)
const width = leadingWidth(line.text) + 2
// 6px 是 CodeMirror 给 .cm-line 的左内边距,盖掉了要补回来
builder.add(
line.from,
line.from,
Decoration.line({
attributes: {
style: `padding-left: calc(${width}ch + 6px); text-indent: -${width}ch; word-break: keep-all; overflow-wrap: anywhere`,
},
}),
)
// 行首缩进后面紧跟一长串没空格的(printf("%d",a*100+b*10+c);),浏览器会在缩进后面折,
// 第一行只剩一截空白。把缩进和第一个字粘成不折的一段,长串就接在缩进后面再折
const indent = line.text.match(/^[ \t]+/)?.[0].length ?? 0
if (indent > 0 && indent < line.length) {
builder.add(line.from, line.from + indent + 1, glue)
}
pos = line.to + 1
}
}
return builder.finish()
}
const hangPlugin = ViewPlugin.fromClass(
class {
decorations: DecorationSet
constructor(view: EditorView) {
this.decorations = hangDecorations(view)
}
update(update: ViewUpdate) {
if (update.docChanged || update.viewportChanged) {
this.decorations = hangDecorations(update.view)
}
}
},
{ decorations: (plugin) => plugin.decorations },
)
/** 编辑器:折行 + 悬挂缩进 */
export const hangWrapExtensions = [EditorView.lineWrapping, hangPlugin]