♿ start new lines at indent
This commit is contained in:
@@ -441,36 +441,24 @@ const hrPlugin = ViewPlugin.fromClass(
|
|||||||
// Paragraphs in the manuscript use single newlines (no blank separators),
|
// Paragraphs in the manuscript use single newlines (no blank separators),
|
||||||
// so every text line is a paragraph. We indent all of them except the first
|
// so every text line is a paragraph. We indent all of them except the first
|
||||||
// paragraph after a heading, HR, or document start (traditional typography).
|
// paragraph after a heading, HR, or document start (traditional typography).
|
||||||
const blankLineDeco = Decoration.line({ class: 'cm-blank-line' })
|
const noIndentDeco = Decoration.line({ class: 'cm-no-indent' })
|
||||||
const paragraphStartDeco = Decoration.line({ class: 'cm-paragraph-start' })
|
|
||||||
|
|
||||||
function buildParagraphDecos(view: EditorView): DecorationSet {
|
function buildParagraphDecos(view: EditorView): DecorationSet {
|
||||||
const builder = new RangeSetBuilder<Decoration>()
|
const builder = new RangeSetBuilder<Decoration>()
|
||||||
const doc = view.state.doc
|
const doc = view.state.doc
|
||||||
// Start true so the very first text paragraph gets no indent
|
|
||||||
let skipNextIndent = true
|
|
||||||
|
|
||||||
for (let n = 1; n <= doc.lines; n++) {
|
for (let n = 1; n <= doc.lines; n++) {
|
||||||
const line = doc.line(n)
|
const line = doc.line(n)
|
||||||
const text = line.text
|
const text = line.text
|
||||||
const isBlank = text.trim() === ''
|
|
||||||
const isHeading = /^#{1,6} /.test(text)
|
const isHeading = /^#{1,6} /.test(text)
|
||||||
const isHR = /^---+$/.test(text.trim())
|
const isHR = /^---+$/.test(text.trim())
|
||||||
const isSpecial = /^[-*>]/.test(text) // list / blockquote
|
const isSpecial = /^[-*>]/.test(text) // list / blockquote / blank
|
||||||
|
|
||||||
if (isBlank) {
|
// Only suppress indent for structural lines — never for regular text.
|
||||||
builder.add(line.from, line.from, blankLineDeco)
|
// This ensures no text line ever changes its decoration status based on
|
||||||
// blank lines don't affect the skip flag
|
// neighboring lines, eliminating cascade-induced layout shifts.
|
||||||
} else if (isHeading || isHR) {
|
if (isHeading || isHR || isSpecial) {
|
||||||
skipNextIndent = true
|
builder.add(line.from, line.from, noIndentDeco)
|
||||||
} else if (isSpecial) {
|
|
||||||
skipNextIndent = false
|
|
||||||
} else {
|
|
||||||
// Regular text paragraph
|
|
||||||
if (!skipNextIndent) {
|
|
||||||
builder.add(line.from, line.from, paragraphStartDeco)
|
|
||||||
}
|
|
||||||
skipNextIndent = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return builder.finish()
|
return builder.finish()
|
||||||
@@ -481,7 +469,7 @@ const paragraphIndentPlugin = ViewPlugin.fromClass(
|
|||||||
decorations: DecorationSet
|
decorations: DecorationSet
|
||||||
constructor(view: EditorView) { this.decorations = buildParagraphDecos(view) }
|
constructor(view: EditorView) { this.decorations = buildParagraphDecos(view) }
|
||||||
update(update: ViewUpdate) {
|
update(update: ViewUpdate) {
|
||||||
if (update.docChanged || update.viewportChanged) {
|
if (update.docChanged) {
|
||||||
this.decorations = buildParagraphDecos(update.view)
|
this.decorations = buildParagraphDecos(update.view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,8 +504,8 @@ function buildTheme(fontSize: number, dark: boolean, focusMode = false): ReturnT
|
|||||||
'.cm-cursor': { borderLeftColor: 'var(--accent)' },
|
'.cm-cursor': { borderLeftColor: 'var(--accent)' },
|
||||||
'.cm-selectionBackground': { backgroundColor: 'var(--active-bg)' },
|
'.cm-selectionBackground': { backgroundColor: 'var(--active-bg)' },
|
||||||
'&.cm-focused .cm-selectionBackground': { backgroundColor: 'var(--active-bg)' },
|
'&.cm-focused .cm-selectionBackground': { backgroundColor: 'var(--active-bg)' },
|
||||||
'.cm-blank-line': { fontSize: '0.45em', lineHeight: '1' },
|
'.cm-line': { textIndent: '2em' },
|
||||||
'.cm-paragraph-start': { textIndent: '2em' },
|
'.cm-no-indent': { textIndent: '0' },
|
||||||
'.cm-gutters': { display: 'none' },
|
'.cm-gutters': { display: 'none' },
|
||||||
'.cm-activeLine': { backgroundColor: 'transparent' },
|
'.cm-activeLine': { backgroundColor: 'transparent' },
|
||||||
'.cm-activeLineGutter': { backgroundColor: 'transparent' },
|
'.cm-activeLineGutter': { backgroundColor: 'transparent' },
|
||||||
|
|||||||
Reference in New Issue
Block a user