盖茨比前端验证

Gatsby Frontmatter Validation

我有几个关于架构自定义的问题。

data/categories.json

[
    {
        "name": "Foo Bar",
        "slug": "foo-bar"
    },
    { 
        "name": "Fuz Baz",
        "slug": "fuz-baz"
    }
]

盖茨比-config.js

  ...
  
  mapping: {
    "MarkdownRemark.frontmatter.author": `AuthorsJson.alias`,
    "MarkdownRemark.frontmatter.category": `CategoriesJson.name`
  }

盖茨比-node.js

exports.createSchemaCustomization = ({ actions, schema }) => {
    const { createTypes } = actions;
    const typeDefs = [
        `type AuthorsJson implements Node @dontInfer {
            alias: String,
            name: String
            slug: String,
            bio: String,
            profile: String
            posts: [MarkdownRemark] @link(by: "frontmatter.author.alias", from: "alias")
        }`,
        `type CategoriesJson implements Node @dontInfer {
            name: String,
            slug: String,
            posts: [MarkdownRemark] @link(by: "frontmatter.category.name", from: "name")
        }`,
    ];

    createTypes(typeDefs);
}

最重要的问题是,我如何完成 frontmatter 验证?

  1. 根据上面的问题,我如何强制每个post提供一个类别并且该类别必须存在于categories.json中(例如他们可以'自己编类)?
  2. 如果front matter是一个数组,如何保证数组中的元素不超过3个?

谢谢!

选项 1:

这是我在 gatsby-node.js 中的内容:

var categories = [];
var aliases = [];

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions

  if(node.internal.type === `CategoriesJson`) {
      categories.push(node.name);
  }

  if(node.internal.type === `AuthorsJson`) {
      aliases.push(node.alias);
  }

  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })

    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })

    if (node.frontmatter.author === null || node.frontmatter.author === undefined) {
        throw "Page is missing alias: " + node.fileAbsolutePath;
    }

    if (aliases.indexOf(node.frontmatter.author) == -1) {
        throw "Page has invalid alias: " + node.fileAbsolutePath;
    }

    if (node.frontmatter.category === null || node.frontmatter.category === undefined) {
        throw "Page is missing category: " + node.fileAbsolutePath;
    }

    if (categories.indexOf(node.frontmatter.category) == -1) {
        throw "Page has invalid category ('" + node.frontmatter.category +"'): " + node.fileAbsolutePath;
    }
    
    if (node.frontmatter.tags.length > 3) {
        throw "Page has more than 3 tags: " + node.fileAbsolutePath;
    }
  }
}

有没有更好的方法?

您可以通过以下方式简化所有条件:

let categories = [];
let aliases = [];

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions

  if(node.internal.type === `CategoriesJson`) {
      categories.push(node.name);
  }

  if(node.internal.type === `AuthorsJson`) {
      aliases.push(node.alias);
  }

  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })

    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })

    if (!node.frontmatter.author || !aliases.includes(node.frontmatter.author)) {
        throw "Page is missing alias: " + node.fileAbsolutePath;
    }


    if (!node.frontmatter.category || !categories.includes(node.frontmatter.category)) {
        throw "Page is missing category: " + node.fileAbsolutePath;
    }

   
    if (node.frontmatter.tags.length > 3) {
        throw "Page has more than 3 tags: " + node.fileAbsolutePath;
    }
  }
}

我还添加了 let 而不是 var,后者现在已被弃用。检查 https://www.javascripttutorial.net/es6/difference-between-var-and-let/ and replaced the indexOf == -1 for the more semantic includes.

处的差异

其余的,我觉得这个方法很可靠,这是个好方法。

If front matter is an array, how do I ensure that no more than 3 elements exist in the array?

默认情况下(并且应该如此)frontmatter 将始终是一个对象。