From b50d21cbdea34c2c77ed3698434e5af5fb66bded Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Mon, 8 Feb 2021 20:38:24 -0500 Subject: [PATCH] feat: add support for page URL overrides --- lib/config.ts | 51 ++++++++++++++++++++++++++++++++++++ lib/get-all-pages.ts | 3 ++- lib/get-canonical-page-id.ts | 29 ++++++++++++++++++++ lib/resolve-notion-page.ts | 11 +++++++- lib/types.ts | 12 +++++++++ site.config.js | 16 ++++++++++- 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 lib/get-canonical-page-id.ts diff --git a/lib/config.ts b/lib/config.ts index ce35a3d..68e6a25 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -7,6 +7,7 @@ import { parsePageId } from 'notion-utils' import { getSiteConfig, getEnv } from './get-config-value' +import { PageUrlOverridesMap, PageUrlOverridesInverseMap } from './types' export const rootNotionPageId: string = parsePageId( getSiteConfig('rootNotionPageId'), @@ -23,6 +24,15 @@ export const rootNotionSpaceId: string | null = parsePageId( { uuid: true } ) +export const pageUrlOverrides = cleanPageUrlOverrides( + getSiteConfig('pageUrlOverrides', {}) || {} +) + +export const inversePageUrlOverrides = invertPageUrlOverrides(pageUrlOverrides) + +console.log('pageUrlOverrides', pageUrlOverrides) +console.log('inversePageUrlOverrides', inversePageUrlOverrides) + // general site config export const name: string = getSiteConfig('name') export const author: string = getSiteConfig('author') @@ -146,3 +156,44 @@ function getGoogleApplicationCredentials() { throw err } } + +function cleanPageUrlOverrides( + pageUrlOverrides: PageUrlOverridesMap +): PageUrlOverridesMap { + return Object.keys(pageUrlOverrides).reduce((acc, pageId) => { + const uuid = parsePageId(pageId, { uuid: false }) + const uri = pageUrlOverrides[pageId] + + if (!uuid) { + throw new Error(`Invalid pageUrlOverrides page id "${pageId}"`) + } + + if (!uri) { + throw new Error(`Missing pageUrlOverrides value for page "${pageId}"`) + } + + if (!uri.startsWith('/')) { + throw new Error( + `Invalid pageUrlOverrides value for page "${pageId}": value "${uri}" should be a relative URI that starts with "/"` + ) + } + + const path = uri.slice(1) + + return { + ...acc, + [uuid]: path + } + }, {}) +} + +function invertPageUrlOverrides( + pageUrlOverrides: PageUrlOverridesMap +): PageUrlOverridesInverseMap { + return Object.keys(pageUrlOverrides).reduce((acc, pageId) => { + return { + ...acc, + [pageUrlOverrides[pageId]]: pageId + } + }, {}) +} diff --git a/lib/get-all-pages.ts b/lib/get-all-pages.ts index 2874104..eaa5190 100644 --- a/lib/get-all-pages.ts +++ b/lib/get-all-pages.ts @@ -1,9 +1,10 @@ import pMemoize from 'p-memoize' -import { getAllPagesInSpace, getCanonicalPageId } from 'notion-utils' +import { getAllPagesInSpace } from 'notion-utils' import * as types from './types' import { includeNotionIdInUrls } from './config' import { getPage } from './notion' +import { getCanonicalPageId } from './get-canonical-page-id' const uuid = !!includeNotionIdInUrls diff --git a/lib/get-canonical-page-id.ts b/lib/get-canonical-page-id.ts new file mode 100644 index 0000000..46bd64b --- /dev/null +++ b/lib/get-canonical-page-id.ts @@ -0,0 +1,29 @@ +import { ExtendedRecordMap } from 'notion-types' +import { + parsePageId, + getCanonicalPageId as getCanonicalPageIdImpl +} from 'notion-utils' + +import { pageUrlOverrides } from './config' + +export function getCanonicalPageId( + pageId: string, + recordMap: ExtendedRecordMap, + { uuid = true }: { uuid?: boolean } = {} +): string | null { + const cleanPageId = parsePageId(pageId, { uuid: false }) + if (!cleanPageId) { + return null + } + + console.log('getCanonicalPageId', pageId) + + const override = pageUrlOverrides[cleanPageId] + if (override) { + return override + } else { + return getCanonicalPageIdImpl(pageId, recordMap, { + uuid + }) + } +} diff --git a/lib/resolve-notion-page.ts b/lib/resolve-notion-page.ts index 52bc92b..ad9a725 100644 --- a/lib/resolve-notion-page.ts +++ b/lib/resolve-notion-page.ts @@ -1,6 +1,7 @@ +import { parsePageId } from 'notion-utils' import * as acl from './acl' import * as types from './types' -import { parsePageId } from 'notion-utils' +import { inversePageUrlOverrides } from './config' import { getPage } from './notion' import { getSiteMaps } from './get-site-maps' import { getSiteForDomain } from './get-site-for-domain' @@ -13,6 +14,14 @@ export async function resolveNotionPage(domain: string, rawPageId?: string) { if (rawPageId && rawPageId !== 'index') { pageId = parsePageId(rawPageId) + if (!pageId) { + const override = inversePageUrlOverrides[rawPageId] + + if (override) { + pageId = parsePageId(override) + } + } + if (pageId) { const resources = await Promise.all([ getSiteForDomain(domain), diff --git a/lib/types.ts b/lib/types.ts index 63c33c9..8e7cbf5 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -54,6 +54,18 @@ export interface CanonicalPageMap { [canonicalPageId: string]: string } +export interface PageUrlOverridesMap { + // maps from a notion page id to the URL path the page should be resolved to + // (this overrides the built-in URL path generation for these pages) + [pageId: string]: string +} + +export interface PageUrlOverridesInverseMap { + // maps from a URL path to the notion page id the page should be resolved to + // (this overrides the built-in URL path generation for these pages) + [pageId: string]: string +} + export interface PreviewImage { url: string originalWidth: number diff --git a/site.config.js b/site.config.js index dfaa8ec..85e8761 100644 --- a/site.config.js +++ b/site.config.js @@ -3,6 +3,7 @@ module.exports = { rootNotionPageId: '78fc5a4b88d74b0e824e29407e9f1ec1', // if you want to restrict pages to a single notion workspace (optional) + // (this should be a Notion ID; see the docs for how to extract this) rootNotionSpaceId: null, // basic site info (required) @@ -36,5 +37,18 @@ module.exports = { // whether or not to enable support for LQIP preview images (optional) // NOTE: this requires you to set up Google Firebase and add the environment // variables specified in .env.example - isPreviewImageSupportEnabled: false + isPreviewImageSupportEnabled: false, + + // map of notion page IDs to URL paths (optional) + // any pages defined here will override their default URL paths + // example: + // + // pageUrlOverrides: { + // '067dd719a912471ea9a3ac10710e7fdf': '/foo', + // '0be6efce9daf42688f65c76b89f8eb27': '/bar' + // } + pageUrlOverrides: { + '067dd719a912471ea9a3ac10710e7fdf': '/foo', + '0be6efce9daf42688f65c76b89f8eb27': '/bar' + } }