зеркало из https://github.com/github/docs.git
86 строки
2.5 KiB
JavaScript
86 строки
2.5 KiB
JavaScript
import matter from 'gray-matter'
|
|
import revalidator from 'revalidator'
|
|
import { difference, intersection } from 'lodash-es'
|
|
import cleanUpDeprecatedGhaeFlagErrors from './temporary-ghae-deprecated-flag-error-cleanup.js'
|
|
|
|
function readFrontmatter(markdown, opts = { validateKeyNames: false, validateKeyOrder: false }) {
|
|
const schema = opts.schema || { properties: {} }
|
|
const filepath = opts.filepath || null
|
|
|
|
let content, data
|
|
let errors = []
|
|
|
|
try {
|
|
;({ content, data } = matter(markdown))
|
|
} catch (e) {
|
|
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;')
|
|
? defaultReason
|
|
: e.reason
|
|
: defaultReason
|
|
|
|
const error = {
|
|
reason,
|
|
message: 'YML parsing error!',
|
|
}
|
|
|
|
if (filepath) error.filepath = filepath
|
|
errors.push(error)
|
|
return { errors }
|
|
}
|
|
|
|
const allowedKeys = Object.keys(schema.properties)
|
|
const existingKeys = Object.keys(data)
|
|
const expectedKeys = intersection(allowedKeys, existingKeys)
|
|
|
|
;({ errors } = revalidator.validate(data, schema))
|
|
|
|
// add filepath property to each error object
|
|
if (errors.length && filepath) {
|
|
errors = errors.map((error) => Object.assign(error, { filepath }))
|
|
}
|
|
|
|
// validate key names
|
|
if (opts.validateKeyNames) {
|
|
const invalidKeys = difference(existingKeys, allowedKeys)
|
|
invalidKeys.forEach((key) => {
|
|
const error = {
|
|
property: key,
|
|
message: `not allowed. Allowed properties are: ${allowedKeys.join(', ')}`,
|
|
}
|
|
if (filepath) error.filepath = filepath
|
|
errors.push(error)
|
|
})
|
|
}
|
|
|
|
// validate key order
|
|
if (opts.validateKeyOrder && existingKeys.join('') !== expectedKeys.join('')) {
|
|
const error = {
|
|
property: 'keys',
|
|
message: `keys must be in order. Current: ${existingKeys.join(
|
|
','
|
|
)}; Expected: ${expectedKeys.join(',')}`,
|
|
}
|
|
if (filepath) error.filepath = filepath
|
|
errors.push(error)
|
|
}
|
|
|
|
// TODO temporary kludge! See notes in the module.
|
|
if (errors.length) {
|
|
errors = cleanUpDeprecatedGhaeFlagErrors(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
|