fix: frontmatter headline

If one wrote a frontmatter the incomplete ending dashes where interpreted as a headline and therefore the last line in the frontmatter was handled as the first heading of the document.

Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
Philip Molares 2024-09-01 12:25:22 +02:00
parent 61fc33fc73
commit 02a5f62d27
6 changed files with 38 additions and 3 deletions

View file

@ -96,4 +96,17 @@ describe('frontmatter extraction', () => {
expect(extraction?.rawText).toEqual('multi\nline')
})
})
describe('is incomplete', () => {
it('if frontmatter is closed with one dash', () => {
const testNote = ['---', 'type: document', '-', 'content']
const extraction = extractFrontmatter(testNote)
expect(extraction?.incomplete).toBeTruthy()
})
it('if frontmatter is closed with two dash', () => {
const testNote = ['---', 'type: document', '-', 'content']
const extraction = extractFrontmatter(testNote)
expect(extraction?.incomplete).toBeTruthy()
})
})
})

View file

@ -7,6 +7,7 @@ import type { FrontmatterExtractionResult } from './types.js'
const FRONTMATTER_BEGIN_REGEX = /^-{3,}$/
const FRONTMATTER_END_REGEX = /^(?:-{3,}|\.{3,})$/
const FRONTMATTER_INCOMPLETE_END_REGEX = /^-{1,2}$/
/**
* Extracts a frontmatter block from a given multiline string.
@ -25,13 +26,21 @@ export const extractFrontmatter = (
return undefined
}
for (let i = 1; i < lines.length; i++) {
if (FRONTMATTER_INCOMPLETE_END_REGEX.test(lines[i])) {
return {
rawText: '',
lineOffset: i + 1,
incomplete: true
}
}
if (
lines[i].length === lines[0].length &&
FRONTMATTER_END_REGEX.test(lines[i])
) {
return {
rawText: lines.slice(1, i).join('\n'),
lineOffset: i + 1
lineOffset: i + 1,
incomplete: false
}
}
}

View file

@ -7,4 +7,5 @@
export interface FrontmatterExtractionResult {
rawText: string
lineOffset: number
incomplete: boolean
}

View file

@ -18,7 +18,7 @@ export class FrontmatterLinter implements Linter {
lint(view: EditorView): Diagnostic[] {
const lines = view.state.doc.toString().split('\n')
const frontmatterExtraction = extractFrontmatter(lines)
if (frontmatterExtraction === undefined) {
if (frontmatterExtraction === undefined || frontmatterExtraction.incomplete) {
return []
}
const frontmatterLines = lines.slice(1, frontmatterExtraction.lineOffset - 1)

View file

@ -19,10 +19,13 @@ import type { CommonMarkdownRendererProps, HeightChangeRendererProps } from '../
import { DocumentTocSidebar } from './document-toc-sidebar'
import styles from './markdown-document.module.scss'
import useResizeObserver from '@react-hook/resize-observer'
import React, { useMemo, useRef, useState } from 'react'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { Logger } from '../../../../utils/logger'
export type DocumentMarkdownRendererProps = CommonMarkdownRendererProps & ScrollProps & HeightChangeRendererProps
const logger = new Logger('DocumentMarkdownRenderer')
/**
* Renders a Markdown document and handles scrolling, yaml metadata and a floating table of contents.
*
@ -64,6 +67,11 @@ export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> =
const markdownBodyRef = useRef<HTMLDivElement>(null)
const currentLineMarkers = useRef<LineMarkers[]>()
// ToDo: Remove this
useEffect(() => {
logger.debug(markdownContentLines)
}, [markdownContentLines])
const extensions = useMarkdownExtensions(
baseUrl,
RendererType.DOCUMENT,

View file

@ -83,6 +83,10 @@ const buildStateFromFrontmatterUpdate = (
state: NoteDetails,
frontmatterExtraction: FrontmatterExtractionResult
): NoteDetails => {
if (frontmatterExtraction.incomplete) {
frontmatterExtraction.rawText = state.rawFrontmatter
return buildStateFromFrontmatter(state, parseFrontmatter(frontmatterExtraction), frontmatterExtraction)
}
if (frontmatterExtraction.rawText === state.rawFrontmatter) {
return state
}