Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement contentlayer #5

Merged
merged 7 commits into from Dec 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Expand Up @@ -48,4 +48,7 @@ yarn-error.log*
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*
.pnp.*

# Contentlayer
.contentlayer
2 changes: 1 addition & 1 deletion content/posts/breaking-bad-fan-video-walt-jesse.mdx
Expand Up @@ -5,4 +5,4 @@ tags:
- video
---

https://youtube.com/watch?v=FveFmShXoRE
<YouTube youTubeId="FveFmShXoRE" noCookie />
2 changes: 1 addition & 1 deletion content/posts/el-alma-de-la-ciudad.mdx
Expand Up @@ -9,7 +9,7 @@ tags:

Venía platicando con Diana luego de una muy rica cena y caminata, casi todo el camino al son de Panchita Disco de el increíble grupo Burocracia Cósmica:

https://youtube.com/watch?v=yN5fq1NyKq4
<YouTube youTubeId="yN5fq1NyKq4" noCookie />

Vamos, escúchenla. ¿Listos? Bueno. Cuando íbamos pasando por el callejón donde solemos verlos tocar los domingos, ella empezó a tararear la canción, y en ese momento comencé a sentir como si la calle tuviera vida. Los músicos, las personas moviéndose al ritmo de la canción. Todo eso estaba presente. Los edificios también sentían la energía de la música, y ellos mismos comenzaban a moverse.

Expand Down
2 changes: 1 addition & 1 deletion content/posts/felices-fiestas.mdx
Expand Up @@ -5,7 +5,7 @@ tags:
- personal
---

![https://www.flickr.com/photos/alfito_grc/2088576792/](https://farm3.staticflickr.com/2151/2088576792_ff26b4ec1d_z.jpg?zz=1)
<Flickr flickrLink="2151/2088576792_ff26b4ec1d_z.jpg" />

Francamente no soy muy de celebrar cosas, menos la navidad, tal vez porque los dos últimos años fueron algo tristes en ese aspecto, sin embargo, esta vez tengo muchas razones para estar agradecido. Si, perdí a personas muy queridas para mi, pero a cambio gane a muchísimas otras personas maravillosas, que me permitieron entrar a formar aunque fuera una pequeña parte de su vida.

Expand Down
Expand Up @@ -28,7 +28,7 @@ We need to disable the auto-loading of CSS by FontAwesome and add the styles our

in my case it was accomplished by modifying the `gatsby-browser.js` file and adding:

```javascript
```javascript:gatsby-browser.js
import { config } from '@fortawesome/fontawesome-svg-core';
import '@fortawesome/fontawesome-svg-core/styles.css';

Expand Down
2 changes: 1 addition & 1 deletion content/posts/ludovico-einaudi-divenire.mdx
Expand Up @@ -5,4 +5,4 @@ tags:
- video
---

https://youtube.com/watch?v=_RyPFwAWSKM
<YouTube youTubeId="_RyPFwAWSKM" noCookie />
2 changes: 1 addition & 1 deletion content/posts/miracle-sudoku.mdx
Expand Up @@ -11,4 +11,4 @@ I'm a big fan of Sudokus, is one of those things where it's possible to spend se

It starts with only two cells filled and several extra rules, besides Sudoku rules. It's really fun how he goes from "I'm being trolled" to "Oh my god..".

https://youtube.com/watch?v=yKf9aUIxdb4
<YouTube youTubeId="yKf9aUIxdb4" noCookie />
10 changes: 5 additions & 5 deletions content/posts/personajes-en-los-esports.mdx
Expand Up @@ -12,22 +12,22 @@ Estoy viendo el torneo de CS:GO en [Dreamhack](http://www.twitch.tv/dreamhackcs)

### BigDaddyN0Tail (Dota 2)

https://youtube.com/watch?v=sO2T4JNHDI0
<YouTube youTubeId="sO2T4JNHDI0" noCookie />

### SumaiL (Dota 2)

https://youtube.com/watch?v=CoX_-eX2ByM
<YouTube youTubeId="CoX_-eX2ByM" noCookie />

### s4 (Dota 2)

https://youtube.com/watch?v=dy5DDi0qbGw
<YouTube youTubeId="dy5DDi0qbGw" noCookie />

### FalleN (CS:GO)

https://youtube.com/watch?v=_KB9P3goVic
<YouTube youTubeId="_KB9P3goVic" noCookie />

### Olofmeister (CS:GO)

https://youtube.com/watch?v=1mvpFEzXHg0
<YouTube youTubeId="1mvpFEzXHg0" noCookie />

Hay mas videos de perfiles de CS:GO en el canal de [Valve](https://www.youtube.com/user/Valve/videos) y de Dota 2 en el canal de [Dota 2](https://www.youtube.com/user/dota2/videos).
2 changes: 1 addition & 1 deletion content/posts/united-we-rise.mdx
Expand Up @@ -5,7 +5,7 @@ tags:
- video
---

https://youtube.com/watch?v=ePSqOsMskWQ
<YouTube youTubeId="ePSqOsMskWQ" noCookie />

Tenía este video guardado en los borradores desde hace mas de un año, y sigue siendo igual de válido que antes.

Expand Down
2 changes: 1 addition & 1 deletion content/posts/viajando.mdx
Expand Up @@ -8,7 +8,7 @@ tags:
- couchsurfing
---

![https://www.flickr.com/photos/inthesity/2844059346/](https://farm4.staticflickr.com/3246/2844059346_85047348fd_o.jpg)
<Flickr flickrLink="3246/2844059346_85047348fd_o.jpg" />

Estas semanas que vienen se ven un poco pesadas, mucho trabajo por delante, mucho estrés y muchas cosas por hacer. Aún así estoy emocionado porque son buenos proyectos en los que seguro aprenderé cosas nuevas. De cualquier modo estuve pensando y creo que para relajarme un poco (de esto y de otras cosas que vengo cargando desde antes), me he decidido a empezar a viajar mas.

Expand Down
137 changes: 137 additions & 0 deletions contentlayer.config.ts
@@ -0,0 +1,137 @@
import { defineDocumentType, makeSource } from 'contentlayer/source-files';
import { createApi } from 'unsplash-js';
import type { ComputedFields } from 'contentlayer/source-files';
import readingTime from 'reading-time';
import slug from 'rehype-slug';
import headings from 'rehype-autolink-headings';
import { rehypeAccessibleEmojis } from 'rehype-accessible-emojis';
import { h, s } from 'hastscript';
import highlight from 'rehype-highlight';
import { toString } from 'mdast-util-to-string';
import codeTitles from 'rehype-code-titles';
import remarkGfm from 'remark-gfm';

import Cache from './src/utils/cache';

const cache = new Cache();

const unsplash = createApi({
accessKey: process.env.UNSPLASH_ACCESS_KEY as string,
});

const computedFields: ComputedFields = {
slug: {
type: 'string',
resolve: (doc) => doc._raw.sourceFileName.replace(/\.mdx$/, ''),
},
readingTime: { type: 'json', resolve: (doc) => readingTime(doc.body.raw) },
unsplash: {
type: 'json',
resolve: async (doc) => {
let image = null;
if (doc.image) {
image = await cache.get(doc.image);

if (!image) {
const response = (
await unsplash.photos.get({ photoId: doc.image })
)?.response;

image = {
description:
response?.description || response?.alt_description,
url: response?.urls.raw,
blur_hash: response?.blur_hash,
attributionLink: response?.links.html,
width: response?.width,
height: response?.height,
user: {
name: response?.user.name,
link: response?.user.links.html,
},
};

await cache.set(doc.image, image);
}

return image;
}

return null;
},
},
};

export const Post = defineDocumentType(() => ({
name: 'Post',
filePathPattern: 'posts/*.mdx',
bodyType: 'mdx',
fields: {
title: { type: 'string', required: true },
date: { type: 'date', required: true },
tags: { type: 'list', of: { type: 'string' } },
image: { type: 'string' },
excerpt: { type: 'string' },
},
computedFields,
}));

const contentLayerConfig = makeSource(async () => {
return {
contentDirPath: 'content',
documentTypes: [Post],
mdx: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
slug,
[
headings,
{
behavior: 'after',
group: h('div.heading-container'),
properties: {
ariaHidden: true,
tabIndex: -1,
},
content: (node: Element) => {
return [
h(
'span.visually-hidden',
`Read the "${toString(
node.children,
)}" section`,
),
h(
'span.icon.icon-link',
{ ariaHidden: true },
s(
'svg',
{
'aria-hidden': true,
focusable: false,
height: 30,
width: 30,
version: '1.1',
viewBox: '0 0 16 16',
},
[
s('path', {
'fill-rule': 'evenodd',
d: 'M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z',
}),
],
),
),
];
},
},
],
rehypeAccessibleEmojis,
codeTitles,
highlight,
],
},
};
});

export default contentLayerConfig;
5 changes: 5 additions & 0 deletions next.config.js
@@ -1,7 +1,11 @@
const withPlugins = require('next-compose-plugins');
const optimizedImages = require('next-optimized-images');
const pwa = require('next-pwa');
const { withContentlayer } = require('next-contentlayer');

/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
images: {
domains: ['osiux.ws', 'www.osiux.ws', 'images.unsplash.com'],
Expand Down Expand Up @@ -33,6 +37,7 @@ module.exports = withPlugins(
},
},
],
withContentlayer(),
],
nextConfig,
);
20 changes: 12 additions & 8 deletions package.json
Expand Up @@ -23,23 +23,24 @@
"@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@mdx-js/react": "^1.6.22",
"@tailwindcss/typography": "^0.4.1",
"@vercel/node": "^1.12.1",
"blurhash": "^1.1.4",
"cache-manager": "^3.6.0",
"cache-manager-fs-hash": "^1.0.0",
"contentlayer": "^0.0.33",
"date-fns": "^2.27.0",
"form-data": "^4.0.0",
"framer-motion": "^5.5.5",
"fs-extra": "^10.0.0",
"gatsby-remark-embedder": "^5.0.0",
"gray-matter": "^4.0.3",
"hast-util-parse-selector": "^3.1.0",
"hastscript": "^7.0.2",
"highlight.js": "^11.3.1",
"mdx-embed": "^0.0.22",
"next": "12.0.7",
"next-compose-plugins": "^2.2.1",
"next-mdx-remote": "^3.0.8",
"next-contentlayer": "^0.0.33",
"next-optimized-images": "^3.0.0-canary.10",
"next-pwa": "^5.4.4",
"next-remote-watch": "^1.0.0",
Expand All @@ -52,11 +53,6 @@
"react-dom": "17.0.2",
"react-hint": "^3.2.1",
"react-optimized-image": "^0.4.1",
"reading-time": "^1.5.0",
"rehype-accessible-emojis": "^0.3.2",
"rehype-autolink-headings": "^6.1.0",
"rehype-highlight": "^5.0.1",
"rehype-slug": "^5.0.0",
"slugify": "^1.6.4",
"unsplash-js": "^7.0.15"
},
Expand All @@ -74,7 +70,15 @@
"hast-util-is-element": "^2.1.2",
"husky": "^7.0.4",
"lint-staged": ">=11",
"mdast-util-to-string": "^3.1.0",
"prettier": "2.5.1",
"reading-time": "^1.5.0",
"rehype-accessible-emojis": "^0.3.2",
"rehype-autolink-headings": "^6.1.0",
"rehype-code-titles": "^1.0.3",
"rehype-highlight": "^5.0.1",
"rehype-slug": "^5.0.0",
"remark-gfm": "^3.0.1",
"tailwindcss": "^2.2.17",
"twin.macro": "^2.8.2",
"typescript": "^4.5.4"
Expand Down
2 changes: 1 addition & 1 deletion pages/_app.tsx
Expand Up @@ -18,7 +18,7 @@ config.autoAddCss = false;
import Navigation from '@app/components/Navigation';
import Footer from '@app/components/Footer';

const Container = tw.div`h-screen antialiased grid grid-rows-layout max-w-3xl mx-auto w-full py-6 px-3 mt-28 md:(max-w-4xl px-0 pt-0 pb-16)`;
const Container = tw.div`h-screen antialiased grid grid-rows-layout max-w-3xl mx-auto w-full py-6 px-3 md:(max-w-4xl px-0 pt-0 pb-16)`;

const App = ({ Component, pageProps }: AppProps) => (
<CacheProvider value={cache}>
Expand Down
13 changes: 5 additions & 8 deletions pages/blog/[[...page]].tsx
@@ -1,18 +1,18 @@
import tw from 'twin.macro';
import type { GetStaticProps, GetStaticPaths } from 'next';
import { NextSeo } from 'next-seo';
import { allPosts } from '.contentlayer/data';
import type { Post } from '.contentlayer/types';

import SimplePost from '@app/components/posts/SimplePost';
import Pagination from '@app/components/Pagination';
import Layout from '@app/components/Layout';

import { getPostsSlug, getPosts, PostData } from '@app/utils/posts';
import { comparePostDates } from '@app/utils/dates';

export const POSTS_PER_PAGE = 10;

export type ArchivePageProps = {
posts: PostData[];
posts: Post[];
totalPages: number;
currentPage: number;
};
Expand All @@ -23,7 +23,7 @@ const ArchivePage = ({ posts, totalPages, currentPage }: ArchivePageProps) => {
<NextSeo title={`Archive - Page ${currentPage}`} />
<h1 tw="text-5xl mb-10">Archive</h1>
{posts.map((post) => (
<SimplePost key={post.meta.slug} {...post.meta} />
<SimplePost key={post.slug} {...post} />
))}
<Pagination totalPages={totalPages} currentPage={currentPage} />
</Layout>
Expand All @@ -33,8 +33,6 @@ const ArchivePage = ({ posts, totalPages, currentPage }: ArchivePageProps) => {
export const getStaticProps: GetStaticProps = async ({ params }) => {
const [, page] = params?.page?.[0]?.split('-') ?? [, 1];

const allPosts = await getPosts();

const sortedPosts = allPosts.sort(comparePostDates);

return {
Expand All @@ -50,9 +48,8 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
};

export const getStaticPaths: GetStaticPaths = async () => {
const posts = getPostsSlug();
const paths = Array.from(
{ length: Math.ceil(posts.length / POSTS_PER_PAGE) },
{ length: Math.ceil(allPosts.length / POSTS_PER_PAGE) },
(_, i) => ({
params: {
page: i === 0 ? undefined : [`page-${i + 1}`],
Expand Down