Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify document type resolution #123

Open
schickling opened this issue Feb 10, 2022 · 2 comments
Open

Simplify document type resolution #123

schickling opened this issue Feb 10, 2022 · 2 comments

Comments

@schickling
Copy link
Collaborator

Context

In the contentlayer/source-files plugin there are currently two mechanisms to tell Contentlayer how map a given document (e.g. a .md file) to one of many document definitions (e.g. a BlogPost, Page, ...). The two mechanisms are:

  1. Explicitly via the filePathPattern option provided for defineDocumentType
  2. Implicitly by looking up a "type" field in a given document (configurable via fieldOptions.typeFieldName)

Problem

I'm seeing two problems with the current design:

A: Technical problems/limitations

When using mechanism (1) there can be situations where the provided filePathPattern can overlap between document definitions and there currently is no way to explicitly configure the "precedence" document matching behaviour of Contentlayer.

B: Hard to understand / learn

Additionally to the technical problems (A) having two different ways to do the same thing (especially when they overlap) makes things much harder to understand - especially for new Contentlayer users who e.g. might ask themselves "which approach should I use?" or "which approach is better?".

I think that providing less ways to do the same thing is the right approach in most cases as it reduces cognitive overload.

Additionally there's also the complexity resulting of the possibility of combining both mechanisms (1) + (2).

Solution

As an alternative to the current mechanisms (1) + (2) I'm proposing a single unified approach to let users specify how to map document files to document type definitions by simply implementing a resolveDocumentType function as a property in makeSource like the following:

As replacement for mechanism (1)

Assuming a content file structure like:

.
├── about.md
├── index.md
└── posts
    ├── post-1.md
    ├── post-2.md
    └── post-3.md
const Post = defineDocumentType(() => ({
  name: 'Post',
  fields: {
    // ...
  }
}))

const Page = defineDocumentType(() => ({
  name: 'Page',
  fields: {
    // ...
  }
}))

export default makeSource({
  contentDirPath: 'posts',
  documentTypes: [Post, Page],
  resolveDocumentType: (frontmatter, raw) => raw.sourceFilePath.startsWith('posts/') ? 'Post' : 'Page'
})

As replacement for mechanism (2)

Assuming each document as a frontmatter field called type

const Post = defineDocumentType(() => ({
  name: 'Post',
  fields: {
    // ...
  }
}))

const Page = defineDocumentType(() => ({
  name: 'Page',
  fields: {
    // ...
  }
}))

export default makeSource({
  contentDirPath: 'posts',
  documentTypes: [Post, Page],
  resolveDocumentType: (frontmatter, raw) => frontmatter.type
})

Feedback wanted

We'd love to hear your feedback on the proposed API change. 🙏

@timlrx
Copy link

timlrx commented Feb 16, 2022

Copying from the discord chat:

Here's an idea that combines the above with #84

const ctfl = makeSource({ type: 'contentful', accessToken: /* ... */ })
const local = makeSource({ type: 'local', path: /* ... */ })

const Page = defineDocumentType(() => ({
  name: 'Page',
  source: ctfl,
  ...
}))
const Post = defineDocumentType(() => ({
  name: 'Post',
  source: local,
  contentType: 'mdx',
  resolveDocument: (frontmatter, path) => frontmatter.type,
  mdx: {remarkPlugins:[], rehypePlugins: []}
  ...
}))

export {Page, Post}

The idea is to have a clearer separation of the source from the transformation pipeline (defineDocuementType). resolveDocument would in this case be only specific only to md/mdx files.

The part that I still don't really like is that resolveDocument in defineDocumentType still takes a path. I think it's more natural for filePathPattern to exist in the makeSource section and maybe defineDocumentType can take a resolveType property?

@stale
Copy link

stale bot commented May 7, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants