chore(dev): Removed blog from the dev site
This commit is contained in:
parent
c3be46c487
commit
8c65b9d132
6 changed files with 26 additions and 440 deletions
|
@ -1,70 +0,0 @@
|
|||
import Head from 'next/head'
|
||||
|
||||
const rss = (lang, type, title) => ({
|
||||
title,
|
||||
type: "application/rss+xml",
|
||||
href: `/feeds/${type}-${lang}.rss.xml`
|
||||
})
|
||||
const atom = (lang, type, title) => ({
|
||||
title,
|
||||
type: "application/rss+atom",
|
||||
href: `/feeds/${type}-${lang}.atom.xml`
|
||||
})
|
||||
const json = (lang, type, title) => ({
|
||||
title,
|
||||
type: "application/json",
|
||||
href: `/feeds/${type}-${lang}.json`
|
||||
})
|
||||
|
||||
|
||||
const feeds = {
|
||||
en: [
|
||||
atom('en', 'blog', "Atom feed of FreeSewing.org blog posts"),
|
||||
json('en', 'blog', "JSON feed of FreeSewing.org blog posts"),
|
||||
rss( 'en', 'blog', "RSS feed of FreeSewing.org blog posts"),
|
||||
atom('en', 'showcase', "Atom feed of FreeSewing.org showcase posts"),
|
||||
json('en', 'showcase', "JSON feed of FreeSewing.org showcase posts"),
|
||||
rss( 'en', 'showcase', "RSS feed of FreeSewing.org showcase posts"),
|
||||
],
|
||||
de: [
|
||||
atom('de', 'blog', "Atom-Feed von FreeSewing.org-Blogbeiträgen"),
|
||||
json('de', 'blog', "JSON-Feed von FreeSewing.org-Blogbeiträgen"),
|
||||
rss( 'de', 'blog', "RSS-Feed von FreeSewing.org-Blogbeiträgen"),
|
||||
atom('de', 'showcase', "Atom-Feed von FreeSewing.org-Galeriebeiträgen"),
|
||||
json('de', 'showcase', "JSON-Feed von FreeSewing.org-Galeriebeiträgen"),
|
||||
rss( 'de', 'showcase', "RSS-Feed von FreeSewing.org-Galeriebeiträgen"),
|
||||
],
|
||||
es: [
|
||||
atom('es', 'blog', "Fuente Atom de las publicaciones del blog FreeSewing.org"),
|
||||
json('es', 'blog', "Fuente JSON de las publicaciones del blog FreeSewing.org"),
|
||||
rss( 'es', 'blog', "Fuente RSS de las publicaciones del blog FreeSewing.org"),
|
||||
atom('es', 'showcase', "Fuente Atom de publicaciones de exhibición de FreeSewing.org"),
|
||||
json('es', 'showcase', "Fuente JSON de publicaciones de exhibición de FreeSewing.org"),
|
||||
rss( 'es', 'showcase', "Fuente RSS de publicaciones de exhibición de FreeSewing.org"),
|
||||
],
|
||||
fr: [
|
||||
atom('fr', 'blog', "Flux Atom des articles du blog FreeSewing.org"),
|
||||
json('fr', 'blog', "Flux JSON des articles du blog FreeSewing.org"),
|
||||
rss( 'fr', 'blog', "Flux RSS des articles du blog FreeSewing.org"),
|
||||
atom('fr', 'showcase', "Flux Atom des articles du galerie FreeSewing.org"),
|
||||
json('fr', 'showcase', "Flux JSON des articles du galerie FreeSewing.org"),
|
||||
rss( 'fr', 'showcase', "Flux RSS des articles du galerie FreeSewing.org"),
|
||||
],
|
||||
nl: [
|
||||
atom('nl', 'blog', "Atom feed van FreeSewing.org blog posts"),
|
||||
json('nl', 'blog', "JSON feed van FreeSewing.org blog posts"),
|
||||
rss( 'nl', 'blog', "RSS feed van FreeSewing.org blog posts"),
|
||||
atom('nl', 'showcase', "Atom feed van FreeSewing.org voorbeelden"),
|
||||
json('nl', 'showcase', "JSON feed van FreeSewing.org voorbeelden"),
|
||||
rss( 'nl', 'showcase', "RSS feed van FreeSewing.org voorbeelden"),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
const Feeds = ({ lang='en' }) => (
|
||||
<Head>
|
||||
{feeds[lang].map(feed => <link key={feed.href} {...feed} />)}
|
||||
</Head>
|
||||
)
|
||||
|
||||
export default Feeds
|
|
@ -5,25 +5,22 @@ import { useHotkeys } from 'react-hotkeys-hook'
|
|||
// Layouts components
|
||||
import LayoutWrapper from 'site/components/wrappers/layout'
|
||||
import Docs from 'site/components/layouts/docs'
|
||||
// Add feeds
|
||||
import Feeds from 'site/components/feeds.js'
|
||||
// Modal
|
||||
import Modal from 'shared/components/modal'
|
||||
|
||||
/* This component should wrap all page content */
|
||||
const PageWrapper= ({
|
||||
title="FIXME: No title set",
|
||||
noSearch=false,
|
||||
app=false,
|
||||
layout=Docs,
|
||||
crumbs=false,
|
||||
children=[]
|
||||
const PageWrapper = ({
|
||||
title = 'FIXME: No title set',
|
||||
noSearch = false,
|
||||
app = false,
|
||||
layout = Docs,
|
||||
crumbs = false,
|
||||
children = [],
|
||||
}) => {
|
||||
|
||||
const swipeHandlers = useSwipeable({
|
||||
onSwipedLeft: evt => (app.primaryMenu) ? app.setPrimaryMenu(false) : null,
|
||||
onSwipedRight: evt => (app.primaryMenu) ? null : app.setPrimaryMenu(true),
|
||||
trackMouse: true
|
||||
onSwipedLeft: () => (app.primaryMenu ? app.setPrimaryMenu(false) : null),
|
||||
onSwipedRight: () => (app.primaryMenu ? null : app.setPrimaryMenu(true)),
|
||||
trackMouse: true,
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
@ -43,7 +40,9 @@ const PageWrapper= ({
|
|||
app: app,
|
||||
title: title,
|
||||
crumbs: crumbs,
|
||||
search, setSearch, toggleSearch: () => setSearch(!search),
|
||||
search,
|
||||
setSearch,
|
||||
toggleSearch: () => setSearch(!search),
|
||||
noSearch: noSearch,
|
||||
}
|
||||
|
||||
|
@ -56,12 +55,8 @@ const PageWrapper= ({
|
|||
data-theme={app.theme}
|
||||
key={app.theme} // This forces the data-theme update
|
||||
>
|
||||
<Feeds lang={app.locale} />
|
||||
<LayoutWrapper {...childProps}>
|
||||
{Layout
|
||||
? <Layout {...childProps}>{children}</Layout>
|
||||
: children
|
||||
}
|
||||
{Layout ? <Layout {...childProps}>{children}</Layout> : children}
|
||||
</LayoutWrapper>
|
||||
{app.popup && <Modal cancel={() => app.setPopup(false)}>{app.popup}</Modal>}
|
||||
</div>
|
||||
|
@ -69,4 +64,3 @@ const PageWrapper= ({
|
|||
}
|
||||
|
||||
export default PageWrapper
|
||||
|
||||
|
|
|
@ -1,168 +0,0 @@
|
|||
import Page from 'site/components/wrappers/page.js'
|
||||
import useApp from 'site/hooks/useApp.js'
|
||||
import TimeAgo from 'react-timeago'
|
||||
import MdxWrapper from 'shared/components/wrappers/mdx'
|
||||
import mdxCompiler from 'shared/mdx/compiler'
|
||||
import Head from 'next/head'
|
||||
import Lightbox from 'shared/components/lightbox.js'
|
||||
import ImageWrapper from 'shared/components/wrappers/img.js'
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { strapiHost } from 'shared/config/freesewing.mjs'
|
||||
import { strapiImage } from 'shared/utils'
|
||||
|
||||
const Author = ({ author }) => (
|
||||
<div id="author" className="flex flex-col lg:flex-row m-auto p-2 items-center">
|
||||
<div className="theme-gradient w-40 h-40 p-2 rounded-full aspect-square hidden lg:block">
|
||||
<div
|
||||
className={`
|
||||
w-lg bg-cover bg-center rounded-full aspect-square
|
||||
hidden lg:block
|
||||
`}
|
||||
style={{backgroundImage: `url(${strapiHost}${author?.image?.sizes?.small?.url})`}}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="theme-gradient p-2 rounded-full aspect-square w-40 h-40 lg:hidden m-auto">
|
||||
<img
|
||||
className={`block w-full h-full mx-auto rounded-full`}
|
||||
src={`${strapiHost}${author?.image?.sizes.small.url}`}
|
||||
alt={author?.displayname}
|
||||
width={author?.image?.sizes.small.w}
|
||||
height={author?.image?.sizes.small.h}
|
||||
/>
|
||||
</div>
|
||||
<div className={`
|
||||
text-center p-2 px-4 rounded-r-lg bg-opacity-50
|
||||
lg:text-left
|
||||
`}
|
||||
>
|
||||
<p className="text-xl">
|
||||
<span className="font-semibold"> {author?.displayname}</span>
|
||||
<span className="text-sm pl-2 opacity-70">Wrote this</span>
|
||||
</p>
|
||||
<div className="prose mdx">
|
||||
<MdxWrapper mdx={author?.mdx} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const PostPage = ({ post, author }) => {
|
||||
const app = useApp()
|
||||
|
||||
return (
|
||||
<Page app={app} title={post.title}>
|
||||
<Head>
|
||||
<meta property="og:title" content={post.title} key="title" />
|
||||
<meta property="og:type" content="article" key='type' />
|
||||
<meta property="og:description" content={post.intro || post.title} key='description' />
|
||||
<meta property="og:article:author" content={author.displayname} key='author' />
|
||||
<meta property="og:url" content={`https://freesewing.dev/blog/${post.slug}`} key='url' />
|
||||
<meta property="og:image" content={`https://canary.backend.freesewing.org/og-img/en/dev/blog/${post.slug}`} key='image' />
|
||||
<meta property="og:image:type" content="image/png" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta property="og:locale" content="en_US" key='locale' />
|
||||
<meta property="og:site_name" content="freesewing.dev" key='site' />
|
||||
</Head>
|
||||
<article className="mb-12">
|
||||
<div className="flex flex-row justify-between text-sm mb-1 mt-2">
|
||||
<span><TimeAgo date={post.date} /> [{post.date}]</span>
|
||||
<span>
|
||||
By <a
|
||||
href="#author"
|
||||
className="text-secondary hover:text-secondary-focus"
|
||||
>
|
||||
{author.displayname || 'FIXME: No displayname'}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<figure>
|
||||
<Lightbox>
|
||||
<ImageWrapper>
|
||||
<img
|
||||
src={`${strapiHost}${post.image.url}`}
|
||||
alt={post.caption}
|
||||
className="shadow m-auto"
|
||||
/>
|
||||
</ImageWrapper>
|
||||
<figcaption
|
||||
className="text-center mb-8 prose m-auto mt-1"
|
||||
dangerouslySetInnerHTML={{__html: post.caption}}
|
||||
/>
|
||||
</Lightbox>
|
||||
</figure>
|
||||
<div className="strapi prose lg:prose-lg mb-12 m-auto">
|
||||
<MdxWrapper mdx={post.mdx} app={app} />
|
||||
</div>
|
||||
<div className="max-w-prose text-lg lg:text-xl">
|
||||
<Author author={author} />
|
||||
</div>
|
||||
</article>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* getStaticProps() is used to fetch data at build-time.
|
||||
*
|
||||
* On this page, it is loading the blog content from strapi.
|
||||
*
|
||||
* This, in combination with getStaticPaths() below means this
|
||||
* page will be used to render/generate all blog content.
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export async function getStaticProps({ params, locale }) {
|
||||
|
||||
const { slug } = params
|
||||
const post = await fetch(
|
||||
`${strapiHost}/blogposts?_locale=${locale}&dev_ne=true&slug_eq=${slug}`
|
||||
)
|
||||
.then(response => response.json())
|
||||
.then(data => data[0])
|
||||
.catch(err => console.log(err))
|
||||
|
||||
return {
|
||||
props: {
|
||||
post: {
|
||||
slug,
|
||||
...(await mdxCompiler(post.body)),
|
||||
title: post.title,
|
||||
date: post.date,
|
||||
caption: post.caption,
|
||||
image: {
|
||||
w: post.image.width,
|
||||
h: post.image.height,
|
||||
url: post.image.url
|
||||
},
|
||||
},
|
||||
author: {
|
||||
displayname: post.author.displayname,
|
||||
slug: post.author.slug,
|
||||
about: post.author.about,
|
||||
image: strapiImage(post.author.picture, ['small']),
|
||||
...(await mdxCompiler(post.author.about)),
|
||||
},
|
||||
...(await serverSideTranslations(locale)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getStaticPaths = async () => {
|
||||
const paths = await fetch(
|
||||
`${strapiHost}/blogposts?_locale=en&dev_ne=true&_limit=-1`
|
||||
)
|
||||
.then(response => response.json())
|
||||
.then(data => data.map(post => `/blog/${post.slug}`))
|
||||
.catch(err => console.log(err))
|
||||
|
||||
return {
|
||||
paths: [ ...paths ],
|
||||
fallback: false,
|
||||
}
|
||||
}
|
||||
|
||||
export default PostPage
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
import Page from 'site/components/wrappers/page.js'
|
||||
import useApp from 'site/hooks/useApp.js'
|
||||
import Link from 'next/link'
|
||||
import TimeAgo from 'react-timeago'
|
||||
import { strapiHost } from 'shared/config/freesewing.mjs'
|
||||
import { strapiImage } from 'shared/utils'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
|
||||
const strapi = "https://posts.freesewing.org"
|
||||
const textShadow = {
|
||||
style: {
|
||||
textShadow: "1px 1px 1px #000000, -1px -1px 1px #000000, 1px -1px 1px #000000, -1px 1px 1px #000000, 2px 2px 1px #000000"
|
||||
}
|
||||
}
|
||||
|
||||
const Preview = ({ app, post }) => (
|
||||
<div className="shadow rounded-lg">
|
||||
<Link href={`/blog/${post.slug}`}>
|
||||
<a title={post.title} className="hover:underline">
|
||||
<div className="bg-base-100 w-full aspect-video shadow flex flex-column items-end rounded-lg" style={{
|
||||
backgroundImage: `url(${strapi}${post.image.sizes.medium.url})`,
|
||||
backgroundSize: 'cover',
|
||||
}}>
|
||||
<div className="grow"></div>
|
||||
<div className="text-right mb-3 lg:mb-8">
|
||||
<div className={`
|
||||
bg-neutral text-neutral-content bg-opacity-40 text-right
|
||||
px-4 py-1
|
||||
lg:px-8 lg:py-4
|
||||
|
||||
`}>
|
||||
<h5 className={`
|
||||
text-neutral-content
|
||||
text-xl font-bold
|
||||
md:text-2xl md:font-normal
|
||||
xl:text-3xl
|
||||
`} {...textShadow}
|
||||
>
|
||||
{post.title}
|
||||
</h5>
|
||||
<p className={`
|
||||
hidden md:block
|
||||
m-0 p-1 -mt-2
|
||||
text-neutral-content
|
||||
leading-normal text-sm font-normal
|
||||
opacity-70
|
||||
`}{ ...textShadow}>
|
||||
<TimeAgo date={post.date} /> by <strong>{post.author}</strong>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
|
||||
const BlogIndexPage = (props) => {
|
||||
const app = useApp()
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Page app={app} title={t('blog')} slug='blog'>
|
||||
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2 max-w-7xl">
|
||||
{props.posts.map(post => <Preview app={app} post={post} key={post.slug}/>)
|
||||
}
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
export default BlogIndexPage
|
||||
|
||||
/*
|
||||
* getStaticProps() is used to fetch data at build-time.
|
||||
*
|
||||
* On this page, it is loading the blog content from strapi.
|
||||
*
|
||||
* This, in combination with getStaticPaths() below means this
|
||||
* page will be used to render/generate all blog content.
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export async function getStaticProps({ params, locale }) {
|
||||
|
||||
const posts = await fetch(
|
||||
`${strapiHost}/blogposts?_locale=en&_sort=date:DESC&dev_eq=true`
|
||||
)
|
||||
.then(response => response.json())
|
||||
.then(data => data)
|
||||
.catch(err => console.log(err))
|
||||
|
||||
return {
|
||||
props: {
|
||||
posts: posts.map(post => ({
|
||||
slug: post.slug,
|
||||
title: post.title,
|
||||
date: post.date,
|
||||
author: post.author.displayname,
|
||||
image: strapiImage(post.image, ['medium']),
|
||||
})),
|
||||
...(await serverSideTranslations(locale)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,6 @@ import remarkRehype from 'remark-rehype'
|
|||
import rehypeSanitize from 'rehype-sanitize'
|
||||
import rehypeStringify from 'rehype-stringify'
|
||||
import yaml from 'yaml'
|
||||
import { getPosts } from '../../shared/prebuild/strapi.mjs'
|
||||
import { getMdxFileList } from '../../shared/prebuild/mdx.mjs'
|
||||
import config from '../algolia.config.mjs'
|
||||
dotenv.config()
|
||||
|
@ -30,70 +29,13 @@ dotenv.config()
|
|||
/*
|
||||
* Initialize Algolia client
|
||||
*/
|
||||
const client = algoliasearch(
|
||||
config.algolia.app,
|
||||
process.env.ALGOLIA_API_WRITE_KEY
|
||||
)
|
||||
const client = algoliasearch(config.algolia.app, process.env.ALGOLIA_API_WRITE_KEY)
|
||||
const index = client.initIndex(config.algolia.index)
|
||||
|
||||
/*
|
||||
* Turn a Strapi blog post into an object ready for indexing
|
||||
*/
|
||||
const transformBlogpost = post => ({
|
||||
objectID: `/blog/${post.slug}`,
|
||||
page: `/blog/${post.slug}`,
|
||||
title: post.title,
|
||||
date: post.date,
|
||||
slug: post.slug,
|
||||
body: post.body,
|
||||
author: post.author,
|
||||
caption: post.caption,
|
||||
type: 'blog',
|
||||
})
|
||||
|
||||
/*
|
||||
* Turn a Strapi author into an object ready for indexing
|
||||
*/
|
||||
const transformAuthor = author => ({
|
||||
objectID: `/blog/authors/${author.name}`,
|
||||
page: `/blog/authors/${author.name}`,
|
||||
name: author.name,
|
||||
displayname: author.displayname,
|
||||
about: author.about,
|
||||
})
|
||||
|
||||
/*
|
||||
* Get and index blog posts and author info from Strapi
|
||||
*/
|
||||
const indexStrapiContent = async () => {
|
||||
|
||||
// Say hi
|
||||
console.log(`🗂️ Indexing Strapi content to Algolia`)
|
||||
|
||||
const authors = {}
|
||||
const rawPosts = await getPosts('blog', 'dev', 'en')
|
||||
// Extract list of authors
|
||||
for (const [slug, post] of Object.entries(rawPosts)) {
|
||||
authors[post.author.slug] = transformAuthor(post.author)
|
||||
rawPosts[slug].author = post.author.slug
|
||||
}
|
||||
// Index posts to Algolia
|
||||
index
|
||||
.saveObjects(Object.values(rawPosts).map(post => transformBlogpost(post)))
|
||||
.then(({ objectIDs }) => null)
|
||||
.catch(err => console.log(err))
|
||||
// Index authors to Algolia
|
||||
index
|
||||
.saveObjects(Object.values(authors))
|
||||
.then(({ objectIDs }) => null)
|
||||
.catch(err => console.log(err))
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads markdown from disk and compiles it into HTML for indexing
|
||||
*/
|
||||
const markdownLoader = async file => {
|
||||
|
||||
const markdownLoader = async (file) => {
|
||||
const md = await fs.promises.readFile(file, 'utf-8')
|
||||
|
||||
const page = await unified()
|
||||
|
@ -124,12 +66,10 @@ const clearIndex = async () => {
|
|||
await index.clearObjects()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get and index markdown content
|
||||
*/
|
||||
const indexMarkdownContent = async () => {
|
||||
|
||||
// Say hi
|
||||
console.log(`🗂️ Indexing Markdown content to Algolia`)
|
||||
|
||||
|
@ -145,19 +85,15 @@ const indexMarkdownContent = async () => {
|
|||
await index.clearObjects()
|
||||
await index
|
||||
.saveObjects(pages)
|
||||
.then(({ objectIDs }) => null)
|
||||
.catch(err => console.log(err))
|
||||
.then(() => null)
|
||||
.catch((err) => console.log(err))
|
||||
}
|
||||
|
||||
const run = async () => {
|
||||
if (
|
||||
process.env.VERCEL_ENV === 'production' ||
|
||||
process.env.FORCE_ALGOLIA
|
||||
) {
|
||||
if (process.env.VERCEL_ENV === 'production' || process.env.FORCE_ALGOLIA) {
|
||||
console.log()
|
||||
await clearIndex()
|
||||
await indexMarkdownContent()
|
||||
await indexStrapiContent()
|
||||
console.log()
|
||||
} else {
|
||||
console.log()
|
||||
|
@ -168,4 +104,3 @@ const run = async () => {
|
|||
}
|
||||
|
||||
run()
|
||||
|
||||
|
|
|
@ -9,13 +9,15 @@ import { prebuildLab } from './lab.mjs'
|
|||
const SITE = process.env.SITE || 'lab'
|
||||
|
||||
const run = async () => {
|
||||
if (SITE !== 'lab') {
|
||||
if (SITE === 'org') {
|
||||
const mdxPages = await prebuildMdx(SITE)
|
||||
const [posts, authors] = await prebuildStrapi(SITE)
|
||||
const [posts] = await prebuildStrapi(SITE)
|
||||
prebuildNavigation(mdxPages, posts, SITE)
|
||||
} else {
|
||||
await prebuildLab()
|
||||
}
|
||||
} else if (SITE === 'dev') {
|
||||
const mdxPages = await prebuildMdx(SITE)
|
||||
prebuildNavigation(mdxPages, false, SITE)
|
||||
} else await prebuildLab()
|
||||
|
||||
await prebuildI18n(SITE)
|
||||
await prebuildContributors(SITE)
|
||||
await prebuildPatrons(SITE)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue