diff --git a/app/markdown.css b/app/markdown.css
new file mode 100644
index 0000000..6cafa05
--- /dev/null
+++ b/app/markdown.css
@@ -0,0 +1,256 @@
+.markdown {
+ all: unset;
+ display: block;
+ box-sizing: border-box;
+
+ color: #333;
+ line-height: 1.6;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+}
+
+.markdown ul,
+.markdown ol {
+ list-style: none;
+}
+.markdown li {
+ display: list-item; /* Возвращаем поведение списка */
+}
+
+
+.markdown > *:first-child {
+ margin-top: 0;
+}
+
+.markdown > *:last-child {
+ margin-bottom: 0;
+}
+.markdown h1,
+.markdown h2,
+.markdown h3,
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+ font-weight: 600;
+ line-height: 1.25;
+ margin-top: 1.5em;
+ margin-bottom: 0.5em;
+ color: #111;
+}
+
+.markdown h1 {
+ font-size: 2em;
+ border-bottom: 2px solid #eaecef;
+ padding-bottom: 0.3em;
+}
+
+.markdown h2 {
+ font-size: 1.5em;
+ border-bottom: 1px solid #eaecef;
+ padding-bottom: 0.3em;
+}
+
+.markdown h3 { font-size: 1.25em; }
+.markdown h4 { font-size: 1em; }
+.markdown h5 { font-size: 0.875em; }
+.markdown h6 { font-size: 0.85em; color: #666; }
+
+.markdown p {
+ margin-top: 0;
+ margin-bottom: 1em;
+}
+
+.markdown strong {
+ font-weight: 600;
+}
+
+.markdown em {
+ font-style: italic;
+}
+
+.markdown del {
+ text-decoration: line-through;
+ color: #666;
+}
+
+.markdown hr {
+ height: 1px;
+ border: none;
+ background-color: #eaecef;
+ margin: 2em 0;
+}
+
+.markdown a {
+ color: #0366d6;
+ text-decoration: none;
+}
+
+.markdown a:hover {
+ text-decoration: underline;
+}
+
+.markdown a:visited {
+ color: #5a32a3;
+}
+
+.markdown ul,
+.markdown ol {
+ padding-left: 2em;
+ margin-bottom: 1em;
+}
+
+.markdown li {
+ margin-bottom: 0.5em;
+}
+
+.markdown li > ul,
+.markdown li > ol {
+ margin-top: 0.5em;
+}
+
+.markdown ul {
+ list-style-type: disc;
+}
+
+.markdown ul ul {
+ list-style-type: circle;
+}
+
+.markdown ul ul ul {
+ list-style-type: square;
+}
+
+.markdown ol {
+ list-style-type: decimal;
+}
+
+.markdown li > p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+.markdown code {
+ background-color: #f6f8fa;
+ padding: 0.2em 0.4em;
+ border-radius: 3px;
+ font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
+ font-size: 0.9em;
+ color: #e74c3c;
+}
+
+.markdown pre {
+ background-color: #f6f8fa;
+ padding: 1em;
+ border-radius: 6px;
+ overflow: auto;
+ margin-bottom: 1em;
+ border: 1px solid #e1e4e8;
+}
+
+.markdown pre code {
+ background-color: transparent;
+ padding: 0;
+ color: inherit;
+ font-size: 0.9em;
+ line-height: 1.5;
+}
+
+.markdown blockquote {
+ margin: 0;
+ padding: 0 1em;
+ color: #666;
+ border-left: 4px solid #dfe2e5;
+}
+
+.markdown blockquote > :first-child {
+ margin-top: 0;
+}
+
+.markdown blockquote > :last-child {
+ margin-bottom: 0;
+}
+
+.markdown table {
+ border-collapse: collapse;
+ width: 100%;
+ margin-bottom: 1em;
+}
+
+.markdown table th,
+.markdown table td {
+ border: 1px solid #dfe2e5;
+ padding: 0.5em 1em;
+}
+
+.markdown table th {
+ background-color: #f6f8fa;
+ font-weight: 600;
+ text-align: left;
+}
+
+.markdown table tr:nth-child(even) {
+ background-color: #fafbfc;
+}
+
+.markdown img {
+ max-width: 100%;
+ height: auto;
+ border-radius: 4px;
+}
+
+.markdown img + em {
+ display: block;
+ text-align: center;
+ color: #666;
+ font-size: 0.9em;
+ margin-top: 0.5em;
+}
+
+.markdown input[type="checkbox"] {
+ margin-right: 0.5em;
+ margin-left: -1.5em;
+}
+
+@media (prefers-color-scheme: dark) {
+ .markdown {
+ color: #e0e0e0;
+ background-color: transparent;
+ }
+
+ .markdown h1,
+ .markdown h2,
+ .markdown h3,
+ .markdown h4,
+ .markdown h5,
+ .markdown h6 {
+ color: #fff;
+ border-color: #444;
+ }
+
+ .markdown code,
+ .markdown pre {
+ background-color: #2d2d2d;
+ border-color: #444;
+ }
+
+ .markdown a {
+ color: #58a6ff;
+ }
+
+ .markdown blockquote {
+ color: #aaa;
+ border-color: #555;
+ }
+
+ .markdown table th,
+ .markdown table td {
+ border-color: #444;
+ }
+
+ .markdown table th {
+ background-color: #2d2d2d;
+ }
+
+ .markdown table tr:nth-child(even) {
+ background-color: #2a2a2a;
+ }
+}
\ No newline at end of file
diff --git a/app/post/[slug]/page.tsx b/app/post/[slug]/page.tsx
index 4219364..ad02418 100644
--- a/app/post/[slug]/page.tsx
+++ b/app/post/[slug]/page.tsx
@@ -1,6 +1,7 @@
import { getPostData, getAllPostSlugs } from '@/lib/posts';
import { notFound } from 'next/navigation';
import Link from 'next/link';
+import "@/app/markdown.css"
interface PostPageProps {
params: Promise<{ slug: string }>;
@@ -88,7 +89,7 @@ export default async function PostPage({ params }: PostPageProps) {
diff --git a/lib/posts.ts b/lib/posts.ts
index 255118f..ebbdba2 100644
--- a/lib/posts.ts
+++ b/lib/posts.ts
@@ -3,6 +3,12 @@ import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
+import { unified } from 'unified';
+import remarkParse from 'remark-parse';
+import remarkGfm from 'remark-gfm';
+import remarkRehype from 'remark-rehype';
+import rehypeRaw from 'rehype-raw';
+import rehypeStringify from 'rehype-stringify';
const postsDirectory = path.join(process.cwd(), 'posts');
@@ -46,21 +52,39 @@ export function getSortedPostsData(): Omit[] {
});
}
-export async function getPostData(slug: string): Promise {
- const fullPath = path.join(postsDirectory, `${slug}.md`);
- const fileContents = fs.readFileSync(fullPath, 'utf8');
- const matterResult = matter(fileContents);
- const processedContent = await remark()
- .use(html)
- .process(matterResult.content);
- const contentHtml = processedContent.toString();
+export async function getPostData(slug: string): Promise {
+ try {
+ const fullPath = path.join(postsDirectory, `${slug}.md`);
+
+ if (!fs.existsSync(fullPath)) {
+ console.error(`Файл не найден: ${fullPath}`);
+ return null;
+ }
+
+ const fileContents = fs.readFileSync(fullPath, 'utf8');
+ const matterResult = matter(fileContents);
+
+ // Используем unified pipeline для более полной поддержки Markdown
+ const processedContent = await unified()
+ .use(remarkParse) // парсим Markdown
+ .use(remarkGfm) // добавляем поддержку GFM (таблицы, задачи и т.д.)
+ .use(remarkRehype, { allowDangerousHtml: true }) // конвертируем в HTML
+ .use(rehypeRaw) // разрешаем raw HTML
+ .use(rehypeStringify) // сериализуем в строку
+ .process(matterResult.content || '');
+
+ const contentHtml = processedContent.toString();
- return {
- slug,
- contentHtml,
- title: matterResult.data.title,
- date: matterResult.data.date,
- tags: matterResult.data.tags || [],
- description: matterResult.data.description || '',
- };
+ return {
+ slug,
+ contentHtml,
+ title: matterResult.data.title || 'Без названия',
+ date: matterResult.data.date || new Date().toISOString().split('T')[0],
+ tags: matterResult.data.tags || [],
+ description: matterResult.data.description || '',
+ };
+ } catch (error) {
+ console.error(`Ошибка при загрузке поста ${slug}:`, error);
+ return null;
+ }
}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 2fd1d48..08c7f41 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,8 +14,15 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
+ "rehype-raw": "^7.0.0",
+ "rehype-sanitize": "^6.0.0",
+ "rehype-stringify": "^10.0.1",
"remark": "^15.0.1",
- "remark-html": "^16.0.1"
+ "remark-gfm": "^4.0.1",
+ "remark-html": "^16.0.1",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.1.2",
+ "unified": "^11.0.5"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
@@ -2201,6 +2208,18 @@
"node": ">=10.13.0"
}
},
+ "node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/es-abstract": {
"version": "1.23.9",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz",
@@ -3297,6 +3316,64 @@
"node": ">= 0.4"
}
},
+ "node_modules/hast-util-from-parse5": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
+ "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "devlop": "^1.0.0",
+ "hastscript": "^9.0.0",
+ "property-information": "^7.0.0",
+ "vfile": "^6.0.0",
+ "vfile-location": "^5.0.0",
+ "web-namespaces": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-parse-selector": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz",
+ "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-raw": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz",
+ "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "hast-util-from-parse5": "^8.0.0",
+ "hast-util-to-parse5": "^8.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "parse5": "^7.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0",
+ "web-namespaces": "^2.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/hast-util-sanitize": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-5.0.2.tgz",
@@ -3335,6 +3412,25 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/hast-util-to-parse5": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz",
+ "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "web-namespaces": "^2.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/hast-util-whitespace": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
@@ -3348,6 +3444,23 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/hastscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz",
+ "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-parse-selector": "^4.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/html-void-elements": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
@@ -4276,6 +4389,16 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/markdown-table": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
+ "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -4286,6 +4409,34 @@
"node": ">= 0.4"
}
},
+ "node_modules/mdast-util-find-and-replace": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
+ "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "escape-string-regexp": "^5.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/mdast-util-from-markdown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
@@ -4310,6 +4461,107 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/mdast-util-gfm": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
+ "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-gfm-autolink-literal": "^2.0.0",
+ "mdast-util-gfm-footnote": "^2.0.0",
+ "mdast-util-gfm-strikethrough": "^2.0.0",
+ "mdast-util-gfm-table": "^2.0.0",
+ "mdast-util-gfm-task-list-item": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-autolink-literal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
+ "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-find-and-replace": "^3.0.0",
+ "micromark-util-character": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-strikethrough": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
+ "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
+ "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "markdown-table": "^3.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-task-list-item": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
+ "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/mdast-util-phrasing": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
@@ -4458,6 +4710,127 @@
"micromark-util-types": "^2.0.0"
}
},
+ "node_modules/micromark-extension-gfm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
+ "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-extension-gfm-autolink-literal": "^2.0.0",
+ "micromark-extension-gfm-footnote": "^2.0.0",
+ "micromark-extension-gfm-strikethrough": "^2.0.0",
+ "micromark-extension-gfm-table": "^2.0.0",
+ "micromark-extension-gfm-tagfilter": "^2.0.0",
+ "micromark-extension-gfm-task-list-item": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-autolink-literal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
+ "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-strikethrough": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
+ "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-table": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
+ "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-tagfilter": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
+ "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-task-list-item": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
+ "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/micromark-factory-destination": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
@@ -5184,6 +5557,18 @@
"node": ">=6"
}
},
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -5426,6 +5811,50 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/rehype-raw": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
+ "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-raw": "^9.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-sanitize": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-sanitize/-/rehype-sanitize-6.0.0.tgz",
+ "integrity": "sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-sanitize": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-stringify": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz",
+ "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-to-html": "^9.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark": {
"version": "15.0.1",
"resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz",
@@ -5442,6 +5871,24 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/remark-gfm": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
+ "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-gfm": "^3.0.0",
+ "micromark-extension-gfm": "^3.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-stringify": "^11.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark-html": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/remark-html/-/remark-html-16.0.1.tgz",
@@ -5475,6 +5922,23 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/remark-rehype": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
+ "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark-stringify": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
@@ -6483,6 +6947,20 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/vfile-location": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz",
+ "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/vfile-message": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
@@ -6497,6 +6975,16 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/web-namespaces": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
+ "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 08b3052..d33dd6f 100644
--- a/package.json
+++ b/package.json
@@ -15,8 +15,15 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
+ "rehype-raw": "^7.0.0",
+ "rehype-sanitize": "^6.0.0",
+ "rehype-stringify": "^10.0.1",
"remark": "^15.0.1",
- "remark-html": "^16.0.1"
+ "remark-gfm": "^4.0.1",
+ "remark-html": "^16.0.1",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.1.2",
+ "unified": "^11.0.5"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
diff --git a/posts/styles.md b/posts/styles.md
new file mode 100644
index 0000000..c3f94c4
--- /dev/null
+++ b/posts/styles.md
@@ -0,0 +1,131 @@
+---
+title: "Тест Markdown разметки"
+date: "2024-12-22"
+tags: ["test", "markdown"]
+description: "Тестирование поддержки таблиц и списков в Markdown"
+---
+
+# Тест Markdown разметки
+
+## Списки
+
+### Ненумерованный список
+- Первый пункт
+- Второй пункт
+ - Вложенный пункт 1
+ - Вложенный пункт 2
+- Третий пункт
+
+### Нумерованный список
+1. Первый пункт
+2. Второй пункт
+ 1. Вложенный пункт 1
+ 2. Вложенный пункт 2
+3. Третий пункт
+
+### Список задач
+- [x] Сделать поддержку таблиц
+- [ ] Добавить подсветку синтаксиса
+- [ ] Настроить стили
+
+## Таблицы
+
+### Простая таблица
+| Заголовок 1 | Заголовок 2 | Заголовок 3 |
+|-------------|-------------|-------------|
+| Ячейка 1 | Ячейка 2 | Ячейка 3 |
+| Ячейка 4 | Ячейка 5 | Ячейка 6 |
+
+### Таблица с выравниванием
+| Левый | По центру | Правый | Числа |
+|:------|:---------:|-------:|------:|
+| текст | текст | текст | 1000 |
+| данные| данные | данные| 200 |
+| еще | еще | еще | 3 |
+
+### Сложная таблица
+| Процессор | Архитектура | Частота | Ядра |
+|-----------|-------------|---------|------|
+| Cortex-A78 | ARM | 2.8 GHz | 8 |
+| Rocket | RISC-V | 1.5 GHz | 4 |
+| x86-64 | x86 | 3.5 GHz | 16 |
+
+## Код
+
+```python
+def hello():
+ print("Hello World")
+
+def calculate(a, b):
+ return a + b
+```
+
+
+```cpp
+#include
+#include
+
+using namespace std;
+
+void quicksort(char *items, int len);
+void qs(char *items, int left, int right);
+
+int main() {
+ setlocale(LC_ALL, "ru_RU.UTF-8");
+ char str[] = "jfmckldoelazlkper";
+ int i;
+
+ cout << "Исходный массив: " << str << "\n";
+ quicksort(str, strlen(str));
+
+ cout << "Отсортированный массив: " << str << "\n";
+ return 0;
+}
+
+void quicksort(char *items, int len)
+{
+ qs(items, 0, len-1);
+}
+
+void qs(char *items, int left, int right)
+{
+ int i, j;
+ char x, y;
+ i = left, j = right;
+ x = items[( left+right) / 2];
+ do {
+ while ((items[i] < x) && (i < right)) i++;
+ while ((x < items[j]) && (j > left)) j--;
+
+ if (i <= j) {
+ y = items[i];
+ items[i] = items[j];
+ items[j] = y;
+ i++; j--;
+ }
+ } while (i <= j);
+
+ if(left < j) qs(items, left, j);
+ if(i < right) qs(items, i, right);
+}
+```
+
+## Цитата
+
+> Это важная цитата из статьи о RISC-V
+> Вторая строка цитаты
+
+## Ссылки и изображения
+
+[Ссылка на RISC-V](https://riscv.org)
+
+
+
+## Горизонтальная линия
+
+---
+
+**RISC-V** (произносится «риск-файв») — это открытая и свободная архитектура набора команд (Instruction Set Architecture, ISA) для процессоров. В отличие от закрытых архитектур x86 (Intel, AMD) или ARM, спецификации RISC-V находятся в открытом доступе, а их использование не требует выплаты лицензионных отчислений. Это не конкретный процессор, а стандарт, на основе которого любая компания или исследовательская группа может разработать собственное ядро.
+
+В условиях современных технологических ограничений RISC-V перестал быть просто академическим проектом и превратился в стратегическую возможность для создания независимой технологической базы.
+