AbdulElahGwaith's picture
Upload folder using huggingface_hub
88df9e4 verified
import matter from '@gr2m/gray-matter'
import { validateJson } from '@/tests/lib/validate-json-schema'
interface ReadFrontmatterOptions {
schema?: Record<string, any> // Schema can have arbitrary properties for validation
filepath?: string | null
}
function readFrontmatter(markdown: string, opts: ReadFrontmatterOptions = {}) {
const schema = opts.schema || { type: 'object', properties: {} }
const filepath = opts.filepath || null
let content
let data
try {
;({ content, data } = matter(markdown))
} catch (e: any) {
const defaultReason = 'invalid frontmatter entry'
const reason = e.reason
? // make this common error message a little easier to understand
e.reason.startsWith('can not read a block mapping entry;') ||
e.reason === 'bad indentation of a mapping entry'
? defaultReason
: e.reason
: defaultReason
const error: any = {
reason,
message: 'YML parsing error!',
}
if (filepath) error.filepath = filepath
const errors = [error]
console.warn(errors)
return { errors }
}
const validate: any = validateJson(schema, data)
// Combine the AJV-supplied `instancePath` and `params` into a more user-friendly frontmatter path.
// For example, given:
// "instancePath": "/versions",
// "params": { "additionalProperty": "ftp" }
// return:
// property: 'versions.ftp'
//
// The purpose is to help users understand that the error is on the `fpt` key within the `versions` object.
// Note if the error is on a top-level FM property like `title`, the `instancePath` will be empty.
const cleanPropertyPath = (params: Record<string, any>, instancePath: string) => {
const mainProps = Object.values(params)[0]
if (!instancePath) return mainProps
const prefixProps = instancePath.replace('/', '').replace(/\//g, '.')
return typeof mainProps !== 'object' ? `${prefixProps}.${mainProps}` : prefixProps
}
const errors = []
if (!validate.isValid && filepath) {
const formattedErrors = validate.errors.map((error: any) => {
const userFriendly: any = {}
userFriendly.property = cleanPropertyPath(error.params, error.instancePath)
userFriendly.message = error.message
userFriendly.reason = error.keyword
userFriendly.filepath = filepath
return userFriendly
})
errors.push(...formattedErrors)
} else if (!validate.isValid) {
errors.push(...validate.errors)
}
return { content, data, errors }
}
// Expose gray-matter's underlying stringify method for joining a parsed
// frontmatter object and a markdown string back into a unified string
//
// stringify('some string', {some: 'frontmatter'})
readFrontmatter.stringify = matter.stringify
export default readFrontmatter