| 41 | } |
| 42 | |
| 43 | static async read(opts) { |
| 44 | assert(opts.languageCode, 'languageCode is required') |
| 45 | assert(opts.relativePath, 'relativePath is required') |
| 46 | assert(opts.basePath, 'basePath is required') |
| 47 | |
| 48 | const relativePath = slash(opts.relativePath) |
| 49 | const fullPath = slash(path.join(opts.basePath, relativePath)) |
| 50 | |
| 51 | // Per https://nodejs.org/api/fs.html#fs_fs_exists_path_callback |
| 52 | // its better to read and handle errors than to check access/stats first |
| 53 | try { |
| 54 | const { data, content, errors: frontmatterErrors } = await readFileContents(fullPath) |
| 55 | |
| 56 | return { |
| 57 | ...opts, |
| 58 | relativePath, |
| 59 | fullPath, |
| 60 | ...data, |
| 61 | markdown: content, |
| 62 | frontmatterErrors, |
| 63 | } |
| 64 | } catch (err) { |
| 65 | if (err.code === 'ENOENT') return false |
| 66 | console.error(err) |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | constructor(opts) { |
| 71 | if (opts.frontmatterErrors && opts.frontmatterErrors.length) { |