refactor: change return type of frontmatter extractor to use undefined

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2023-05-19 19:41:25 +02:00
parent 77f858bff8
commit 4d0a2cb79e
5 changed files with 29 additions and 56 deletions

View file

@ -4,7 +4,6 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { extractFrontmatter } from './extractor.js' import { extractFrontmatter } from './extractor.js'
import type { PresentFrontmatterExtractionResult } from './types.js'
import { describe, expect, it } from '@jest/globals' import { describe, expect, it } from '@jest/globals'
describe('frontmatter extraction', () => { describe('frontmatter extraction', () => {
@ -12,22 +11,22 @@ describe('frontmatter extraction', () => {
it('is false when note does not contain three dashes at all', () => { it('is false when note does not contain three dashes at all', () => {
const testNote = ['abcdef', 'more text'] const testNote = ['abcdef', 'more text']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(false) expect(extraction).toBeUndefined()
}) })
it('is false when note does not start with three dashes', () => { it('is false when note does not start with three dashes', () => {
const testNote = ['', '---', 'this is not frontmatter'] const testNote = ['', '---', 'this is not frontmatter']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(false) expect(extraction).toBeUndefined()
}) })
it('is false when note start with less than three dashes', () => { it('is false when note start with less than three dashes', () => {
const testNote = ['--', 'this is not frontmatter'] const testNote = ['--', 'this is not frontmatter']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(false) expect(extraction).toBeUndefined()
}) })
it('is false when note starts with three dashes but contains other characters in the same line', () => { it('is false when note starts with three dashes but contains other characters in the same line', () => {
const testNote = ['--- a', 'this is not frontmatter'] const testNote = ['--- a', 'this is not frontmatter']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(false) expect(extraction).toBeUndefined()
}) })
it('is false when note has no ending marker for frontmatter', () => { it('is false when note has no ending marker for frontmatter', () => {
const testNote = [ const testNote = [
@ -38,75 +37,63 @@ describe('frontmatter extraction', () => {
'end marker' 'end marker'
] ]
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(false) expect(extraction).toBeUndefined()
}) })
it('is false when note end marker is present but with not the same amount of dashes as start marker', () => { it('is false when note end marker is present but with not the same amount of dashes as start marker', () => {
const testNote = ['---', 'this is not frontmatter', '----', 'content'] const testNote = ['---', 'this is not frontmatter', '----', 'content']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(false) expect(extraction).toBeUndefined()
}) })
it('is true when note end marker is present with the same amount of dashes as start marker', () => { it('is true when note end marker is present with the same amount of dashes as start marker', () => {
const testNote = ['---', 'this is frontmatter', '---', 'content'] const testNote = ['---', 'this is frontmatter', '---', 'content']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(true) expect(extraction).toBeDefined()
}) })
it('is true when note end marker is present with the same amount of dashes as start marker but without content', () => { it('is true when note end marker is present with the same amount of dashes as start marker but without content', () => {
const testNote = ['---', 'this is frontmatter', '---'] const testNote = ['---', 'this is frontmatter', '---']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(true) expect(extraction).toBeDefined()
}) })
it('is true when note end marker is present with the same amount of dots as start marker', () => { it('is true when note end marker is present with the same amount of dots as start marker', () => {
const testNote = ['---', 'this is frontmatter', '...', 'content'] const testNote = ['---', 'this is frontmatter', '...', 'content']
const extraction = extractFrontmatter(testNote) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(true) expect(extraction).toBeDefined()
}) })
}) })
describe('lineOffset property', () => { describe('lineOffset property', () => {
it('is correct for single line frontmatter without content', () => { it('is correct for single line frontmatter without content', () => {
const testNote = ['---', 'single line frontmatter', '...'] const testNote = ['---', 'single line frontmatter', '...']
const extraction = extractFrontmatter( const extraction = extractFrontmatter(testNote)
testNote expect(extraction?.lineOffset).toEqual(3)
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(3)
}) })
it('is correct for single line frontmatter with content', () => { it('is correct for single line frontmatter with content', () => {
const testNote = ['---', 'single line frontmatter', '...', 'content'] const testNote = ['---', 'single line frontmatter', '...', 'content']
const extraction = extractFrontmatter( const extraction = extractFrontmatter(testNote)
testNote expect(extraction?.lineOffset).toEqual(3)
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(3)
}) })
it('is correct for multi-line frontmatter without content', () => { it('is correct for multi-line frontmatter without content', () => {
const testNote = ['---', 'abc', '123', 'def', '...'] const testNote = ['---', 'abc', '123', 'def', '...']
const extraction = extractFrontmatter( const extraction = extractFrontmatter(testNote)
testNote expect(extraction?.lineOffset).toEqual(5)
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(5)
}) })
it('is correct for multi-line frontmatter with content', () => { it('is correct for multi-line frontmatter with content', () => {
const testNote = ['---', 'abc', '123', 'def', '...', 'content'] const testNote = ['---', 'abc', '123', 'def', '...', 'content']
const extraction = extractFrontmatter( const extraction = extractFrontmatter(testNote)
testNote expect(extraction?.lineOffset).toEqual(5)
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(5)
}) })
}) })
describe('rawText property', () => { describe('rawText property', () => {
it('contains single-line frontmatter text', () => { it('contains single-line frontmatter text', () => {
const testNote = ['---', 'single-line', '...', 'content'] const testNote = ['---', 'single-line', '...', 'content']
const extraction = extractFrontmatter( const extraction = extractFrontmatter(testNote)
testNote expect(extraction?.rawText).toEqual('single-line')
) as PresentFrontmatterExtractionResult
expect(extraction.rawText).toEqual('single-line')
}) })
it('contains multi-line frontmatter text', () => { it('contains multi-line frontmatter text', () => {
const testNote = ['---', 'multi', 'line', '...', 'content'] const testNote = ['---', 'multi', 'line', '...', 'content']
const extraction = extractFrontmatter( const extraction = extractFrontmatter(testNote)
testNote expect(extraction?.rawText).toEqual('multi\nline')
) as PresentFrontmatterExtractionResult
expect(extraction.rawText).toEqual('multi\nline')
}) })
}) })
}) })

View file

@ -20,11 +20,9 @@ const FRONTMATTER_END_REGEX = /^(?:-{3,}|\.{3,})$/
*/ */
export const extractFrontmatter = ( export const extractFrontmatter = (
lines: string[] lines: string[]
): FrontmatterExtractionResult => { ): FrontmatterExtractionResult | undefined => {
if (lines.length < 2 || !FRONTMATTER_BEGIN_REGEX.test(lines[0])) { if (lines.length < 2 || !FRONTMATTER_BEGIN_REGEX.test(lines[0])) {
return { return undefined
isPresent: false
}
} }
for (let i = 1; i < lines.length; i++) { for (let i = 1; i < lines.length; i++) {
if ( if (
@ -32,13 +30,10 @@ export const extractFrontmatter = (
FRONTMATTER_END_REGEX.test(lines[i]) FRONTMATTER_END_REGEX.test(lines[i])
) { ) {
return { return {
isPresent: true,
rawText: lines.slice(1, i).join('\n'), rawText: lines.slice(1, i).join('\n'),
lineOffset: i + 1 lineOffset: i + 1
} }
} }
} }
return { return undefined
isPresent: false
}
} }

View file

@ -4,16 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
export type FrontmatterExtractionResult = export interface FrontmatterExtractionResult {
| PresentFrontmatterExtractionResult
| NonPresentFrontmatterExtractionResult
export interface PresentFrontmatterExtractionResult {
isPresent: true
rawText: string rawText: string
lineOffset: number lineOffset: number
} }
interface NonPresentFrontmatterExtractionResult {
isPresent: false
}

View file

@ -20,7 +20,7 @@ export class FrontmatterLinter implements Linter {
lint(view: EditorView): Diagnostic[] { lint(view: EditorView): Diagnostic[] {
const lines = view.state.doc.toString().split('\n') const lines = view.state.doc.toString().split('\n')
const frontmatterExtraction = extractFrontmatter(lines) const frontmatterExtraction = extractFrontmatter(lines)
if (!frontmatterExtraction.isPresent) { if (frontmatterExtraction === undefined) {
return [] return []
} }
const startOfYaml = lines[0].length + 1 const startOfYaml = lines[0].length + 1

View file

@ -8,7 +8,7 @@ import { initialState } from './initial-state'
import { createNoteFrontmatterFromYaml } from './raw-note-frontmatter-parser/parser' import { createNoteFrontmatterFromYaml } from './raw-note-frontmatter-parser/parser'
import type { NoteDetails } from './types/note-details' import type { NoteDetails } from './types/note-details'
import { extractFrontmatter, generateNoteTitle } from '@hedgedoc/commons' import { extractFrontmatter, generateNoteTitle } from '@hedgedoc/commons'
import type { PresentFrontmatterExtractionResult } from '@hedgedoc/commons' import type { FrontmatterExtractionResult } from '@hedgedoc/commons'
/** /**
* Copies a {@link NoteDetails} but with another markdown content. * Copies a {@link NoteDetails} but with another markdown content.
@ -40,7 +40,7 @@ const buildStateFromMarkdownContentAndLines = (
): NoteDetails => { ): NoteDetails => {
const frontmatterExtraction = extractFrontmatter(markdownContentLines) const frontmatterExtraction = extractFrontmatter(markdownContentLines)
const lineStartIndexes = calculateLineStartIndexes(markdownContentLines) const lineStartIndexes = calculateLineStartIndexes(markdownContentLines)
if (frontmatterExtraction.isPresent) { if (frontmatterExtraction !== undefined) {
return buildStateFromFrontmatterUpdate( return buildStateFromFrontmatterUpdate(
{ {
...state, ...state,
@ -76,7 +76,7 @@ const buildStateFromMarkdownContentAndLines = (
*/ */
const buildStateFromFrontmatterUpdate = ( const buildStateFromFrontmatterUpdate = (
state: NoteDetails, state: NoteDetails,
frontmatterExtraction: PresentFrontmatterExtractionResult frontmatterExtraction: FrontmatterExtractionResult
): NoteDetails => { ): NoteDetails => {
if (frontmatterExtraction.rawText === state.rawFrontmatter) { if (frontmatterExtraction.rawText === state.rawFrontmatter) {
return state return state