Skip to content

Commit

Permalink
post(carbonyl): first draft
Browse files Browse the repository at this point in the history
  • Loading branch information
fathyb committed Jan 27, 2023
1 parent fb16107 commit dabb0a7
Show file tree
Hide file tree
Showing 45 changed files with 2,553 additions and 351 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ node_modules/

/build
/src/generated
/src/posts/*/preview.mdx
/src/posts/*/*.gen.mdx
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@mui/icons-material": "^5.10.9",
"@mui/material": "^5.10.11",
"@react-three/fiber": "^8.9.1",
"feed": "^4.2.2",
"history": "^5.3.0",
"prism-themes": "^1.9.0",
"react": "^18.2.0",
Expand Down
27 changes: 0 additions & 27 deletions scripts/footer-loader.js

This file was deleted.

161 changes: 125 additions & 36 deletions scripts/gen-posts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,62 +10,151 @@ import { unified } from 'unified'
const mdx = unified().use(remarkParse).use(remarkMdx).use(remarkMath)
const rootDir = path.dirname(new URL(import.meta.url).pathname)
const postsDir = path.join(rootDir, '../src/posts')
const generatedDir = path.join(rootDir, '../src/generated')
const files = await fs.readdir(postsDir, { withFileTypes: true })
const posts = await Promise.all(
files
.filter((file) => file.isDirectory() && !file.name.startsWith('.'))
.map(async ({ name: file }) => {
const contents = await fs.readFile(
path.join(postsDir, file, 'index.mdx'),
'utf-8',
)
const tree = mdx.parse(contents)
const title = tree.children.find(
(c) => c.type === 'heading' && c.depth === 1,
)?.children[0]?.value

if (!title || typeof title !== 'string') {
throw new Error(`Could not find post title for ${file}`)
}

const secondHeading = tree.children.filter(
(c) => c.type === 'heading' && c.depth === 2,
)[1]

await fs.writeFile(
path.join(postsDir, file, 'preview.mdx'),
secondHeading
? contents.slice(0, secondHeading.position.start.offset)
: contents,
)

return { file, title }
}),
.map(async ({ name: file }) =>
Promise.all([
fs
.readFile(path.join(postsDir, file, 'index.mdx'), 'utf-8')
.then(async (contents) => {
const tree = mdx.parse(contents)
const title = tree.children
.find((c) => c.type === 'heading' && c.depth === 1)
?.children.map((node) => {
if (typeof node.value === 'string') {
return node.value
} else {
console.error('node:', node)

throw new Error('Unsupported title node!')
}
})
.join('')
.trim()

if (!title) {
throw new Error(
`Could not find post title for ${file}`,
)
}

let preview = ''
let description = ''

for (let i = 0; i < tree.children.length; i++) {
const node = tree.children[i]

if (node.type === 'thematicBreak') {
break
}

preview += contents.slice(
node.position.start.offset,
tree.children[i + 1]
? tree.children[i + 1].position.start.offset
: node.position.end.offset,
)
}

for (let i = 3; i < tree.children.length; i++) {
const node = tree.children[i]

if (
node.type === 'mdxjsEsm' ||
node.type === 'mdxJsxFlowElement'
) {
continue
}

if (node.type === 'thematicBreak') {
break
}

description += contents.slice(
node.position.start.offset,
tree.children[i + 1]
? tree.children[i + 1].position.start.offset
: node.position.end.offset,
)
}

await Promise.all([
fs.writeFile(
path.join(
postsDir,
file,
'index.preview.gen.mdx',
),
preview,
),
fs.writeFile(
path.join(
postsDir,
file,
'index.description.gen.mdx',
),
description,
),
])

return { file, title }
}),
fs
.stat(path.join(postsDir, file, 'index.tsx'), 'utf-8')
.then(() => true)
.catch((error) => {
if (error?.code === 'ENOENT') {
return false
} else {
throw error
}
})
.then((provider) =>
fs.writeFile(
path.join(generatedDir, `${file}.entry.tsx`),
`
import Post from ${JSON.stringify(
`../posts/${file}${
provider ? '' : '/index.mdx'
}`,
)}
export default Post
`,
),
),
]).then(([post]) => post),
),
)

const hidden = [] //['every-sin']
const chunks = posts.map((post) => {
const slug = post.file.replace(/\.mdx?$/, '')

return `
{
path: ${JSON.stringify('/' + slug)},
title: ${JSON.stringify(post.title)},
hidden: ${hidden.includes(slug)},
post: lazy(() =>
import(${JSON.stringify(
path.join('../posts', post.file, 'index.mdx'),
)})
import(${JSON.stringify(`./${post.file}.entry`)})
),
preview: lazy(() =>
description: lazy(() =>
import(${JSON.stringify(
path.join('../posts', post.file, 'preview.mdx'),
path.join(
'../posts',
post.file,
'index.description.gen.mdx',
),
)})
)
),
preview: require(${JSON.stringify(
path.join('../posts', post.file, 'index.preview.gen.mdx'),
)}).default,
}
`
})
const generatedDir = path.join(rootDir, '../src/generated')

await fs.mkdir(generatedDir, { recursive: true })
await fs.writeFile(
Expand Down
119 changes: 66 additions & 53 deletions src/components/app.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { useState } from 'react'
import { matchPath, useLocation } from 'react-router'
import { Box, Typography, useTheme } from '@mui/material'

import { posts } from '../generated/posts'
import { useTitle } from '../hooks/use-title'
import { ThemeProvider } from '../providers/theme-provider'
import { useGlobalTransition } from '../providers/router-provider'

import { Link } from './link'
import { Sidebar } from './sidebar'
import { MDXWrapper } from './mdx-wrapper'
import { Footer } from './footer'

export function App() {
return (
Expand All @@ -20,74 +23,84 @@ export function App() {
function Route() {
const theme = useTheme()
const { pathname } = useLocation()
const [pending] = useGlobalTransition()
const [pendingPost, setPendingPost] = useState('')
const post = posts.find((p) => matchPath(p.path, pathname))

useTitle(post ? `${post.title} - Fathy` : 'Fathy')
useTitle(post ? `${post.title} - Fathy Boundjadj` : 'Fathy Boundjadj')

if (post) {
return (
<MDXWrapper main>
<post.post />
<Footer githubEditPath={`src/posts/${post.path}/index.mdx`} />
</MDXWrapper>
)
}

if (matchPath('/', pathname)) {
return (
<>
<Box
sx={{
position: 'relative',
padding: theme.spacing(2),
zIndex: 500,
if (!matchPath('/', pathname)) {
return <h2>not found</h2>
}

return (
<>
<Box
sx={{
position: 'relative',
padding: theme.spacing(2),
zIndex: 500,

[`@media (min-width: ${theme.spacing(125)})`]: {
padding: 0,
[`@media (min-width: ${theme.spacing(125)})`]: {
padding: 0,
position: 'absolute',
right: 0,
top: 0,
bottom: 0,
width: theme.spacing(33),
},
}}
>
<Sidebar />
</Box>
{posts.map((post) => (
<Box key={post.path} position="relative" zIndex={100}>
<MDXWrapper
sx={{
overflow: 'hidden',
position: 'relative',
maxHeight: theme.spacing(60),
maskImage:
'linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0) 90%)',
}}
>
<post.preview />
</MDXWrapper>

<Box
sx={{
position: 'absolute',
bottom: theme.spacing(1),
right: 0,
top: 0,
bottom: 0,
width: theme.spacing(33),
},
}}
>
<Sidebar />
</Box>
{posts
.filter((post) => !post.hidden)
.map((post) => (
<Box key={post.path} position="relative" zIndex={100}>
<MDXWrapper
sx={{
overflow: 'hidden',
position: 'relative',
maxHeight: theme.spacing(60),
maskImage:
'linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0) 90%)',
}}
>
<post.preview />
</MDXWrapper>

<Box
sx={{
position: 'absolute',
bottom: theme.spacing(1),
right: 0,
left: 0,
left: 0,

textAlign: 'center',
textAlign: 'center',
}}
>
<Typography>
<Link
to={post.path}
onClick={() => {
setPendingPost(post.path)
}}
>
<Typography>
<Link to={post.path}>Read more..</Link>
</Typography>
</Box>
</Box>
))}
</>
)
}

return <h2>not found</h2>
{pending && pendingPost === post.path
? 'Loading..'
: 'Read more..'}
</Link>
</Typography>
</Box>
</Box>
))}
</>
)
}

0 comments on commit dabb0a7

Please sign in to comment.