OurBigBook logoOurBigBook Docs OurBigBook logoOurBigBook.comSite Source code
web/next.config.js
//const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const { PHASE_DEVELOPMENT_SERVER } = require('next/constants')
const { NextResponse } = require('next/server')
const { match, compile } = require('next/dist/compiled/path-to-regexp')

// Public URL patterns and their internal Next page destinations. Shared with
// middleware for redirects from the legacy URLs.
const legacyRoutePatterns = [
  ['/go/settings/:uid', '/:uid/-/settings'],
  ...['children', 'incoming', 'tagged'].map(action => [
    `/go/user/:uid/${action}/:parentTopicId+`, `/:uid/:parentTopicId+/-/${action}`,
  ]),
  ...['articles', 'children', 'incoming', 'tagged', 'comments', 'files', 'discussions',
    'followed', 'follows', 'liked', 'liked-discussions', 'likes', 'likes-discussions',
    'follows-articles', 'follows-discussions'].map(action => [
    `/go/user/:uid/${action}`, `/:uid/-/${action}`,
  ]),
  ...['comments', 'discussions'].map(action => [
    `/go/${action}/:uid`, `/:uid/-/home/${action}`,
  ]),
  ...['comments', 'discussions', 'edit', 'delete', 'source', 'new', 'new-discussion'].map(action => [
    `/go/${action}/:slug+`, `/:slug+/-/${action}`,
  ]),
  ['/go/discussion/:number/:slug+', '/:slug+/-/discussion/:number'],
  ['/go/edit-discussion/:number/:slug+', '/:slug+/-/discussion/:number/edit'],
  ['/go/delete-discussion/:number/:slug+', '/:slug+/-/discussion/:number/delete'],
  // Article actions above must match before file previews, whose path is a catch-all.
  ['/:uid/_file/:path+', '/:uid/-/file/:path+'],
  ['/:uid/_dir/:path*', '/:uid/-/dir/:path*'],
]

module.exports = phase => ({
  // Builds clean their output directory. Keep them away from the running dev
  // server's chunks and caches, including when NODE_ENV is set by our wrappers.
  distDir: phase === PHASE_DEVELOPMENT_SERVER ? '.next-dev' : '.next',
  async rewrites() {
    return { beforeFiles: [
      ...legacyRoutePatterns.map(([destination, source]) => ({ source, destination })),
      { source: '/-/:path*', destination: '/go/:path*' },
    ] }
  },
  eslint: {
    // Next.js 11 enables it by default, which is great. Being naughty until I get
    // the patience to fix i it.
    ignoreDuringBuilds: true,
  },
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.module.rules.push(
      {
        // To allow embedding the default defines into the Web Editor.
        test: /\.tex$/,
        type: 'asset/source',
      }
    );
    return config
  },
})

const redirects = [
  ...['comments', 'discussions'].map(action => [
    `/:uid/-/article/${action}`, `/:uid/-/home/${action}`,
  ]),
  ...legacyRoutePatterns,
  ['/:uid/_raw/:path+', '/:uid/-/raw/:path+'],
  ['/go/:path*', '/-/:path*'],
].map(([source, destination]) => ({
  match: match(source),
  destination: compile(destination),
}))

// Middleware supplies x-nextjs-redirect for client navigation data requests;
// next.config redirects only supply Location, which is insufficient there.
function middleware(request) {
  for (const redirect of redirects) {
    const matched = redirect.match(request.nextUrl.pathname)
    if (matched) {
      const url = request.nextUrl.clone()
      url.pathname = redirect.destination(matched.params)
      // The Pages Router adds dynamic route parameters to data request queries.
      // They already belong to the path and must not leak into the redirect URL.
      if (request.headers.has('x-nextjs-data')) {
        // Redirect-only aliases can be resolved through the generic [...slug] page.
        const routeParams = { slug: request.nextUrl.pathname.slice(1).split('/'), ...matched.params }
        for (const [key, value] of Object.entries(routeParams)) {
          const parts = (Array.isArray(value) ? value : [value]).map(part => decodeURIComponent(String(part)))
          const query = url.searchParams.getAll(key)
          if (query.length === parts.length && query.every((part, i) => part === parts[i])) {
            url.searchParams.delete(key)
          }
        }
      }
      return NextResponse.redirect(url, 308)
    }
  }
  return NextResponse.next()
}

module.exports.middleware = middleware