commit
cbea3dce0a
|
@ -18,7 +18,7 @@ export const RenderArticleBlock = ({
|
||||||
}: {
|
}: {
|
||||||
block: LPE.Article.ContentBlock
|
block: LPE.Article.ContentBlock
|
||||||
activeId: string | null
|
activeId: string | null
|
||||||
headingElementsRef: HeadingElementsRef
|
headingElementsRef?: HeadingElementsRef
|
||||||
hide?: boolean
|
hide?: boolean
|
||||||
}) => {
|
}) => {
|
||||||
switch (block.type) {
|
switch (block.type) {
|
||||||
|
@ -70,7 +70,9 @@ export const RenderArticleBlock = ({
|
||||||
variant="body1"
|
variant="body1"
|
||||||
component={block.tagName as any}
|
component={block.tagName as any}
|
||||||
genericFontFamily="sans-serif"
|
genericFontFamily="sans-serif"
|
||||||
className={extractClassFromFirstTag(block.html) || ''}
|
className={`${extractClassFromFirstTag(
|
||||||
|
block.html,
|
||||||
|
)} ${block.classNames.join(' ')}`}
|
||||||
id={extractIdFromFirstTag(block.html) || `p-${block.order}`}
|
id={extractIdFromFirstTag(block.html) || `p-${block.order}`}
|
||||||
dangerouslySetInnerHTML={{ __html: extractInnerHtml(block.html) }}
|
dangerouslySetInnerHTML={{ __html: extractInnerHtml(block.html) }}
|
||||||
/>
|
/>
|
||||||
|
@ -82,7 +84,9 @@ export const RenderArticleBlock = ({
|
||||||
variant="body1"
|
variant="body1"
|
||||||
component={block.tagName as any}
|
component={block.tagName as any}
|
||||||
genericFontFamily="sans-serif"
|
genericFontFamily="sans-serif"
|
||||||
className={extractClassFromFirstTag(block.html) || ''}
|
className={`${extractClassFromFirstTag(
|
||||||
|
block.html,
|
||||||
|
)} ${block.classNames.join(' ')}`}
|
||||||
id={extractIdFromFirstTag(block.html) || `p-${block.order}`}
|
id={extractIdFromFirstTag(block.html) || `p-${block.order}`}
|
||||||
dangerouslySetInnerHTML={{ __html: extractInnerHtml(block.html) }}
|
dangerouslySetInnerHTML={{ __html: extractInnerHtml(block.html) }}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { LPE } from '../../types/lpe.types'
|
||||||
|
|
||||||
type Props = PropsWithChildren<{
|
type Props = PropsWithChildren<{
|
||||||
block: LPE.Article.TextBlock
|
block: LPE.Article.TextBlock
|
||||||
headingElementsRef: HeadingElementsRef
|
headingElementsRef?: HeadingElementsRef
|
||||||
typographyProps?: TypographyProps
|
typographyProps?: TypographyProps
|
||||||
}>
|
}>
|
||||||
export const ArticleHeading = ({
|
export const ArticleHeading = ({
|
||||||
|
@ -24,7 +24,9 @@ export const ArticleHeading = ({
|
||||||
extractIdFromFirstTag(block.html) || `${block.tagName}-${block.order}`
|
extractIdFromFirstTag(block.html) || `${block.tagName}-${block.order}`
|
||||||
const refProp = {
|
const refProp = {
|
||||||
ref: (ref: any) => {
|
ref: (ref: any) => {
|
||||||
|
if (headingElementsRef) {
|
||||||
headingElementsRef.current[id] = ref
|
headingElementsRef.current[id] = ref
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ const ArticleHeader = ({
|
||||||
<ArticleSubtitle
|
<ArticleSubtitle
|
||||||
variant="body1"
|
variant="body1"
|
||||||
genericFontFamily="sans-serif"
|
genericFontFamily="sans-serif"
|
||||||
component="div"
|
component="p"
|
||||||
>
|
>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</ArticleSubtitle>
|
</ArticleSubtitle>
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { Typography } from '@acid-info/lsd-react'
|
||||||
|
import styled from '@emotion/styled'
|
||||||
|
import React from 'react'
|
||||||
|
import { LPE } from '../../types/lpe.types'
|
||||||
|
import { RenderArticleBlock } from '@/components/Article/Article.Block'
|
||||||
|
|
||||||
|
export type StaticPageProps = React.DetailedHTMLProps<
|
||||||
|
React.HTMLAttributes<HTMLDivElement>,
|
||||||
|
HTMLDivElement
|
||||||
|
> & {
|
||||||
|
data: {
|
||||||
|
page: LPE.StaticPage.Document
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const StaticPage: React.FC<StaticPageProps> = ({
|
||||||
|
data,
|
||||||
|
data: { page },
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const titleBlock = data.page.content.find((block) => {
|
||||||
|
return (
|
||||||
|
block.type === LPE.Post.ContentBlockTypes.Text &&
|
||||||
|
block.classNames &&
|
||||||
|
block.classNames.includes('title')
|
||||||
|
)
|
||||||
|
}) as LPE.Post.TextBlock | undefined
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Root {...props}>
|
||||||
|
<article>
|
||||||
|
{titleBlock && (
|
||||||
|
<Typography variant={'h1'} genericFontFamily={'serif'}>
|
||||||
|
{titleBlock.text}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{data.page.content.map((block, idx) => (
|
||||||
|
<RenderArticleBlock block={block} activeId={null} key={idx} />
|
||||||
|
))}
|
||||||
|
</article>
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Root = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
#p-2 {
|
||||||
|
font-size: var(--lsd-body1-fontSize) !important;
|
||||||
|
line-height: var(--lsd-body1-lineHeight) !important;
|
||||||
|
}
|
||||||
|
article {
|
||||||
|
width: 700px;
|
||||||
|
> * {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './StaticPage'
|
|
@ -0,0 +1,87 @@
|
||||||
|
import { CustomNextPage, GetStaticPaths, GetStaticProps } from 'next'
|
||||||
|
import Error from 'next/error'
|
||||||
|
import SEO from '../components/SEO/SEO'
|
||||||
|
import { StaticPage, StaticPageProps } from '../containers/StaticPage'
|
||||||
|
import unbodyApi from '../services/unbody/unbody.service'
|
||||||
|
import NotFoundPage from './404'
|
||||||
|
|
||||||
|
type PageProps = Partial<Pick<StaticPageProps, 'data'>> & {
|
||||||
|
error?: string
|
||||||
|
notFound?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const Page: CustomNextPage<PageProps> = ({
|
||||||
|
data,
|
||||||
|
error,
|
||||||
|
notFound,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
if (!data) {
|
||||||
|
if (notFound) {
|
||||||
|
return <Error statusCode={400} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Error statusCode={500} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SEO
|
||||||
|
description={
|
||||||
|
data.page.subtitle ||
|
||||||
|
'Logos online publishing and blogging platform for writers and readers.'
|
||||||
|
}
|
||||||
|
title={`${data.page.title} - Logos Press Engine`}
|
||||||
|
/>
|
||||||
|
<StaticPage data={data} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticPaths: GetStaticPaths = async () => {
|
||||||
|
const { data } = await unbodyApi.getStaticPages()
|
||||||
|
return {
|
||||||
|
paths: data.map((page) => ({
|
||||||
|
params: {
|
||||||
|
slug: page.slug,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
fallback: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps<PageProps> = async (ctx) => {
|
||||||
|
const { data, errors } = await unbodyApi.getStaticPage({
|
||||||
|
slug: ctx.params!.slug as string,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
if (errors && typeof errors === 'string' && errors.includes('not found')) {
|
||||||
|
return {
|
||||||
|
notFound: true,
|
||||||
|
props: {
|
||||||
|
notFound: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(errors)
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
error: 'Something went wrong!',
|
||||||
|
},
|
||||||
|
notFound: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
data: {
|
||||||
|
page: data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
notFound: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Page
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { LPE } from '../../../types/lpe.types'
|
||||||
|
import { UnbodyResGoogleDocData } from '../unbody.types'
|
||||||
|
import { UnbodyDataTypeConfig } from './types'
|
||||||
|
|
||||||
|
export const StaticPageDataType: UnbodyDataTypeConfig<
|
||||||
|
UnbodyResGoogleDocData,
|
||||||
|
LPE.StaticPage.Document
|
||||||
|
> = {
|
||||||
|
key: 'StaticPageDocument',
|
||||||
|
objectType: 'GoogleDoc',
|
||||||
|
classes: ['static-page', 'document'],
|
||||||
|
|
||||||
|
isMatch: (helpers, data) => data.pathString.includes('/Static pages/'),
|
||||||
|
|
||||||
|
transform: async (helpers, data) => {
|
||||||
|
const textBlock = helpers.dataTypes.get({
|
||||||
|
objectType: 'TextBlock',
|
||||||
|
})
|
||||||
|
const imageBlock = helpers.dataTypes.get({
|
||||||
|
objectType: 'ImageBlock',
|
||||||
|
})
|
||||||
|
|
||||||
|
const blocks =
|
||||||
|
await helpers.dataTypes.transformMany<LPE.Article.ContentBlock>(
|
||||||
|
[...textBlock, ...imageBlock],
|
||||||
|
[...(data.blocks || [])].sort((a, b) => a.order - b.order),
|
||||||
|
data,
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: data._additional.id,
|
||||||
|
slug: data.slug,
|
||||||
|
title: data.title,
|
||||||
|
subtitle: data.subtitle || '',
|
||||||
|
summary: data.summary || '',
|
||||||
|
createdAt: data.createdAt || null,
|
||||||
|
modifiedAt: data.modifiedAt || null,
|
||||||
|
content: blocks,
|
||||||
|
type: 'static_page',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import { ArticleTextBlockDataType } from './ArticleTextBlock.dataType'
|
||||||
import { ImageBlockDataType } from './ImageBlock.dataType'
|
import { ImageBlockDataType } from './ImageBlock.dataType'
|
||||||
import { PodcastEpisodeDataType } from './PodcastEpisodeDocument.dataType'
|
import { PodcastEpisodeDataType } from './PodcastEpisodeDocument.dataType'
|
||||||
import { PodcastShowDataType } from './PodcastShowDocument.dataType'
|
import { PodcastShowDataType } from './PodcastShowDocument.dataType'
|
||||||
|
import { StaticPageDataType } from './StaticPageDocument.dataType'
|
||||||
import { TextBlockDataType } from './TextBlock.dataType'
|
import { TextBlockDataType } from './TextBlock.dataType'
|
||||||
import { UnbodyDataTypes } from './UnbodyDataTypes'
|
import { UnbodyDataTypes } from './UnbodyDataTypes'
|
||||||
|
|
||||||
|
@ -17,4 +18,5 @@ export const unbodyDataTypes = new UnbodyDataTypes([
|
||||||
ArticleSearchResultItemDataType,
|
ArticleSearchResultItemDataType,
|
||||||
PodcastShowDataType,
|
PodcastShowDataType,
|
||||||
PodcastEpisodeDataType,
|
PodcastEpisodeDataType,
|
||||||
|
StaticPageDataType,
|
||||||
])
|
])
|
||||||
|
|
|
@ -49,6 +49,7 @@ export const UnbodyDataTypeKeys = {
|
||||||
ArticleSearchResultItem: 'ArticleSearchResultItem',
|
ArticleSearchResultItem: 'ArticleSearchResultItem',
|
||||||
PodcastShowDocument: 'PodcastShowDocument',
|
PodcastShowDocument: 'PodcastShowDocument',
|
||||||
PodcastEpisodeDocument: 'PodcastEpisodeDocument',
|
PodcastEpisodeDocument: 'PodcastEpisodeDocument',
|
||||||
|
StaticPageDocument: 'StaticPageDocument',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type UnbodyDataTypeKey =
|
export type UnbodyDataTypeKey =
|
||||||
|
@ -61,6 +62,7 @@ export const UnbodyDataTypeClasses = {
|
||||||
Episode: 'episode',
|
Episode: 'episode',
|
||||||
Document: 'document',
|
Document: 'document',
|
||||||
Search: 'search',
|
Search: 'search',
|
||||||
|
StaticPage: 'static-page',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type UnbodyDataTypeClass =
|
export type UnbodyDataTypeClass =
|
||||||
|
|
|
@ -36,6 +36,10 @@ const podcastEpisodeDocument = unbodyDataTypes.get({
|
||||||
classes: ['podcast', 'document', 'episode'],
|
classes: ['podcast', 'document', 'episode'],
|
||||||
objectType: 'GoogleDoc',
|
objectType: 'GoogleDoc',
|
||||||
})!
|
})!
|
||||||
|
const staticPageDocument = unbodyDataTypes.get({
|
||||||
|
classes: ['static-page', 'document'],
|
||||||
|
objectType: 'GoogleDoc',
|
||||||
|
})!
|
||||||
|
|
||||||
const sortPosts = (a: LPE.Post.Document, b: LPE.Post.Document) =>
|
const sortPosts = (a: LPE.Post.Document, b: LPE.Post.Document) =>
|
||||||
(a.type === 'podcast' ? new Date(a.publishedAt) : new Date(a.modifiedAt!)) >
|
(a.type === 'podcast' ? new Date(a.publishedAt) : new Date(a.modifiedAt!)) >
|
||||||
|
@ -52,7 +56,8 @@ export class UnbodyService {
|
||||||
|
|
||||||
initialData: {
|
initialData: {
|
||||||
posts: LPE.Post.Document[]
|
posts: LPE.Post.Document[]
|
||||||
} = { posts: [] }
|
staticPages: LPE.StaticPage.Document[]
|
||||||
|
} = { posts: [], staticPages: [] }
|
||||||
|
|
||||||
constructor(private apiKey: string, private projectId: string) {
|
constructor(private apiKey: string, private projectId: string) {
|
||||||
const cache = new InMemoryCache({
|
const cache = new InMemoryCache({
|
||||||
|
@ -103,6 +108,7 @@ export class UnbodyService {
|
||||||
private _loadInitialData = async () => {
|
private _loadInitialData = async () => {
|
||||||
const articles: LPE.Article.Data[] = await this.fetchAllArticles()
|
const articles: LPE.Article.Data[] = await this.fetchAllArticles()
|
||||||
const episodes: LPE.Podcast.Document[] = await this.fetchAllEpisodes()
|
const episodes: LPE.Podcast.Document[] = await this.fetchAllEpisodes()
|
||||||
|
const staticPages = await this.fetchAllStaticPages()
|
||||||
|
|
||||||
const posts: LPE.Post.Document[] = [...articles, ...episodes].sort(
|
const posts: LPE.Post.Document[] = [...articles, ...episodes].sort(
|
||||||
sortPosts,
|
sortPosts,
|
||||||
|
@ -110,9 +116,10 @@ export class UnbodyService {
|
||||||
|
|
||||||
this.initialData = {
|
this.initialData = {
|
||||||
posts,
|
posts,
|
||||||
|
staticPages,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initialDataPromise.resolve({ posts })
|
this.initialDataPromise.resolve({ posts, staticPages })
|
||||||
}
|
}
|
||||||
|
|
||||||
loadInitialData = async (forced: boolean = false) => {
|
loadInitialData = async (forced: boolean = false) => {
|
||||||
|
@ -123,6 +130,31 @@ export class UnbodyService {
|
||||||
return this.initialDataPromise.promise
|
return this.initialDataPromise.promise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fetchAllStaticPages = async () => {
|
||||||
|
const result: LPE.StaticPage.Document[] = []
|
||||||
|
|
||||||
|
let skip = 0
|
||||||
|
const limit = 50
|
||||||
|
while (true) {
|
||||||
|
const { data } = await this.findStaticPages({
|
||||||
|
skip,
|
||||||
|
limit,
|
||||||
|
parseContent: false,
|
||||||
|
textBlocks: false,
|
||||||
|
includeDrafts: false,
|
||||||
|
toc: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
result.push(...data)
|
||||||
|
|
||||||
|
if (data.length === 0) break
|
||||||
|
|
||||||
|
skip += 50
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
private fetchAllEpisodes = async () => {
|
private fetchAllEpisodes = async () => {
|
||||||
const result: LPE.Podcast.Document[] = []
|
const result: LPE.Podcast.Document[] = []
|
||||||
|
|
||||||
|
@ -227,6 +259,112 @@ export class UnbodyService {
|
||||||
return GoogleDoc?.[0]?.meta?.count || 0
|
return GoogleDoc?.[0]?.meta?.count || 0
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
|
findStaticPages = ({
|
||||||
|
skip = 0,
|
||||||
|
limit = 10,
|
||||||
|
slug,
|
||||||
|
toc = false,
|
||||||
|
filter,
|
||||||
|
nearObject,
|
||||||
|
textBlocks = false,
|
||||||
|
includeDrafts = false,
|
||||||
|
}: {
|
||||||
|
slug?: string
|
||||||
|
skip?: number
|
||||||
|
limit?: number
|
||||||
|
toc?: boolean
|
||||||
|
filter?: GetPostsQueryVariables['filter']
|
||||||
|
nearObject?: string
|
||||||
|
textBlocks?: boolean
|
||||||
|
parseContent?: boolean
|
||||||
|
includeDrafts?: boolean
|
||||||
|
}) =>
|
||||||
|
this.handleRequest<LPE.StaticPage.Document[]>(async () => {
|
||||||
|
const {
|
||||||
|
data: {
|
||||||
|
Get: { GoogleDoc: docs },
|
||||||
|
},
|
||||||
|
} = await this.client.query({
|
||||||
|
query: GetPostsDocument,
|
||||||
|
variables: {
|
||||||
|
toc,
|
||||||
|
textBlocks,
|
||||||
|
mentions: true,
|
||||||
|
imageBlocks: true,
|
||||||
|
...(nearObject
|
||||||
|
? {
|
||||||
|
nearObject: {
|
||||||
|
id: nearObject,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...this.helpers.args.page(skip, limit),
|
||||||
|
filter: {
|
||||||
|
operator: 'And',
|
||||||
|
operands: [
|
||||||
|
this.helpers.args.wherePath([
|
||||||
|
'Static pages',
|
||||||
|
includeDrafts ? 'published|draft' : 'published',
|
||||||
|
]),
|
||||||
|
...(slug
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
path: ['slug'],
|
||||||
|
operator: 'Equal',
|
||||||
|
valueString: slug,
|
||||||
|
} as GetObjectsGoogleDocWhereInpObj,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(nearObject
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
path: ['id'],
|
||||||
|
operator: 'NotEqual',
|
||||||
|
valueString: nearObject,
|
||||||
|
} as GetObjectsGoogleDocWhereInpObj,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(filter ? [filter] : []),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return unbodyDataTypes.transformMany<LPE.StaticPage.Document>(
|
||||||
|
staticPageDocument,
|
||||||
|
docs,
|
||||||
|
undefined,
|
||||||
|
)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
getStaticPages = () =>
|
||||||
|
this.handleRequest<LPE.StaticPage.Document[]>(async () => {
|
||||||
|
const { staticPages } = await this.loadInitialData()
|
||||||
|
|
||||||
|
return staticPages
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
getStaticPage = ({
|
||||||
|
slug,
|
||||||
|
includeDrafts = false,
|
||||||
|
}: {
|
||||||
|
slug: string
|
||||||
|
includeDrafts?: boolean
|
||||||
|
}) =>
|
||||||
|
this.handleRequest<LPE.StaticPage.Document | null>(async () => {
|
||||||
|
const { data } = await this.findStaticPages({
|
||||||
|
limit: 1,
|
||||||
|
slug,
|
||||||
|
includeDrafts,
|
||||||
|
textBlocks: true,
|
||||||
|
parseContent: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data.length === 0) throw 'Static page not found!'
|
||||||
|
|
||||||
|
return data[0]
|
||||||
|
}, null)
|
||||||
|
|
||||||
getArticles = ({
|
getArticles = ({
|
||||||
skip = 0,
|
skip = 0,
|
||||||
limit = 10,
|
limit = 10,
|
||||||
|
|
|
@ -52,7 +52,6 @@ export namespace LPE {
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type ContentBlockType = DictValues<typeof ContentBlockTypes>
|
export type ContentBlockType = DictValues<typeof ContentBlockTypes>
|
||||||
|
|
||||||
export const ContentBlockLabels = {
|
export const ContentBlockLabels = {
|
||||||
Title: 'title',
|
Title: 'title',
|
||||||
Subtitle: 'subtitle',
|
Subtitle: 'subtitle',
|
||||||
|
@ -92,6 +91,32 @@ export namespace LPE {
|
||||||
export type Document = LPE.Article.Data | LPE.Podcast.Document
|
export type Document = LPE.Article.Data | LPE.Podcast.Document
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace StaticPage {
|
||||||
|
export type TextBlock = Post.TextBlock<Metadata>
|
||||||
|
export type ImageBlock = Post.ImageBlock<Metadata>
|
||||||
|
export type ContentBlock = Post.ContentBlock<Metadata>
|
||||||
|
export type Footnote = Post.Footnote
|
||||||
|
export type Footnotes = Post.Footnotes
|
||||||
|
export const ContentBlockLabels = Post.ContentBlockLabels
|
||||||
|
export type ContentBlockLabel = Post.ContentBlockLabel
|
||||||
|
|
||||||
|
export type Metadata = {
|
||||||
|
id: string
|
||||||
|
slug: string
|
||||||
|
title: string
|
||||||
|
summary: string
|
||||||
|
subtitle: string
|
||||||
|
|
||||||
|
createdAt: string | null
|
||||||
|
modifiedAt: string | null
|
||||||
|
type: 'static_page'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Document = Metadata & {
|
||||||
|
content: Array<Article.ContentBlock>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export namespace Article {
|
export namespace Article {
|
||||||
export type Toc = Post.Toc
|
export type Toc = Post.Toc
|
||||||
export type TocItem = Post.TocItem
|
export type TocItem = Post.TocItem
|
||||||
|
|
Loading…
Reference in New Issue