(markdown, opts = { validateKeyNames: false, validateKeyOrder: false })
| 4 | import cleanUpDeprecatedGhaeFlagErrors from './temporary-ghae-deprecated-flag-error-cleanup.js' |
| 5 | |
| 6 | function readFrontmatter(markdown, opts = { validateKeyNames: false, validateKeyOrder: false }) { |
| 7 | const schema = opts.schema || { properties: {} } |
| 8 | const filepath = opts.filepath || null |
| 9 | |
| 10 | let content, data |
| 11 | let errors = [] |
| 12 | |
| 13 | try { |
| 14 | ;({ content, data } = matter(markdown)) |
| 15 | } catch (e) { |
| 16 | const defaultReason = 'invalid frontmatter entry' |
| 17 | |
| 18 | const reason = e.reason |
| 19 | ? // make this common error message a little easier to understand |
| 20 | e.reason.startsWith('can not read a block mapping entry;') |
| 21 | ? defaultReason |
| 22 | : e.reason |
| 23 | : defaultReason |
| 24 | |
| 25 | const error = { |
| 26 | reason, |
| 27 | message: 'YML parsing error!', |
| 28 | } |
| 29 | |
| 30 | if (filepath) error.filepath = filepath |
| 31 | errors.push(error) |
| 32 | return { errors } |
| 33 | } |
| 34 | |
| 35 | const allowedKeys = Object.keys(schema.properties) |
| 36 | const existingKeys = Object.keys(data) |
| 37 | const expectedKeys = intersection(allowedKeys, existingKeys) |
| 38 | |
| 39 | ;({ errors } = revalidator.validate(data, schema)) |
| 40 | |
| 41 | // add filepath property to each error object |
| 42 | if (errors.length && filepath) { |
| 43 | errors = errors.map((error) => Object.assign(error, { filepath })) |
| 44 | } |
| 45 | |
| 46 | // validate key names |
| 47 | if (opts.validateKeyNames) { |
| 48 | const invalidKeys = difference(existingKeys, allowedKeys) |
| 49 | invalidKeys.forEach((key) => { |
| 50 | const error = { |
| 51 | property: key, |
| 52 | message: `not allowed. Allowed properties are: ${allowedKeys.join(', ')}`, |
| 53 | } |
| 54 | if (filepath) error.filepath = filepath |
| 55 | errors.push(error) |
| 56 | }) |
| 57 | } |
| 58 | |
| 59 | // validate key order |
| 60 | if (opts.validateKeyOrder && existingKeys.join('') !== expectedKeys.join('')) { |
| 61 | const error = { |
| 62 | property: 'keys', |
| 63 | message: `keys must be in order. Current: ${existingKeys.join( |
no test coverage detected