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) + +![Изображение](https://riscv.org/wp-content/uploads/2025/12/breker-sat.jpg) + +## Горизонтальная линия + +--- + +**RISC-V** (произносится «риск-файв») — это открытая и свободная архитектура набора команд (Instruction Set Architecture, ISA) для процессоров. В отличие от закрытых архитектур x86 (Intel, AMD) или ARM, спецификации RISC-V находятся в открытом доступе, а их использование не требует выплаты лицензионных отчислений. Это не конкретный процессор, а стандарт, на основе которого любая компания или исследовательская группа может разработать собственное ядро. + +В условиях современных технологических ограничений RISC-V перестал быть просто академическим проектом и превратился в стратегическую возможность для создания независимой технологической базы. +