hedgedoc/frontend/src/redux/note-details/raw-note-frontmatter-parser/parser.ts
Tilman Vatteroth 762a0a850e
fix: Move content into to frontend directory
Doing this BEFORE the merge prevents a lot of merge conflicts.

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
2022-11-20 19:48:40 +01:00

143 lines
5.3 KiB
TypeScript

/*
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { load } from 'js-yaml'
import type { SlideOptions } from '../types/slide-show-options'
import type { Iso6391Language, NoteFrontmatter, OpenGraph } from '../types/note-details'
import { NoteTextDirection, NoteType } from '../types/note-details'
import { ISO6391 } from '../types/iso6391'
import type { RawNoteFrontmatter } from './types'
import { initialSlideOptions, initialState } from '../initial-state'
/**
* Creates a new frontmatter metadata instance based on a raw yaml string.
* @param rawYaml The frontmatter content in yaml format.
* @throws Error when the content string is invalid yaml.
* @return Frontmatter metadata instance containing the parsed properties from the yaml content.
*/
export const createNoteFrontmatterFromYaml = (rawYaml: string): NoteFrontmatter => {
const rawNoteFrontmatter = load(rawYaml) as RawNoteFrontmatter
return parseRawNoteFrontmatter(rawNoteFrontmatter)
}
/**
* Creates a new frontmatter metadata instance based on the given raw metadata properties.
* @param rawData A {@link RawNoteFrontmatter} object containing the properties of the parsed yaml frontmatter.
*/
const parseRawNoteFrontmatter = (rawData: RawNoteFrontmatter): NoteFrontmatter => {
let tags: string[]
if (typeof rawData?.tags === 'string') {
tags = rawData?.tags?.split(',').map((entry) => entry.trim()) ?? []
} else if (typeof rawData?.tags === 'object') {
tags = rawData?.tags?.filter((tag) => tag !== null) ?? []
} else {
tags = [...initialState.frontmatter.tags]
}
return {
title: rawData.title ?? initialState.frontmatter.title,
description: rawData.description ?? initialState.frontmatter.description,
robots: rawData.robots ?? initialState.frontmatter.robots,
newlinesAreBreaks: rawData.breaks ?? initialState.frontmatter.newlinesAreBreaks,
GA: rawData.GA ?? initialState.frontmatter.GA,
disqus: rawData.disqus ?? initialState.frontmatter.disqus,
lang: parseLanguage(rawData),
type: parseNoteType(rawData),
dir: parseTextDirection(rawData),
opengraph: parseOpenGraph(rawData),
slideOptions: parseSlideOptions(rawData),
tags
}
}
/**
* Parses the {@link OpenGraph open graph} from the {@link RawNoteFrontmatter}.
*
* @param rawData The raw note frontmatter data.
* @return the parsed {@link OpenGraph open graph}
*/
const parseOpenGraph = (rawData: RawNoteFrontmatter): OpenGraph => {
return { ...(rawData.opengraph ?? initialState.frontmatter.opengraph) }
}
/**
* Parses the {@link Iso6391Language iso 6391 language code} from the {@link RawNoteFrontmatter}.
*
* @param rawData The raw note frontmatter data.
* @return the parsed {@link Iso6391Language iso 6391 language code}
*/
const parseLanguage = (rawData: RawNoteFrontmatter): Iso6391Language => {
return (rawData.lang ? ISO6391.find((lang) => lang === rawData.lang) : undefined) ?? initialState.frontmatter.lang
}
/**
* Parses the {@link NoteType note type} from the {@link RawNoteFrontmatter}.
*
* @param rawData The raw note frontmatter data.
* @return the parsed {@link NoteType note type}
*/
const parseNoteType = (rawData: RawNoteFrontmatter): NoteType => {
return rawData.type !== undefined
? rawData.type === NoteType.SLIDE
? NoteType.SLIDE
: NoteType.DOCUMENT
: initialState.frontmatter.type
}
/**
* Parses the {@link NoteTextDirection note text direction} from the {@link RawNoteFrontmatter}.
*
* @param rawData The raw note frontmatter data.
* @return the parsed {@link NoteTextDirection note text direction}
*/
const parseTextDirection = (rawData: RawNoteFrontmatter): NoteTextDirection => {
return rawData.dir !== undefined
? rawData.dir === NoteTextDirection.LTR
? NoteTextDirection.LTR
: NoteTextDirection.RTL
: initialState.frontmatter.dir
}
/**
* Parses the {@link SlideOptions} from the {@link RawNoteFrontmatter}.
*
* @param rawData The raw note frontmatter data.
* @return the parsed slide options
*/
const parseSlideOptions = (rawData: RawNoteFrontmatter): SlideOptions => {
const rawSlideOptions = rawData?.slideOptions
return {
autoSlide: parseNumber(rawSlideOptions?.autoSlide) ?? initialSlideOptions.autoSlide,
transition: rawSlideOptions?.transition ?? initialSlideOptions.transition,
backgroundTransition: rawSlideOptions?.backgroundTransition ?? initialSlideOptions.backgroundTransition,
autoSlideStoppable: parseBoolean(rawSlideOptions?.autoSlideStoppable) ?? initialSlideOptions.autoSlideStoppable,
slideNumber: parseBoolean(rawSlideOptions?.slideNumber) ?? initialSlideOptions.slideNumber
}
}
/**
* Parses an unknown variable into a boolean.
*
* @param rawData The raw data
* @return The parsed boolean or undefined if it's not possible to parse the data.
*/
const parseBoolean = (rawData: unknown | undefined): boolean | undefined => {
return rawData === undefined ? undefined : rawData === true
}
/**
* Parses an unknown variable into a number.
*
* @param rawData The raw data
* @return The parsed number or undefined if it's not possible to parse the data.
*/
const parseNumber = (rawData: unknown | undefined): number | undefined => {
if (rawData === undefined) {
return undefined
}
const numValue = Number(rawData)
return isNaN(numValue) ? undefined : numValue
}