/** * Copyright (c) Facebook, Inc. and its affiliates. * * @emails react-core */ 'use strict'; const {resolve} = require('path'); module.exports = async ({graphql, actions}) => { const {createPage, createRedirect} = actions; // Used to detect and prevent duplicate redirects const redirectToSlugMap = {}; const blogTemplate = resolve(__dirname, '../src/templates/blog.js'); const communityTemplate = resolve(__dirname, '../src/templates/community.js'); const docsTemplate = resolve(__dirname, '../src/templates/docs.js'); const tutorialTemplate = resolve(__dirname, '../src/templates/tutorial.js'); // Redirect /index.html to root. createRedirect({ fromPath: '/index.html', redirectInBrowser: true, toPath: '/', }); const allMarkdown = await graphql( ` { allMarkdownRemark(limit: 1000) { edges { node { fields { redirect slug } } } } } `, ); if (allMarkdown.errors) { console.error(allMarkdown.errors); throw Error(allMarkdown.errors); } allMarkdown.data.allMarkdownRemark.edges.forEach(edge => { const slug = edge.node.fields.slug; if (slug === 'docs/error-decoder.html') { // No-op so far as markdown templates go. // Error codes are managed by a page in src/pages // (which gets created by Gatsby during a separate phase). } else if ( slug.includes('blog/') || slug.includes('community/') || slug.includes('contributing/') || slug.includes('docs/') || slug.includes('tutorial/') || slug.includes('warnings/') ) { let template; if (slug.includes('blog/')) { template = blogTemplate; } else if (slug.includes('community/')) { template = communityTemplate; } else if ( slug.includes('contributing/') || slug.includes('docs/') || slug.includes('warnings/') ) { template = docsTemplate; } else if (slug.includes('tutorial/')) { template = tutorialTemplate; } const createArticlePage = path => createPage({ path: path, component: template, context: { slug, }, }); // Register primary URL. createArticlePage(slug); // Register redirects as well if the markdown specifies them. if (edge.node.fields.redirect) { let redirect = JSON.parse(edge.node.fields.redirect); if (!Array.isArray(redirect)) { redirect = [redirect]; } redirect.forEach(fromPath => { if (redirectToSlugMap[fromPath] != null) { console.error( `Duplicate redirect detected from "${fromPath}" to:\n` + `* ${redirectToSlugMap[fromPath]}\n` + `* ${slug}\n`, ); process.exit(1); } // A leading "/" is required for redirects to work, // But multiple leading "/" will break redirects. // For more context see github.com/reactjs/reactjs.org/pull/194 const toPath = slug.startsWith('/') ? slug : `/${slug}`; redirectToSlugMap[fromPath] = slug; createRedirect({ fromPath: `/${fromPath}`, redirectInBrowser: true, toPath, }); }); } } }); const newestBlogEntry = await graphql( ` { allMarkdownRemark( limit: 1 filter: {fileAbsolutePath: {regex: "/blog/"}} sort: {fields: [fields___date], order: DESC} ) { edges { node { fields { slug } } } } } `, ); const newestBlogNode = newestBlogEntry.data.allMarkdownRemark.edges[0].node; // Blog landing page should always show the most recent blog entry. ['/blog/', '/blog'].map(slug => { createRedirect({ fromPath: slug, redirectInBrowser: true, toPath: newestBlogNode.fields.slug, }); }); };