Skip to content

Commit

Permalink
add custom rehype-get-code-props plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkMelior committed Jul 13, 2024
1 parent c5aec8c commit c8d4ade
Show file tree
Hide file tree
Showing 21 changed files with 410 additions and 126 deletions.
72 changes: 50 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,64 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Реализованный функционал

## Getting Started
### Интернационализация (i18n)

First, run the development server:
> Реализован i18n без использования сторонних библиотек
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
#### Файлы:

- [middleware.ts](/middleware.ts) - основной функционал работы i18n
- [getLang()](src/shared/config/i18n/get-lang.ts) - возвращает выбранный язык `en | ru`
- [getDictionary()](src/shared/config/i18n/dictionaries.ts) - возвращает объект с переводами `ключ-значение`
- [type Dictionary](src/shared/config/i18n/dictionaries.ts)
- [/dictionary](src/shared/config/i18n/dictionaries/) - директория с json файлами переводов

#### Особенности:

Не нужно прокидывать props в каждый компонент, где используется перевод:

```diff-ts
- export const Navbar = ({ dict }: { dict: Dictionary['ui'] }) => {...}
+ export const Navbar = async () => {
+ const dictionary = await getDictionary();
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Не нужно передавать язык в `getDictionary(lang)`, как это реализовано в [документации Next.js](https://nextjs.org/docs/app/building-your-application/routing/internationalization#localization):

```diff
- getDictionary(lang)
+ getDictionary()
```

Просто используем в любом серверном компоненте `const dict = await getDictionary();` или прокидываем в клиентский компонент как props `{ dict }: { dict: Dictionary['ui'] }`

---

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
## MDX

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
> MDX синхронизирован с i18n
## Learn More
#### Реализация MDX:

To learn more about Next.js, take a look at the following resources:
- [`app/[lang]/projects/[category]/[name]/page.tsx`](/app/[lang]/projects//[category]/[name]/page.tsx) - layout для mdx файлов
- [`app/[lang]/projects/[category]/page.tsx`](/app/[lang]/projects/[category]/page.tsx) - страница отображения проектов из категории
- [getMetadata()](/src/entity/project/model/services/get-metadata.ts) - получение metadata из mdx
- [getProject(category, name)](/src/entity/project/model/services/get-project.ts) - получение проекта по категории и имени
- [getProjectsByCategory(category)](/src/entity/project/model/services/get-projects-by-category.ts) - получение всех проектов в выбранной категории
- [getProjects()](/src/entity/project/model/services/get-projects.ts) - получение всех категорий и проектов
- [mdx-components.tsx](/src/mdx-components.tsx) - настройка отображения mdx
- [rehypeExtractCodeProps](/src/shared/lib/rehype-extract-code-props/rehype-extract-code-props.ts) - самописный rehype-плагин для чтения пар ключ-значение в коде

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
Вывод mdx страниц и метаданных происходит за счёт преобразования его через [gray-matter](https://www.npmjs.com/package/gray-matter). Рендер mdx через MDXRemote `next-mdx-remote/rsc` для серверного рендеринга (смотреть [`app/[lang]/projects/[category]/[name]/page.tsx`](/app/[lang]/projects//[category]/[name]/page.tsx))

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
---

## Deploy on Vercel
## Архитектура проекта

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Проект написан в соответствии с методологией [Feature-Sliced Design](https://feature-sliced.design/docs/get-started/tutorial).

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
- [shared](/src/shared/) - функциональность многократного использования;
- [entity](/src/entity/) - бизнес сущности;
- [features](/src/features/) - повторно используемые реализации целых функций продукта;
- [widgets](/src/widgets/) - большие автономные блоки функциональности или пользовательского интерфейса;
- [app](/src/app/) - все, что обеспечивает работу приложения.
5 changes: 5 additions & 0 deletions app/[lang]/home-en.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
note: 'Home Page'
title: "👋 Hi, I'm Mark Melior"
description: 'I am learning very fast and a lot, and my communication skills are at a high level. I am looking for a company where I will improve my skills to a strong Frontend developer. I will be glad to meet new people (:'
---
5 changes: 5 additions & 0 deletions app/[lang]/home-ru.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
note: 'Главная страница'
title: '👋 Привет, я Mark Melior'
description: 'Очень быстро и много учусь, коммуникативные навыки на высоком уровне) Ищу компанию, в которой буду совершенствовать свои навыки до сильного Frontend разработчика. Буду рад новым знакомствам (:'
---
4 changes: 1 addition & 3 deletions app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ClientProviders } from '@/app/providers/client-providers';
import '@/app/styles/index.scss';
import { getDictionary, i18n, Locale } from '@/shared/config';
import { i18n, Locale } from '@/shared/config';
import { PageLoader } from '@/shared/ui';
import { Footer, Light, Navbar, Sidebar } from '@/widgets';
import type { Metadata } from 'next';
Expand All @@ -27,8 +27,6 @@ export default async function RootLayout({
children,
params,
}: Readonly<Props>) {
const dict = await getDictionary(params.lang);

return (
<html lang={params.lang}>
<body className={inter.className}>
Expand Down
4 changes: 4 additions & 0 deletions app/[lang]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ export default async function Home({
}: {
params: { lang: Locale };
}) {
// const lang = await getLang();
// const HomePage = dynamic(() => import(`./home-${lang}.mdx`));

const dictionary = await getDictionary(lang);
const { description, note, title } = dictionary['home-page'];

return (
<>
<Header note={note} title={title} description={description} />
{/* <HomePage /> */}
</>
);
}
28 changes: 23 additions & 5 deletions app/[lang]/projects/[category]/[name]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { getProject } from '@/entity/project';
import { MDXComponentsFormat } from '@/mdx-components';
import { rehypeExtractCodeProps } from '@/shared/lib';
import { Header } from '@/widgets';
import { MDXComponents } from 'mdx/types';
import { Metadata } from 'next';
import { MDXRemote } from 'next-mdx-remote/rsc';
import dynamic from 'next/dynamic';
import remarkGfm from 'remark-gfm';

export type ProjectPageProps = {
params: { name: string; category: string };
};

export default async function ProjectPage({ params }: ProjectPageProps) {
const Project = dynamic(
() => import(`/projects/${params.category}/${params.name}/page.mdx`),
);
const { metadata, content } = await getProject(params.category, params.name);

const { metadata } = await getProject(params.category, params.name);
const customComponents: MDXComponents = {
AuthExample: dynamic(() =>
import('@/projects/best-practice/app-router-auth/examples/auth').then(
(mod) => mod.AuthExample,
),
),
};

return (
<>
Expand All @@ -22,7 +31,16 @@ export default async function ProjectPage({ params }: ProjectPageProps) {
description={metadata?.description}
tags={metadata?.tags}
/>
<Project />
<MDXRemote
source={content}
components={{ ...MDXComponentsFormat, ...customComponents }}
options={{
mdxOptions: {
rehypePlugins: [rehypeExtractCodeProps],
remarkPlugins: [remarkGfm],
},
}}
/>
</>
);
}
Expand Down
1 change: 0 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const nextConfig = {
const withMDX = createMDX({
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [],
},
});

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
"gray-matter": "^4.0.3",
"jose": "^5.6.3",
"next": "14.2.4",
"next-mdx-remote": "^5.0.0",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.2.1",
"react-syntax-highlighter": "^15.5.0",
"rehype-mdx-code-props": "^3.0.1",
"remark-gfm": "^4.0.0",
"tailwind-merge": "^2.4.0",
"unist-util-visit": "^5.0.0",
"vaul": "^0.9.1",
"zod": "^3.23.8"
},
Expand Down
Loading

0 comments on commit c8d4ade

Please sign in to comment.