recital / core / src / tools / parse-inline-meta.ts
parse-inline-meta.ts
Raw
/**
 * Copyright (c) 2022 Amorphous
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

import { separateAtShorthand } from './at-shorthand'
import { parseTOMLMeta } from './parse-toml-meta'
import { splitLineBySpacesWithQuotes } from './split-line-by-spaces-with-quotes'

/**
 * Parses an inline string out into Recital-style inline meta.
 *
 * Generally, inline meta follows the following properties:
 * * It's separated by spaces, but adding quotes around strings will preserve spaces
 * * properties that start with @ are parsed as at-shorthand
 * * properties that have an = in them (no spaces) are processed as TOML
 * * If there has not been any TOML or at-shorthand properties yet, the first plaintext string property (including spaces)
 * 	 is designated as the page's title.
 * * Inline meta can be superceded by block meta
 * @param inlineMeta a string of meta to parse
 * @returns a key/value object of parsed meta
 */
export const parseInlineMeta = (inlineMeta: string): { [key: string]: any } => {
	let inlineMetaObject: { [key: string]: any } = {}
	let autoTitleAvailable = true
	let autoTitle = ''

	const inlineMetaTokens = splitLineBySpacesWithQuotes(inlineMeta)

	for (let token of inlineMetaTokens) {
		// if it starts with an @, we have an at-shorthand
		if (token.startsWith('@')) {
			autoTitleAvailable = false
			const tokenMeta = separateAtShorthand(token)
			inlineMetaObject = { ...inlineMetaObject, ...tokenMeta }
			continue
		}

		// if there is an equals, we operate on it with TOML
		if (token.indexOf('=') >= 0) {
			autoTitleAvailable = false
			const tokenMeta = parseTOMLMeta(token)
			inlineMetaObject = { ...inlineMetaObject, ...tokenMeta }
			continue
		}

		// if this is the 'first' set of meta properties, and there
		// is no processing to do on them, we set it as the title
		if (autoTitleAvailable) {
			autoTitle += token + ' '
			continue
		}

		// otherwise, we just assume that it's a boolean with value true
		inlineMetaObject[token] = true
	}

	// add the generated title, if it's relevant
	autoTitle = autoTitle.trim()
	if (autoTitle) {
		inlineMetaObject.title = autoTitle
	}

	return inlineMetaObject
}