├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── docker-image.yml │ ├── submit_urls.yml │ └── sync-neodb-data.yml ├── .gitignore ├── .npmrc ├── .vscode ├── extensions.json ├── settings.json └── typescript-react.code-snippets ├── CONTRIBUTING.md ├── FlowChart.md ├── LICENSE ├── Project.md ├── README.md ├── apps └── gkBlog │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── next-env.d.ts │ ├── next-sitemap.config.js │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.js │ ├── prisma │ └── schema.prisma │ ├── public │ ├── 17dec345aa579ceab23086620028a420.txt │ ├── 9a692f6e78de4cee9cf96c9c373a6b16.txt │ ├── ByteDanceVerify.html │ ├── assets │ │ ├── data │ │ │ ├── essays.json │ │ │ └── neodb │ │ │ │ ├── movie.json │ │ │ │ └── movie_details.json │ │ ├── emojis │ │ │ ├── astonished-face-animated.png │ │ │ ├── astonished-face.png │ │ │ ├── clapping-hands-animated.png │ │ │ ├── clapping-hands.png │ │ │ ├── face-with-monocle-animated.png │ │ │ ├── face-with-monocle.png │ │ │ ├── love-you-gesture.png │ │ │ ├── nerd-face.png │ │ │ └── star-struck.png │ │ ├── images │ │ │ ├── coverImage.png │ │ │ ├── model.glb │ │ │ ├── neodb │ │ │ │ └── cover │ │ │ │ │ ├── 026f727af7-d878-42d4-a53a-c464d0c0ecb4.jpg │ │ │ │ │ ├── 123e49a39f-f47a-48ba-8a8e-5db39e1d5353.jpg │ │ │ │ │ ├── 130cd91e04-5dc9-4536-95fe-538ef04d9490.jpg │ │ │ │ │ ├── 13147ff4ca-6cbb-411e-b76d-6c6a9b1a2687.jpg │ │ │ │ │ ├── 1328a0081e-46a9-4da3-a771-9043268a2e7c.jpg │ │ │ │ │ ├── 133604f9b2-b434-4aa8-92c0-e8f88336e4db.jpg │ │ │ │ │ ├── 1342d14337-0e7e-42e2-b3f5-d92f0903d33f.jpg │ │ │ │ │ ├── 135717365f-c912-4679-9f01-b05fcca43095.jpg │ │ │ │ │ ├── 13736687a2-6a78-4c2a-866e-17a5ee23b756.jpg │ │ │ │ │ ├── 139b340d18-2966-4ce6-b926-54694c944079.jpg │ │ │ │ │ ├── 13a47e43fe-9ea3-43ca-a9e2-808483a6598b.jpg │ │ │ │ │ ├── 13b4e0e03c-c438-4b1c-962d-839a489ecec1.jpg │ │ │ │ │ ├── 13bef5e4f5-105e-436d-b580-7f223a167cb7.jpg │ │ │ │ │ ├── 13c80ca032-f642-4ed2-86c0-94704a240cf0.jpg │ │ │ │ │ ├── 13e99a10f0-76d0-4038-b4f6-d02a2ed7a383.jpg │ │ │ │ │ ├── 13ebc0ea8c-ae2c-4329-93be-c1970a37e20d.jpg │ │ │ │ │ ├── 13eda1111e-c4fc-4f0e-99b7-fff0a4e5022f.jpg │ │ │ │ │ ├── 13f6344886-9243-4924-9257-fb2ad9ed90ce.jpg │ │ │ │ │ ├── 1401818191-c040-4bd0-b8b5-b1342ea2195d.jpg │ │ │ │ │ ├── 144ed58222-783e-4bf5-9563-399c6f0c2b3d.jpg │ │ │ │ │ ├── 14a4cfa306-8e52-4981-b49a-c00435db6831.jpg │ │ │ │ │ ├── 14bd0a7d78-fda5-47f9-9d6c-8fbf573ce8c3.jpg │ │ │ │ │ ├── 14e442937b-efaf-4a42-99b9-4f867d2250f2.jpg │ │ │ │ │ ├── 14e5043627-8e2d-43c0-a6cc-a8e05d8115d3.jpg │ │ │ │ │ ├── 1515210a18-1e0a-4ee2-a5a7-e2c5edb6ecb5.jpg │ │ │ │ │ ├── 152bbd9498-8051-4931-afbf-4eddc7f9150c.jpg │ │ │ │ │ ├── 152d9fd739-6ff0-4b5f-989f-ca5bf295ac36.jpg │ │ │ │ │ ├── 153bc2857e-c61b-49c9-a30a-e5cf062e87f7.jpg │ │ │ │ │ ├── 153dcbfdda-18ce-4e61-9e13-1345dda39ccd.jpg │ │ │ │ │ ├── 153ebbeccc-013f-4682-b8d1-18e9a3a8129a.jpg │ │ │ │ │ ├── 15441d0fe9-fa9b-4fb8-b41c-16f4b4d500ea.jpg │ │ │ │ │ ├── 154887e57f-7ffe-4981-80d8-3daa586ff0ee.jpg │ │ │ │ │ ├── 154ff20ed0-6fd6-4eae-abad-0e6f970b885a.jpg │ │ │ │ │ ├── 15568d4a23-5ef0-4cba-96f4-487d3babbaa8.jpg │ │ │ │ │ ├── 15600f9e3e-d6f3-4d27-b24f-2cff4992f27c.jpg │ │ │ │ │ ├── 15636422b6-4f36-4fb0-8e56-6577c08fc4c4.jpg │ │ │ │ │ ├── 1568906669-00c1-4f62-a7b2-24068159e264.jpg │ │ │ │ │ ├── 156a81ad17-6f6c-4533-b1ab-432d0c87a390.jpg │ │ │ │ │ ├── 15707c4ef9-400b-4c7c-8ff0-df74d3fef33c.jpg │ │ │ │ │ ├── 1578d53bc3-8bbe-4116-83e9-f5c91fc0d3f9.jpg │ │ │ │ │ ├── 157e882f74-65b0-4c11-88a8-6f1a103b5954.jpg │ │ │ │ │ ├── 157eee4ad4-84de-4e92-8fc4-aa4ff42da48f.jpg │ │ │ │ │ ├── 15881fc78e-fd01-4cab-aa49-030c330e48dd.jpg │ │ │ │ │ ├── 158cac42e4-74fb-472f-afd5-78984be19315.jpg │ │ │ │ │ ├── 159008bab2-fd56-48b7-b553-f0a4d76eef0a.jpg │ │ │ │ │ ├── 15a5cb7008-acae-4a3b-8d5d-581355037dcf.jpg │ │ │ │ │ ├── 15b5fa8d7e-ad33-4736-a9db-f39c6613b08b.jpg │ │ │ │ │ ├── 15b71e1380-9ed2-4ac2-bf49-d2e2b3c92156.jpg │ │ │ │ │ ├── 15cd943477-b70e-44fa-b85d-86869783bdc2.jpg │ │ │ │ │ ├── 15d0883f9f-f849-4054-9b49-e021f380f73b.jpg │ │ │ │ │ ├── 15d514432e-a535-493f-a4b6-c4b86e9f9916.jpg │ │ │ │ │ ├── 15dcceff27-b10e-4149-9673-022b83f75410.jpg │ │ │ │ │ ├── 15e065e907-4ace-4646-9fc5-fa2116705698.jpg │ │ │ │ │ ├── 15e6ca679d-2d3d-4e6e-86c6-0e8580f01846.jpg │ │ │ │ │ ├── 15e8c2720f-1bf2-4a9c-927f-6c220e918526.jpg │ │ │ │ │ ├── 15e9868a92-5dc6-4645-a44e-30031f4967a5.jpg │ │ │ │ │ ├── 15eab988ed-8d95-4b0c-a833-6ab27274ea27.jpg │ │ │ │ │ ├── 15ee7eadd5-aa1b-4a17-8418-25990a29d337.jpg │ │ │ │ │ ├── 15f3e99e45-6b26-4747-a8f2-09f292b8f332.jpg │ │ │ │ │ ├── 15f3ec6730-4ef7-47c0-8af4-9e640d573cd8.jpg │ │ │ │ │ ├── 15f440c10b-6210-43ff-860d-907297628e18.jpg │ │ │ │ │ ├── 1618bc6aa2-1e56-4523-96a0-17c992c159e5.jpg │ │ │ │ │ ├── 161baa0173-8a4d-476f-8c9a-b29c9c8ee4b6.jpg │ │ │ │ │ ├── 162fe81dd5-242d-444f-9127-95f6ee31edb7.jpg │ │ │ │ │ ├── 1651a0aaab-19d2-4fde-8f39-409de4e45aac.jpg │ │ │ │ │ ├── 165f79bf08-ac00-4a60-ac1e-7b3c194aa8a2.jpg │ │ │ │ │ ├── 1663bcc4de-a15c-4d50-a3ab-13f9736bd689.jpg │ │ │ │ │ ├── 16770e2bbe-94c9-42dc-a6cd-5aea772f9e39.jpg │ │ │ │ │ ├── 16b10d7e9f-4a2a-471e-8e98-8acc0054ddda.jpg │ │ │ │ │ ├── 1721fa6acb-b578-48e0-9ff3-c192fc520d90.jpg │ │ │ │ │ ├── 180d0ea039-6cd0-4fb3-9c16-486051371ad7.jpg │ │ │ │ │ ├── 26a4fa45-6953-49f9-b8cf-35f7ca58275b.jpg │ │ │ │ │ ├── 292dd0f3ac-6aa4-4c39-a08d-ee732890b21f.jpg │ │ │ │ │ ├── 2e0c2aa6-8ee5-417b-bbc7-104090798a8e.jpg │ │ │ │ │ ├── 31bc2bb5-7210-4ed0-891c-520075ac36e7.webp │ │ │ │ │ ├── 4a236368-8343-40e3-bccf-a196a08f2c52.webp │ │ │ │ │ ├── 4cd9e07d-ff81-4e63-8e16-ac2cd5f81bd7.jpg │ │ │ │ │ ├── 837260ea-0e8b-4952-9cfc-5e06f0d42748.webp │ │ │ │ │ ├── 8722487d-911a-4260-8589-4ea0626eb134.jpg │ │ │ │ │ ├── 896338d8-5109-4667-aec5-6f30a53c004e.jpg │ │ │ │ │ ├── 8be68de4-0d12-4460-bd87-0788af9908cd.jpg │ │ │ │ │ ├── 918b1177-ef27-4f62-853c-d95b82eca6b9.webp │ │ │ │ │ ├── 91aef100-a4ff-4866-8e5e-a6b1af1bc754.jpg │ │ │ │ │ ├── 9abe26d8-4ddb-4e25-987e-a994d72488eb.jpg │ │ │ │ │ ├── 9b8c9c00-d17c-4de2-9dc4-d7d8eba26a3c.jpg │ │ │ │ │ ├── 9fcaf1da-6927-4d94-b5d2-da74ce9e5414.webp │ │ │ │ │ ├── ab916129-e95f-47a3-be39-d0218f9e7f76.jpg │ │ │ │ │ ├── b05acf62-c9ec-4f55-89e0-76457bbcb545.jpg │ │ │ │ │ ├── b41c6631-bb51-4bdf-aa3e-06b7c0fc8fd8.webp │ │ │ │ │ ├── b78f8f40-3910-479a-814d-e05f451f5ca8.webp │ │ │ │ │ ├── c6b6a72c-2a26-487c-9c3f-54c23cf4ca9e.webp │ │ │ │ │ ├── d801edae-d1f3-499d-8a73-123ce9669780.jpg │ │ │ │ │ ├── e1a4d84a-c39d-4094-8b75-b57f2eb31ce0.jpg │ │ │ │ │ ├── e7886af0-9e2c-46f5-a079-90f4d94d0803.jpg │ │ │ │ │ ├── eb0c8821-ae0e-4438-b629-a2c769c161cb.jpg │ │ │ │ │ ├── ee6dbb95-0151-44de-8734-6cf36fe511f1.jpg │ │ │ │ │ └── f929217a-3c36-4a6e-8885-64fc07476424.webp │ │ │ ├── og-image.png │ │ │ └── qlAD.webp │ │ └── sounds │ │ │ ├── click.mp3 │ │ │ ├── close.mp3 │ │ │ ├── lightoff.mp3 │ │ │ ├── lighton.mp3 │ │ │ ├── open.mp3 │ │ │ └── pop_clean.flac │ ├── baidu_verify_codeva-wXcFRrXTHy.html │ ├── favicon.ico │ ├── googlee46587067af4c10b.html │ ├── shenma-site-verification.txt │ └── sogousiteverification.txt │ ├── scripts │ ├── movie_details.py │ └── submit_urls.sh │ ├── src │ ├── assets │ │ └── fonts │ │ │ ├── PlusJakartaSans-ExtraBold.ttf │ │ │ ├── PlusJakartaSans-Regular.ttf │ │ │ └── katex │ │ │ ├── KaTeX_AMS-Regular.ttf │ │ │ ├── KaTeX_AMS-Regular.woff │ │ │ ├── KaTeX_AMS-Regular.woff2 │ │ │ ├── KaTeX_Caligraphic-Bold.ttf │ │ │ ├── KaTeX_Caligraphic-Bold.woff │ │ │ ├── KaTeX_Caligraphic-Bold.woff2 │ │ │ ├── KaTeX_Caligraphic-Regular.ttf │ │ │ ├── KaTeX_Caligraphic-Regular.woff │ │ │ ├── KaTeX_Caligraphic-Regular.woff2 │ │ │ ├── KaTeX_Fraktur-Bold.ttf │ │ │ ├── KaTeX_Fraktur-Bold.woff │ │ │ ├── KaTeX_Fraktur-Bold.woff2 │ │ │ ├── KaTeX_Fraktur-Regular.ttf │ │ │ ├── KaTeX_Fraktur-Regular.woff │ │ │ ├── KaTeX_Fraktur-Regular.woff2 │ │ │ ├── KaTeX_Main-Bold.ttf │ │ │ ├── KaTeX_Main-Bold.woff │ │ │ ├── KaTeX_Main-Bold.woff2 │ │ │ ├── KaTeX_Main-BoldItalic.ttf │ │ │ ├── KaTeX_Main-BoldItalic.woff │ │ │ ├── KaTeX_Main-BoldItalic.woff2 │ │ │ ├── KaTeX_Main-Italic.ttf │ │ │ ├── KaTeX_Main-Italic.woff │ │ │ ├── KaTeX_Main-Italic.woff2 │ │ │ ├── KaTeX_Main-Regular.ttf │ │ │ ├── KaTeX_Main-Regular.woff │ │ │ ├── KaTeX_Main-Regular.woff2 │ │ │ ├── KaTeX_Math-BoldItalic.ttf │ │ │ ├── KaTeX_Math-BoldItalic.woff │ │ │ ├── KaTeX_Math-BoldItalic.woff2 │ │ │ ├── KaTeX_Math-Italic.ttf │ │ │ ├── KaTeX_Math-Italic.woff │ │ │ ├── KaTeX_Math-Italic.woff2 │ │ │ ├── KaTeX_SansSerif-Bold.ttf │ │ │ ├── KaTeX_SansSerif-Bold.woff │ │ │ ├── KaTeX_SansSerif-Bold.woff2 │ │ │ ├── KaTeX_SansSerif-Italic.ttf │ │ │ ├── KaTeX_SansSerif-Italic.woff │ │ │ ├── KaTeX_SansSerif-Italic.woff2 │ │ │ ├── KaTeX_SansSerif-Regular.ttf │ │ │ ├── KaTeX_SansSerif-Regular.woff │ │ │ ├── KaTeX_SansSerif-Regular.woff2 │ │ │ ├── KaTeX_Script-Regular.ttf │ │ │ ├── KaTeX_Script-Regular.woff │ │ │ ├── KaTeX_Script-Regular.woff2 │ │ │ ├── KaTeX_Size1-Regular.ttf │ │ │ ├── KaTeX_Size1-Regular.woff │ │ │ ├── KaTeX_Size1-Regular.woff2 │ │ │ ├── KaTeX_Size2-Regular.ttf │ │ │ ├── KaTeX_Size2-Regular.woff │ │ │ ├── KaTeX_Size2-Regular.woff2 │ │ │ ├── KaTeX_Size3-Regular.ttf │ │ │ ├── KaTeX_Size3-Regular.woff │ │ │ ├── KaTeX_Size3-Regular.woff2 │ │ │ ├── KaTeX_Size4-Regular.ttf │ │ │ ├── KaTeX_Size4-Regular.woff │ │ │ ├── KaTeX_Size4-Regular.woff2 │ │ │ ├── KaTeX_Typewriter-Regular.ttf │ │ │ ├── KaTeX_Typewriter-Regular.woff │ │ │ └── KaTeX_Typewriter-Regular.woff2 │ ├── components │ │ ├── ActionCenter.tsx │ │ ├── Activity.tsx │ │ ├── CountUp.tsx │ │ ├── EmojiReaction.tsx │ │ ├── Footer.tsx │ │ ├── Icons.tsx │ │ ├── IconsFile.tsx │ │ ├── InsightButton.tsx │ │ ├── Kbd.tsx │ │ ├── Logo.tsx │ │ ├── Navigation.tsx │ │ ├── NewPosts.tsx │ │ ├── PageHeader.tsx │ │ ├── Portal.tsx │ │ ├── QuickAccess.tsx │ │ ├── Reactions.tsx │ │ ├── ScriptLoader.tsx │ │ ├── ShareButton.tsx │ │ ├── Shortcuts.tsx │ │ ├── TableOfContents.tsx │ │ ├── TipShortcuts.tsx │ │ ├── Toast.tsx │ │ ├── Toaster.tsx │ │ ├── TwikooComments.tsx │ │ ├── UserProfileGrid.tsx │ │ ├── analytics │ │ │ ├── BaiduAnalytics.tsx │ │ │ ├── ClarityAnalytics.tsx │ │ │ └── GoogleAnalytics.tsx │ │ ├── layouts │ │ │ ├── Root.tsx │ │ │ ├── WithNavigationFooter.tsx │ │ │ ├── WithReactions.tsx │ │ │ ├── WithTableOfContents.tsx │ │ │ └── WithTableOfContentsMock.tsx │ │ ├── mdx │ │ │ ├── AccentDemo.tsx │ │ │ ├── Callout.tsx │ │ │ ├── Code.tsx │ │ │ ├── CodeGroup.tsx │ │ │ ├── Diff.tsx │ │ │ ├── Draft.tsx │ │ │ ├── Image.tsx │ │ │ ├── ImageSensitive.tsx │ │ │ ├── InlineHighlight.tsx │ │ │ ├── Labels.tsx │ │ │ ├── Link.tsx │ │ │ ├── MDXExample.tsx │ │ │ ├── Stack.tsx │ │ │ ├── TIL.tsx │ │ │ ├── VideoEmbed.tsx │ │ │ └── custom-components │ │ │ │ ├── Heading.tsx │ │ │ │ ├── Hr.tsx │ │ │ │ ├── Link.tsx │ │ │ │ ├── Pre.tsx │ │ │ │ ├── Table.tsx │ │ │ │ └── index.tsx │ │ ├── meta │ │ │ ├── Head.tsx │ │ │ └── OgImages.tsx │ │ ├── navigations │ │ │ ├── NavIcon.tsx │ │ │ ├── NavIconQuickAccess.tsx │ │ │ ├── NavLink.tsx │ │ │ ├── NavLinkDropdown.tsx │ │ │ ├── NavLinkExpanded.tsx │ │ │ ├── NavLogo.tsx │ │ │ └── SkipNavigation.tsx │ │ ├── sections │ │ │ ├── SectionButton.tsx │ │ │ ├── SectionContent.tsx │ │ │ └── SectionTitle.tsx │ │ ├── sidebar │ │ │ ├── Card.tsx │ │ │ └── Sidebar.tsx │ │ ├── stats │ │ │ ├── BarChart.tsx │ │ │ ├── Heatmap.tsx │ │ │ ├── PieChart.tsx │ │ │ └── TagCloud.tsx │ │ ├── ui │ │ │ ├── AvatarCircles.tsx │ │ │ ├── BlurFade.tsx │ │ │ └── Marquee.tsx │ │ └── wireframes │ │ │ ├── AppWindow.tsx │ │ │ ├── GitHub.tsx │ │ │ ├── Npm.tsx │ │ │ └── Skeletons.tsx │ ├── constants │ │ └── app.ts │ ├── contents-layouts │ │ ├── Page.tsx │ │ ├── PageWithMDX.tsx │ │ ├── Post │ │ │ ├── PostFooter.tsx │ │ │ ├── PostMeta.tsx │ │ │ └── index.tsx │ │ └── Project │ │ │ ├── ProjectFooter.tsx │ │ │ ├── ProjectMeta.tsx │ │ │ └── index.tsx │ ├── contents │ │ ├── 404.tsx │ │ ├── 500.tsx │ │ ├── TIL │ │ │ ├── Contents.mdx │ │ │ └── index.tsx │ │ ├── album │ │ │ ├── ExternalImages.tsx │ │ │ └── index.tsx │ │ ├── blog │ │ │ ├── PostPreview.tsx │ │ │ └── index.tsx │ │ ├── essay │ │ │ └── index.tsx │ │ ├── feedback │ │ │ └── index.tsx │ │ ├── index │ │ │ ├── Cards │ │ │ │ └── TodoItem.tsx │ │ │ ├── CleanIntuitive.tsx │ │ │ ├── DetailOriented.tsx │ │ │ ├── FeaturedCard.tsx │ │ │ ├── Header │ │ │ │ ├── HeaderCta.tsx │ │ │ │ ├── HeaderImage.tsx │ │ │ │ ├── HeaderImageAnimation.tsx │ │ │ │ ├── HeaderTechStack.tsx │ │ │ │ ├── HeaderTitle.tsx │ │ │ │ └── index.tsx │ │ │ ├── PrettyOptimized.tsx │ │ │ ├── Quote01.tsx │ │ │ └── index.tsx │ │ ├── links │ │ │ ├── Disclaimer.tsx │ │ │ ├── Websites.tsx │ │ │ └── index.tsx │ │ ├── media │ │ │ └── index.tsx │ │ ├── stats │ │ │ └── index.tsx │ │ └── update │ │ │ ├── Contents.mdx │ │ │ ├── ReleaseNote.mdx │ │ │ ├── images │ │ │ └── og-image.png │ │ │ └── index.tsx │ ├── helpers │ │ ├── api.ts │ │ ├── date.ts │ │ ├── mdx.tsx │ │ ├── page.ts │ │ ├── post.ts │ │ ├── server.ts │ │ └── url.ts │ ├── hooks │ │ ├── useAnimateContent.ts │ │ ├── useContentActivity.ts │ │ ├── useContentMeta.ts │ │ ├── useCurrentUrl.ts │ │ ├── useFocusMode.ts │ │ ├── useGlobal.ts │ │ ├── useInsight.ts │ │ ├── useNewPosts.ts │ │ ├── useOnScroll.ts │ │ ├── useScrollSpy.ts │ │ ├── useShortcut.ts │ │ └── useTheme.ts │ ├── lib │ │ ├── meta.ts │ │ ├── posts.ts │ │ ├── rss.ts │ │ └── utils.ts │ ├── pages │ │ ├── 404.tsx │ │ ├── 500.tsx │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ ├── about-me.mdx │ │ ├── album.tsx │ │ ├── api │ │ │ ├── activity │ │ │ │ └── index.ts │ │ │ ├── categories.tsx │ │ │ ├── content │ │ │ │ ├── [slug].ts │ │ │ │ ├── index.ts │ │ │ │ └── latest.ts │ │ │ ├── og-page.tsx │ │ │ ├── og-post.tsx │ │ │ ├── reactions │ │ │ │ └── [slug].ts │ │ │ ├── shares │ │ │ │ └── [slug].ts │ │ │ ├── tags.tsx │ │ │ └── views │ │ │ │ └── [slug].ts │ │ ├── blog.tsx │ │ ├── blog │ │ │ ├── algorithm-00 │ │ │ │ └── index.mdx │ │ │ ├── anki-deck-options │ │ │ │ └── index.mdx │ │ │ ├── anki-introduction │ │ │ │ └── index.mdx │ │ │ ├── beautify-twikoo │ │ │ │ └── index.mdx │ │ │ ├── build-enchilada-kernelsu │ │ │ │ └── index.mdx │ │ │ ├── building-apt-repository │ │ │ │ └── index.mdx │ │ │ ├── c-helloworld │ │ │ │ └── index.mdx │ │ │ ├── category │ │ │ │ └── [category].tsx │ │ │ ├── chemical-reaction-rules │ │ │ │ ├── index.mdx │ │ │ │ └── periodic-table.tsx │ │ │ ├── choose-the-right-license │ │ │ │ └── index.mdx │ │ │ ├── debian-btrfs-subvolumes │ │ │ │ └── index.mdx │ │ │ ├── gentoo-bak │ │ │ │ └── index.mdx │ │ │ ├── github-flow │ │ │ │ └── index.mdx │ │ │ ├── how-i-built-my-blog │ │ │ │ └── index.mdx │ │ │ ├── html-intro │ │ │ │ └── index.mdx │ │ │ ├── learn-css │ │ │ │ └── index.mdx │ │ │ ├── learn-git │ │ │ │ └── index.mdx │ │ │ ├── link-genetic-and-meiosis │ │ │ │ ├── genotype-calculator.tsx │ │ │ │ ├── hybrid-calculator.tsx │ │ │ │ └── index.mdx │ │ │ ├── markdown-introduction │ │ │ │ └── index.mdx │ │ │ ├── onedrive-directory-index │ │ │ │ └── index.mdx │ │ │ ├── pixelexperience-optimize │ │ │ │ ├── VariableFontTester.tsx │ │ │ │ └── index.mdx │ │ │ ├── probability-calculation-formula │ │ │ │ └── index.mdx │ │ │ ├── reset-partition-subvolume │ │ │ │ └── index.mdx │ │ │ ├── self-built-docker-mailserver │ │ │ │ └── index.mdx │ │ │ ├── set-notes-summary │ │ │ │ └── index.mdx │ │ │ ├── stats-page │ │ │ │ └── index.mdx │ │ │ ├── submit-baidu-index │ │ │ │ └── index.mdx │ │ │ ├── tag │ │ │ │ └── [tag].tsx │ │ │ ├── the-2023-retrospective │ │ │ │ └── index.mdx │ │ │ ├── use-sound-introduction │ │ │ │ └── index.mdx │ │ │ ├── webmaster-guidelines │ │ │ │ └── index.mdx │ │ │ └── why-a-is-65 │ │ │ │ └── index.mdx │ │ ├── cookies.mdx │ │ ├── copyright.mdx │ │ ├── credits.mdx │ │ ├── essay.tsx │ │ ├── feedback.tsx │ │ ├── index.tsx │ │ ├── links.tsx │ │ ├── media.tsx │ │ ├── privacy-policy.mdx │ │ ├── rss.xml.tsx │ │ ├── shortcodes.mdx │ │ ├── stats.tsx │ │ ├── today-i-learned.tsx │ │ └── update.tsx │ ├── providers │ │ ├── ColorAccentProvider.tsx │ │ ├── FocusModeProvider.tsx │ │ ├── FramerMotionProvider.tsx │ │ ├── GlobalStateProvider.tsx │ │ └── index.tsx │ ├── styles │ │ ├── base.css │ │ ├── components.css │ │ ├── katex.css │ │ ├── main.css │ │ ├── mdx-components.css │ │ ├── mdx-contents.css │ │ ├── media.css │ │ ├── prism-colors.css │ │ ├── stats.css │ │ └── twikoo.css │ ├── types │ │ └── index.ts │ └── utils │ │ ├── dayjs.ts │ │ ├── fetcher.ts │ │ └── prisma.ts │ ├── tailwind.config.js │ └── tsconfig.json ├── docker-compose.yml ├── package.json ├── packages ├── eslint-config-next-typescript │ ├── index.js │ └── package.json ├── eslint-config-typescript │ ├── index.js │ └── package.json ├── rehype-plugins │ ├── .eslintrc.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── withCodeAttributes.ts │ │ └── withInlineHighlights.ts │ ├── tsconfig.json │ └── tsup.config.js ├── remark-plugins │ ├── .eslintrc.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── utils.ts │ │ ├── withFrontMatter.ts │ │ ├── withLayout.ts │ │ └── withStrict.ts │ ├── tsconfig.json │ └── tsup.config.js └── tsconfig │ ├── base.json │ ├── nextjs.json │ ├── package.json │ └── react-library.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── renovate.json └── turbo.json /.dockerignore: -------------------------------------------------------------------------------- 1 | dist 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # next.js 12 | .next/ 13 | out/ 14 | build 15 | .swc/ 16 | 17 | # misc 18 | .DS_Store 19 | *.pem 20 | *.tsbuildinfo 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # turbo 34 | .turbo 35 | 36 | # next-sitemap 37 | robots.txt 38 | sitemap.xml 39 | 40 | # prevent accidentally committing and pushing draft files/directories 41 | *((DRAFT))* 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | 34 | - Device: [e.g. iPhone6] 35 | - OS: [e.g. iOS8.1] 36 | - Browser [e.g. stock browser, safari] 37 | - Version [e.g. 22] 38 | 39 | **Additional context** 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Compose CI 2 | 3 | on: 4 | push: 5 | paths: 6 | - "apps/gkBlog/src/pages/blog/**/index.mdx" 7 | branches: 8 | - main 9 | 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Set up Docker 19 | uses: docker/setup-buildx-action@v3 20 | 21 | - name: Create .env.local file 22 | run: | 23 | mkdir -p apps/gkBlog 24 | echo "DATABASE_URL=${{ secrets.DATABASE_URL }}" >> apps/gkBlog/.env.local 25 | echo "SALT_IP_ADDRESS=${{ secrets.SALT_IP_ADDRESS }}" >> apps/gkBlog/.env.local 26 | echo "NEXT_PUBLIC_BAIDU_TONGJI=${{ secrets.NEXT_PUBLIC_BAIDU_TONGJI }}" >> apps/gkBlog/.env.local 27 | echo "NEXT_PUBLIC_GOOGLE_ID=${{ secrets.NEXT_PUBLIC_GOOGLE_ID }}" >> apps/gkBlog/.env.local 28 | echo "NEXT_PUBLIC_CLARITY_TAG_ID=${{ secrets.NEXT_PUBLIC_CLARITY_TAG_ID }}" >> apps/gkBlog/.env.local 29 | 30 | - name: Build and Push Docker Image with Docker Compose 31 | env: 32 | DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} 33 | DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} 34 | ALIYUN_REGISTRY: ${{ secrets.ALIYUN_REGISTRY }} 35 | run: | 36 | # 检查 Docker 版本 37 | docker version 38 | 39 | # 登录阿里云镜像仓库 40 | docker login --username=${DOCKER_USERNAME} --password=${DOCKER_PASSWORD} ${ALIYUN_REGISTRY} 41 | 42 | # 使用 Docker Compose 构建镜像 43 | docker compose -f docker-compose.yml build 44 | 45 | # 标记镜像 46 | docker tag gkblog:latest ${ALIYUN_REGISTRY}/docker-qladgk/gkblog:latest 47 | 48 | # 推送镜像到阿里云镜像仓库 49 | docker push ${ALIYUN_REGISTRY}/docker-qladgk/gkblog:latest 50 | -------------------------------------------------------------------------------- /.github/workflows/submit_urls.yml: -------------------------------------------------------------------------------- 1 | name: Submit URLs to Search Engines 2 | 3 | on: 4 | workflow_dispatch: # 手动触发 5 | schedule: 6 | # 每天北京时间早上 8 点运行(UTC 时间 00:00) 7 | - cron: "0 0 * * *" 8 | 9 | jobs: 10 | submit-urls: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out the repository 14 | uses: actions/checkout@v4 15 | 16 | - name: Make script executable 17 | run: chmod +x ./apps/gkBlog/scripts/submit_urls.sh 18 | 19 | - name: Submit URLs to Search Engines 20 | env: 21 | BAIDU_API_URL: ${{ secrets.BAIDU_API_URL }} 22 | BING_API_KEY: ${{ secrets.BING_API_KEY }} 23 | run: ./apps/gkBlog/scripts/submit_urls.sh 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # next.js 12 | .next/ 13 | out/ 14 | build 15 | .swc/ 16 | 17 | # misc 18 | .DS_Store 19 | *.pem 20 | *.tsbuildinfo 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # turbo 35 | .turbo 36 | 37 | # next-sitemap 38 | robots.txt 39 | sitemap.xml 40 | 41 | # prevent accidentally committing and pushing draft files/directories 42 | *((DRAFT))* 43 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers=true 2 | enable-pre-post-scripts=true 3 | engine-strict=true 4 | node-version=18.19.95 5 | public-hoist-pattern[]=*prisma* 6 | public-hoist-pattern[]=*eslint* 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "esbenp.prettier-vscode", 4 | "editorconfig.editorconfig", 5 | "dbaeumer.vscode-eslint", 6 | "bradlc.vscode-tailwindcss", 7 | "csstools.postcss", 8 | "prisma.prisma" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll": "explicit" 5 | }, 6 | "editor.defaultFormatter": "esbenp.prettier-vscode", 7 | "files.associations": { 8 | "*.css": "postcss" 9 | }, 10 | "files.exclude": { 11 | "**/.next": true, 12 | "**/.turbo": true, 13 | "**/node_modules": true 14 | }, 15 | "[shellscript]": { 16 | "editor.defaultFormatter": "foxundermoon.shell-format" 17 | }, 18 | "[dotenv]": { 19 | "editor.defaultFormatter": "foxundermoon.shell-format" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.vscode/typescript-react.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "Element with clsx": { 3 | "prefix": "cl", 4 | "body": ["<${1:div} className={clsx('$2')}>$0"], 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## 设置项目 2 | 3 | 以下步骤将帮助您启动并运行此代码库并做出贡献: 4 | 5 | 1. 复制代码库(点击此页面右上角的“Fork”按钮) 6 | 2. 克隆您的代码库到本地 7 | 8 | ```bash 9 | git clone https://github.com//gkBlog.git 10 | cd gkBlog 11 | ``` 12 | 13 | 3. 运行 `pnpm install` 安装所有依赖项和软件包 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 qlAD 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /apps/gkBlog/.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL = your-database-connection-string 2 | SALT_IP_ADDRESS = super-secret 3 | NEXT_PUBLIC_BAIDU_TONGJI = xxxxxxxxxxxxxx 4 | NEXT_PUBLIC_GOOGLE_ID = xxxxxxxxxxxxxx 5 | NEXT_PUBLIC_CLARITY_TAG_ID = xxxxxxxxxxxxxx -------------------------------------------------------------------------------- /apps/gkBlog/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import('eslint').Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ["next-typescript"], 5 | parserOptions: { 6 | tsconfigRootDir: __dirname, 7 | project: ["./tsconfig.json"], 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /apps/gkBlog/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # Keep environment variables out of version control 3 | .env 4 | -------------------------------------------------------------------------------- /apps/gkBlog/Dockerfile: -------------------------------------------------------------------------------- 1 | # 使用 Node.js 18 的 Debian slim 版本作为基础镜像 2 | FROM node:18-slim AS base 3 | 4 | # 安装必要的系统依赖 5 | RUN apt-get update && \ 6 | apt-get install -y openssl && \ 7 | rm -rf /var/lib/apt/lists/* 8 | 9 | # 全局安装 Turbo 和 pnpm 10 | RUN npm install -g turbo pnpm 11 | 12 | ####################################################### 13 | 14 | # 创建安装阶段 15 | FROM base AS installer 16 | WORKDIR /app 17 | COPY . . 18 | RUN pnpm install 19 | 20 | ####################################################### 21 | 22 | # 创建构建阶段 23 | FROM installer AS builder 24 | WORKDIR /app 25 | RUN pnpm run build 26 | 27 | ####################################################### 28 | 29 | # 创建运行阶段 30 | FROM builder AS runner 31 | WORKDIR /app 32 | 33 | WORKDIR /app/apps/gkBlog 34 | 35 | # 生成 Prisma Client 36 | RUN pnpm exec prisma generate 37 | 38 | # 切换到非 root 用户 39 | RUN addgroup --system --gid 1001 web-group && \ 40 | adduser --system --uid 1001 --home /home/web-user web-user && \ 41 | mkdir -p /home/web-user/.local/share/pnpm && \ 42 | chown -R web-user:web-group /home/web-user && \ 43 | chown -R web-user:web-group /app 44 | 45 | USER web-user 46 | ENV HOME=/home/web-user 47 | ENV PNPM_HOME=/home/web-user/.local/share/pnpm 48 | 49 | # 暴露端口 50 | EXPOSE 3000 51 | 52 | WORKDIR /app 53 | 54 | # 启动命令 55 | CMD ["pnpm", "run", "start"] -------------------------------------------------------------------------------- /apps/gkBlog/README.md: -------------------------------------------------------------------------------- 1 |
2 |

gkBlog

3 |
4 | -------------------------------------------------------------------------------- /apps/gkBlog/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/gkBlog/next-sitemap.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next-sitemap').IConfig} */ 2 | module.exports = { 3 | siteUrl: "https://www.qladgk.com", 4 | priority: 0.6, 5 | generateRobotsTxt: true, 6 | generateIndexSitemap: false, 7 | transform: async (config, path) => { 8 | const defaultValue = (priority) => ({ 9 | loc: path, 10 | changefreq: config.changefreq, 11 | priority: priority || config.priority, 12 | lastmod: config.autoLastmod ? new Date().toISOString() : undefined, 13 | alternateRefs: config.alternateRefs ?? [], 14 | }); 15 | 16 | if (path === "/") { 17 | return defaultValue(1.0); 18 | } 19 | 20 | if (path === "/blog") { 21 | return defaultValue(0.9); 22 | } 23 | 24 | if (path === "/today-i-learned") { 25 | return defaultValue(0.6); 26 | } 27 | 28 | if (path === "/essay") { 29 | return defaultValue(0.6); 30 | } 31 | 32 | if (path === "/album") { 33 | return defaultValue(0.6); 34 | } 35 | 36 | if (path === "/media") { 37 | return defaultValue(0.6); 38 | } 39 | 40 | if (path === "/shortcodes") { 41 | return defaultValue(0.6); 42 | } 43 | 44 | if (path === "/links") { 45 | return defaultValue(0.6); 46 | } 47 | 48 | if (path === "/feedback") { 49 | return defaultValue(0.6); 50 | } 51 | 52 | return defaultValue(); 53 | }, 54 | }; 55 | -------------------------------------------------------------------------------- /apps/gkBlog/next.config.mjs: -------------------------------------------------------------------------------- 1 | import bundleAnalyzer from "@next/bundle-analyzer"; 2 | import nextMDX from "@next/mdx"; 3 | import rehypePlugins from "rehype-plugins"; 4 | import remarkPlugins from "remark-plugins"; 5 | 6 | /** @type {import('next').NextConfig} */ 7 | const nextConfig = { 8 | pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"], 9 | reactStrictMode: true, 10 | images: { 11 | unoptimized: true, 12 | }, 13 | }; 14 | 15 | const withBundleAnalyzer = bundleAnalyzer({ 16 | enabled: process.env.ANALYZE === "true", 17 | }); 18 | 19 | const withMDX = nextMDX({ 20 | extension: /\.mdx?$/, 21 | options: { 22 | remarkPlugins: remarkPlugins.plugins, 23 | rehypePlugins: rehypePlugins.plugins, 24 | providerImportSource: "@mdx-js/react", 25 | }, 26 | }); 27 | 28 | export default withBundleAnalyzer(withMDX(nextConfig)); 29 | -------------------------------------------------------------------------------- /apps/gkBlog/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | "postcss-import": {}, 4 | "tailwindcss/nesting": {}, 5 | tailwindcss: {}, 6 | autoprefixer: {}, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /apps/gkBlog/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "mongodb" 7 | url = env("DATABASE_URL") 8 | } 9 | 10 | model ContentMeta { 11 | id String @id @default(auto()) @map("_id") @db.ObjectId 12 | 13 | type ContentType 14 | title String 15 | slug String @unique 16 | views View[] 17 | shares Share[] 18 | reactions Reaction[] 19 | createdAt DateTime @default(now()) 20 | } 21 | 22 | enum ContentType { 23 | PAGE 24 | POST 25 | PROJECT 26 | } 27 | 28 | model View { 29 | id String @id @default(auto()) @map("_id") @db.ObjectId 30 | 31 | createdAt DateTime @default(now()) 32 | sessionId String 33 | 34 | contentId String @db.ObjectId 35 | content ContentMeta @relation(fields: [contentId], references: [id], onDelete: Cascade) 36 | } 37 | 38 | model Share { 39 | id String @id @default(auto()) @map("_id") @db.ObjectId 40 | 41 | type ShareType? @default(OTHERS) 42 | createdAt DateTime @default(now()) 43 | sessionId String 44 | 45 | contentId String @db.ObjectId 46 | content ContentMeta @relation(fields: [contentId], references: [id], onDelete: Cascade) 47 | } 48 | 49 | enum ShareType { 50 | TWITTER 51 | CLIPBOARD 52 | OTHERS 53 | } 54 | 55 | model Reaction { 56 | id String @id @default(auto()) @map("_id") @db.ObjectId 57 | 58 | count Int? @default(1) 59 | section String? 60 | type ReactionType? @default(CLAPPING) 61 | createdAt DateTime @default(now()) 62 | sessionId String 63 | 64 | contentId String @db.ObjectId 65 | content ContentMeta @relation(fields: [contentId], references: [id], onDelete: Cascade) 66 | } 67 | 68 | enum ReactionType { 69 | CLAPPING 70 | THINKING 71 | AMAZED 72 | } 73 | -------------------------------------------------------------------------------- /apps/gkBlog/public/17dec345aa579ceab23086620028a420.txt: -------------------------------------------------------------------------------- 1 | 17dec345aa579ceab23086620028a420 2 | -------------------------------------------------------------------------------- /apps/gkBlog/public/9a692f6e78de4cee9cf96c9c373a6b16.txt: -------------------------------------------------------------------------------- 1 | 9a692f6e78de4cee9cf96c9c373a6b16 -------------------------------------------------------------------------------- /apps/gkBlog/public/ByteDanceVerify.html: -------------------------------------------------------------------------------- 1 | 0tOedyoAcJ6fTaz2kM4W 2 | -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/astonished-face-animated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/astonished-face-animated.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/astonished-face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/astonished-face.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/clapping-hands-animated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/clapping-hands-animated.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/clapping-hands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/clapping-hands.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/face-with-monocle-animated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/face-with-monocle-animated.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/face-with-monocle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/face-with-monocle.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/love-you-gesture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/love-you-gesture.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/nerd-face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/nerd-face.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/emojis/star-struck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/emojis/star-struck.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/coverImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/coverImage.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/model.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/model.glb -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/026f727af7-d878-42d4-a53a-c464d0c0ecb4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/026f727af7-d878-42d4-a53a-c464d0c0ecb4.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/123e49a39f-f47a-48ba-8a8e-5db39e1d5353.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/123e49a39f-f47a-48ba-8a8e-5db39e1d5353.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/130cd91e04-5dc9-4536-95fe-538ef04d9490.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/130cd91e04-5dc9-4536-95fe-538ef04d9490.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13147ff4ca-6cbb-411e-b76d-6c6a9b1a2687.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13147ff4ca-6cbb-411e-b76d-6c6a9b1a2687.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1328a0081e-46a9-4da3-a771-9043268a2e7c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1328a0081e-46a9-4da3-a771-9043268a2e7c.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/133604f9b2-b434-4aa8-92c0-e8f88336e4db.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/133604f9b2-b434-4aa8-92c0-e8f88336e4db.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1342d14337-0e7e-42e2-b3f5-d92f0903d33f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1342d14337-0e7e-42e2-b3f5-d92f0903d33f.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/135717365f-c912-4679-9f01-b05fcca43095.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/135717365f-c912-4679-9f01-b05fcca43095.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13736687a2-6a78-4c2a-866e-17a5ee23b756.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13736687a2-6a78-4c2a-866e-17a5ee23b756.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/139b340d18-2966-4ce6-b926-54694c944079.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/139b340d18-2966-4ce6-b926-54694c944079.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13a47e43fe-9ea3-43ca-a9e2-808483a6598b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13a47e43fe-9ea3-43ca-a9e2-808483a6598b.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13b4e0e03c-c438-4b1c-962d-839a489ecec1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13b4e0e03c-c438-4b1c-962d-839a489ecec1.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13bef5e4f5-105e-436d-b580-7f223a167cb7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13bef5e4f5-105e-436d-b580-7f223a167cb7.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13c80ca032-f642-4ed2-86c0-94704a240cf0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13c80ca032-f642-4ed2-86c0-94704a240cf0.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13e99a10f0-76d0-4038-b4f6-d02a2ed7a383.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13e99a10f0-76d0-4038-b4f6-d02a2ed7a383.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13ebc0ea8c-ae2c-4329-93be-c1970a37e20d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13ebc0ea8c-ae2c-4329-93be-c1970a37e20d.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13eda1111e-c4fc-4f0e-99b7-fff0a4e5022f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13eda1111e-c4fc-4f0e-99b7-fff0a4e5022f.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/13f6344886-9243-4924-9257-fb2ad9ed90ce.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/13f6344886-9243-4924-9257-fb2ad9ed90ce.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1401818191-c040-4bd0-b8b5-b1342ea2195d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1401818191-c040-4bd0-b8b5-b1342ea2195d.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/144ed58222-783e-4bf5-9563-399c6f0c2b3d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/144ed58222-783e-4bf5-9563-399c6f0c2b3d.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/14a4cfa306-8e52-4981-b49a-c00435db6831.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/14a4cfa306-8e52-4981-b49a-c00435db6831.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/14bd0a7d78-fda5-47f9-9d6c-8fbf573ce8c3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/14bd0a7d78-fda5-47f9-9d6c-8fbf573ce8c3.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/14e442937b-efaf-4a42-99b9-4f867d2250f2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/14e442937b-efaf-4a42-99b9-4f867d2250f2.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/14e5043627-8e2d-43c0-a6cc-a8e05d8115d3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/14e5043627-8e2d-43c0-a6cc-a8e05d8115d3.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1515210a18-1e0a-4ee2-a5a7-e2c5edb6ecb5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1515210a18-1e0a-4ee2-a5a7-e2c5edb6ecb5.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/152bbd9498-8051-4931-afbf-4eddc7f9150c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/152bbd9498-8051-4931-afbf-4eddc7f9150c.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/152d9fd739-6ff0-4b5f-989f-ca5bf295ac36.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/152d9fd739-6ff0-4b5f-989f-ca5bf295ac36.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/153bc2857e-c61b-49c9-a30a-e5cf062e87f7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/153bc2857e-c61b-49c9-a30a-e5cf062e87f7.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/153dcbfdda-18ce-4e61-9e13-1345dda39ccd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/153dcbfdda-18ce-4e61-9e13-1345dda39ccd.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/153ebbeccc-013f-4682-b8d1-18e9a3a8129a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/153ebbeccc-013f-4682-b8d1-18e9a3a8129a.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15441d0fe9-fa9b-4fb8-b41c-16f4b4d500ea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15441d0fe9-fa9b-4fb8-b41c-16f4b4d500ea.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/154887e57f-7ffe-4981-80d8-3daa586ff0ee.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/154887e57f-7ffe-4981-80d8-3daa586ff0ee.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/154ff20ed0-6fd6-4eae-abad-0e6f970b885a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/154ff20ed0-6fd6-4eae-abad-0e6f970b885a.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15568d4a23-5ef0-4cba-96f4-487d3babbaa8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15568d4a23-5ef0-4cba-96f4-487d3babbaa8.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15600f9e3e-d6f3-4d27-b24f-2cff4992f27c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15600f9e3e-d6f3-4d27-b24f-2cff4992f27c.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15636422b6-4f36-4fb0-8e56-6577c08fc4c4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15636422b6-4f36-4fb0-8e56-6577c08fc4c4.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1568906669-00c1-4f62-a7b2-24068159e264.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1568906669-00c1-4f62-a7b2-24068159e264.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/156a81ad17-6f6c-4533-b1ab-432d0c87a390.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/156a81ad17-6f6c-4533-b1ab-432d0c87a390.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15707c4ef9-400b-4c7c-8ff0-df74d3fef33c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15707c4ef9-400b-4c7c-8ff0-df74d3fef33c.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1578d53bc3-8bbe-4116-83e9-f5c91fc0d3f9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1578d53bc3-8bbe-4116-83e9-f5c91fc0d3f9.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/157e882f74-65b0-4c11-88a8-6f1a103b5954.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/157e882f74-65b0-4c11-88a8-6f1a103b5954.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/157eee4ad4-84de-4e92-8fc4-aa4ff42da48f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/157eee4ad4-84de-4e92-8fc4-aa4ff42da48f.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15881fc78e-fd01-4cab-aa49-030c330e48dd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15881fc78e-fd01-4cab-aa49-030c330e48dd.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/158cac42e4-74fb-472f-afd5-78984be19315.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/158cac42e4-74fb-472f-afd5-78984be19315.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/159008bab2-fd56-48b7-b553-f0a4d76eef0a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/159008bab2-fd56-48b7-b553-f0a4d76eef0a.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15a5cb7008-acae-4a3b-8d5d-581355037dcf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15a5cb7008-acae-4a3b-8d5d-581355037dcf.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15b5fa8d7e-ad33-4736-a9db-f39c6613b08b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15b5fa8d7e-ad33-4736-a9db-f39c6613b08b.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15b71e1380-9ed2-4ac2-bf49-d2e2b3c92156.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15b71e1380-9ed2-4ac2-bf49-d2e2b3c92156.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15cd943477-b70e-44fa-b85d-86869783bdc2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15cd943477-b70e-44fa-b85d-86869783bdc2.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15d0883f9f-f849-4054-9b49-e021f380f73b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15d0883f9f-f849-4054-9b49-e021f380f73b.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15d514432e-a535-493f-a4b6-c4b86e9f9916.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15d514432e-a535-493f-a4b6-c4b86e9f9916.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15dcceff27-b10e-4149-9673-022b83f75410.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15dcceff27-b10e-4149-9673-022b83f75410.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15e065e907-4ace-4646-9fc5-fa2116705698.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15e065e907-4ace-4646-9fc5-fa2116705698.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15e6ca679d-2d3d-4e6e-86c6-0e8580f01846.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15e6ca679d-2d3d-4e6e-86c6-0e8580f01846.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15e8c2720f-1bf2-4a9c-927f-6c220e918526.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15e8c2720f-1bf2-4a9c-927f-6c220e918526.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15e9868a92-5dc6-4645-a44e-30031f4967a5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15e9868a92-5dc6-4645-a44e-30031f4967a5.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15eab988ed-8d95-4b0c-a833-6ab27274ea27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15eab988ed-8d95-4b0c-a833-6ab27274ea27.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15ee7eadd5-aa1b-4a17-8418-25990a29d337.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15ee7eadd5-aa1b-4a17-8418-25990a29d337.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15f3e99e45-6b26-4747-a8f2-09f292b8f332.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15f3e99e45-6b26-4747-a8f2-09f292b8f332.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15f3ec6730-4ef7-47c0-8af4-9e640d573cd8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15f3ec6730-4ef7-47c0-8af4-9e640d573cd8.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/15f440c10b-6210-43ff-860d-907297628e18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/15f440c10b-6210-43ff-860d-907297628e18.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1618bc6aa2-1e56-4523-96a0-17c992c159e5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1618bc6aa2-1e56-4523-96a0-17c992c159e5.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/161baa0173-8a4d-476f-8c9a-b29c9c8ee4b6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/161baa0173-8a4d-476f-8c9a-b29c9c8ee4b6.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/162fe81dd5-242d-444f-9127-95f6ee31edb7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/162fe81dd5-242d-444f-9127-95f6ee31edb7.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1651a0aaab-19d2-4fde-8f39-409de4e45aac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1651a0aaab-19d2-4fde-8f39-409de4e45aac.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/165f79bf08-ac00-4a60-ac1e-7b3c194aa8a2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/165f79bf08-ac00-4a60-ac1e-7b3c194aa8a2.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1663bcc4de-a15c-4d50-a3ab-13f9736bd689.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1663bcc4de-a15c-4d50-a3ab-13f9736bd689.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/16770e2bbe-94c9-42dc-a6cd-5aea772f9e39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/16770e2bbe-94c9-42dc-a6cd-5aea772f9e39.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/16b10d7e9f-4a2a-471e-8e98-8acc0054ddda.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/16b10d7e9f-4a2a-471e-8e98-8acc0054ddda.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/1721fa6acb-b578-48e0-9ff3-c192fc520d90.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/1721fa6acb-b578-48e0-9ff3-c192fc520d90.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/180d0ea039-6cd0-4fb3-9c16-486051371ad7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/180d0ea039-6cd0-4fb3-9c16-486051371ad7.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/26a4fa45-6953-49f9-b8cf-35f7ca58275b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/26a4fa45-6953-49f9-b8cf-35f7ca58275b.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/292dd0f3ac-6aa4-4c39-a08d-ee732890b21f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/292dd0f3ac-6aa4-4c39-a08d-ee732890b21f.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/2e0c2aa6-8ee5-417b-bbc7-104090798a8e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/2e0c2aa6-8ee5-417b-bbc7-104090798a8e.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/31bc2bb5-7210-4ed0-891c-520075ac36e7.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/31bc2bb5-7210-4ed0-891c-520075ac36e7.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/4a236368-8343-40e3-bccf-a196a08f2c52.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/4a236368-8343-40e3-bccf-a196a08f2c52.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/4cd9e07d-ff81-4e63-8e16-ac2cd5f81bd7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/4cd9e07d-ff81-4e63-8e16-ac2cd5f81bd7.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/837260ea-0e8b-4952-9cfc-5e06f0d42748.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/837260ea-0e8b-4952-9cfc-5e06f0d42748.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/8722487d-911a-4260-8589-4ea0626eb134.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/8722487d-911a-4260-8589-4ea0626eb134.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/896338d8-5109-4667-aec5-6f30a53c004e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/896338d8-5109-4667-aec5-6f30a53c004e.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/8be68de4-0d12-4460-bd87-0788af9908cd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/8be68de4-0d12-4460-bd87-0788af9908cd.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/918b1177-ef27-4f62-853c-d95b82eca6b9.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/918b1177-ef27-4f62-853c-d95b82eca6b9.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/91aef100-a4ff-4866-8e5e-a6b1af1bc754.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/91aef100-a4ff-4866-8e5e-a6b1af1bc754.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/9abe26d8-4ddb-4e25-987e-a994d72488eb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/9abe26d8-4ddb-4e25-987e-a994d72488eb.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/9b8c9c00-d17c-4de2-9dc4-d7d8eba26a3c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/9b8c9c00-d17c-4de2-9dc4-d7d8eba26a3c.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/9fcaf1da-6927-4d94-b5d2-da74ce9e5414.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/9fcaf1da-6927-4d94-b5d2-da74ce9e5414.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/ab916129-e95f-47a3-be39-d0218f9e7f76.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/ab916129-e95f-47a3-be39-d0218f9e7f76.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/b05acf62-c9ec-4f55-89e0-76457bbcb545.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/b05acf62-c9ec-4f55-89e0-76457bbcb545.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/b41c6631-bb51-4bdf-aa3e-06b7c0fc8fd8.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/b41c6631-bb51-4bdf-aa3e-06b7c0fc8fd8.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/b78f8f40-3910-479a-814d-e05f451f5ca8.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/b78f8f40-3910-479a-814d-e05f451f5ca8.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/c6b6a72c-2a26-487c-9c3f-54c23cf4ca9e.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/c6b6a72c-2a26-487c-9c3f-54c23cf4ca9e.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/d801edae-d1f3-499d-8a73-123ce9669780.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/d801edae-d1f3-499d-8a73-123ce9669780.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/e1a4d84a-c39d-4094-8b75-b57f2eb31ce0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/e1a4d84a-c39d-4094-8b75-b57f2eb31ce0.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/e7886af0-9e2c-46f5-a079-90f4d94d0803.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/e7886af0-9e2c-46f5-a079-90f4d94d0803.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/eb0c8821-ae0e-4438-b629-a2c769c161cb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/eb0c8821-ae0e-4438-b629-a2c769c161cb.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/ee6dbb95-0151-44de-8734-6cf36fe511f1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/ee6dbb95-0151-44de-8734-6cf36fe511f1.jpg -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/neodb/cover/f929217a-3c36-4a6e-8885-64fc07476424.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/neodb/cover/f929217a-3c36-4a6e-8885-64fc07476424.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/og-image.png -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/images/qlAD.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/images/qlAD.webp -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/sounds/click.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/sounds/click.mp3 -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/sounds/close.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/sounds/close.mp3 -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/sounds/lightoff.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/sounds/lightoff.mp3 -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/sounds/lighton.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/sounds/lighton.mp3 -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/sounds/open.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/sounds/open.mp3 -------------------------------------------------------------------------------- /apps/gkBlog/public/assets/sounds/pop_clean.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/assets/sounds/pop_clean.flac -------------------------------------------------------------------------------- /apps/gkBlog/public/baidu_verify_codeva-wXcFRrXTHy.html: -------------------------------------------------------------------------------- 1 | ccc95d024ead875cd40a5f83a6ae61d4 2 | -------------------------------------------------------------------------------- /apps/gkBlog/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/public/favicon.ico -------------------------------------------------------------------------------- /apps/gkBlog/public/googlee46587067af4c10b.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlee46587067af4c10b.html 2 | -------------------------------------------------------------------------------- /apps/gkBlog/public/shenma-site-verification.txt: -------------------------------------------------------------------------------- 1 | shenma-site-verification:2a33f884e831b5ad3e7383d15f479471_1729320377 2 | -------------------------------------------------------------------------------- /apps/gkBlog/public/sogousiteverification.txt: -------------------------------------------------------------------------------- 1 | Ei8gvBbi1o 2 | -------------------------------------------------------------------------------- /apps/gkBlog/scripts/movie_details.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | 4 | with open('apps/gkBlog/public/assets/data/neodb/movie.json', encoding='utf-8') as f: 5 | data = json.load(f)['data'] 6 | 7 | api_urls = [] 8 | for item in data: 9 | api_urls.append(item['item']['api_url']) 10 | 11 | api_urls = ['https://neodb.social' + url for url in api_urls] 12 | 13 | details = [] 14 | for url in api_urls: 15 | response = requests.get(url) 16 | details.append(response.json()) 17 | 18 | with open('apps/gkBlog/public/assets/data/neodb/movie_details.json', 'w', encoding='utf-8') as f: 19 | json.dump(details, f, ensure_ascii=False) 20 | -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/PlusJakartaSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/PlusJakartaSans-ExtraBold.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/PlusJakartaSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/PlusJakartaSans-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_AMS-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_AMS-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_AMS-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_AMS-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_AMS-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_AMS-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Bold.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Bold.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Bold.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Caligraphic-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Bold.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Bold.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Bold.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Fraktur-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Bold.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Bold.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Bold.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-BoldItalic.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-BoldItalic.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-BoldItalic.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Italic.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Italic.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Italic.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Main-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-BoldItalic.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-BoldItalic.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-BoldItalic.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-Italic.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-Italic.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Math-Italic.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Bold.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Bold.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Bold.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Italic.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Italic.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Italic.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_SansSerif-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Script-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Script-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Script-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Script-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Script-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Script-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size1-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size1-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size1-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size1-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size1-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size2-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size2-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size2-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size2-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size2-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size3-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size3-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size3-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size3-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size3-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size3-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size4-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size4-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size4-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Size4-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Size4-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Typewriter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Typewriter-Regular.ttf -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Typewriter-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Typewriter-Regular.woff -------------------------------------------------------------------------------- /apps/gkBlog/src/assets/fonts/katex/KaTeX_Typewriter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/assets/fonts/katex/KaTeX_Typewriter-Regular.woff2 -------------------------------------------------------------------------------- /apps/gkBlog/src/components/CountUp.tsx: -------------------------------------------------------------------------------- 1 | import { animate } from "framer-motion"; 2 | import { useEffect, useRef } from "react"; 3 | 4 | interface CountUpProps { 5 | from: number; 6 | to: number; 7 | } 8 | 9 | function CountUp({ from, to }: CountUpProps) { 10 | const nodeRef = useRef(null); 11 | 12 | useEffect(() => { 13 | const node = nodeRef.current; 14 | 15 | const controls = animate(from, to, { 16 | duration: 1.4, 17 | ease: "easeOut", 18 | onUpdate(value) { 19 | node.textContent = value.toFixed(0); 20 | }, 21 | }); 22 | 23 | return () => controls.stop(); 24 | }, [from, to]); 25 | 26 | return {to}; 27 | } 28 | 29 | export default CountUp; 30 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/Kbd.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import type { PropsWithChildren } from "react"; 4 | 5 | function Kbd({ children }: PropsWithChildren) { 6 | return ( 7 | 13 | {children} 14 | 15 | ); 16 | } 17 | 18 | export default Kbd; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/Logo.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | interface LogoProps { 4 | active?: boolean; 5 | } 6 | 7 | function Logo({ active = false }: LogoProps) { 8 | return ( 9 |
10 |
21 |
28 |
29 | 37 |
38 | ); 39 | } 40 | 41 | export default Logo; 42 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/Portal.tsx: -------------------------------------------------------------------------------- 1 | import { memo, useEffect, useState } from "react"; 2 | import { createPortal } from "react-dom"; 3 | 4 | import type { PropsWithChildren } from "react"; 5 | 6 | interface PortalProps { 7 | selector: string; 8 | } 9 | 10 | function Portal({ selector, children = null }: PropsWithChildren) { 11 | const [container, setContainer] = useState(null); 12 | 13 | useEffect(() => { 14 | setContainer(document.querySelector(selector)); 15 | }, [selector]); 16 | 17 | return container ? createPortal(children, container) : null; 18 | } 19 | 20 | export default memo(Portal); 21 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/ScriptLoader.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | // 工具函数:设置元素的文本 4 | const setElementText = (id: string, text: string | undefined) => { 5 | const element = document.getElementById(id); 6 | if (element) { 7 | element.textContent = text || "未知"; 8 | } 9 | }; 10 | 11 | // 工具函数:解析浏览器信息 12 | const getBrowserInfo = (userAgent: string): string => { 13 | const browserRegex = 14 | /(Chrome|Firefox|Safari|Edge|Opera|MSIE|Trident)\/([\d.]+)/; 15 | const match = userAgent.match(browserRegex); 16 | return match ? `${match[1]} ${match[2]}` : "未知浏览器"; 17 | }; 18 | 19 | function ScriptLoader() { 20 | useEffect(() => { 21 | const fetchIpInfo = async () => { 22 | const fetchUrl = "https://api.qjqq.cn/api/Local"; 23 | 24 | try { 25 | const res = await fetch(fetchUrl); 26 | if (!res.ok) { 27 | throw new Error(`网络请求失败,状态码:${res.status}`); 28 | } 29 | 30 | const json = await res.json(); 31 | const data = json.data || {}; 32 | 33 | // 使用 setElementText 填充页面中的数据 34 | setElementText("userAgentIp", json.ip); 35 | setElementText("userAgentCountry", data.country); 36 | setElementText("userAgentRegion", data.prov); 37 | setElementText("userAgentCity", data.city); 38 | setElementText("userAgentIsp", data.isp); 39 | 40 | // 显示简化后的浏览器信息 41 | const uaInfo = navigator.userAgent; 42 | const browserInfo = getBrowserInfo(uaInfo); 43 | setElementText("userAgentOs", navigator.platform); 44 | setElementText("userAgentBrowser", browserInfo); 45 | } catch (error) { 46 | // console.error('获取 IP 信息失败:', error); // 使用 console.error 避免警告 47 | } 48 | }; 49 | 50 | fetchIpInfo(); 51 | }, []); 52 | 53 | return null; // 组件不需要渲染 UI 54 | } 55 | 56 | export default ScriptLoader; 57 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/Shortcuts.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | import { toast } from "react-hot-toast"; 3 | 4 | import Toast from "@/components/Toast"; 5 | 6 | import useFocusMode from "@/hooks/useFocusMode"; 7 | import useGlobal from "@/hooks/useGlobal"; 8 | import useShortcut from "@/hooks/useShortcut"; 9 | import useTheme from "@/hooks/useTheme"; 10 | 11 | const focusToast = { 12 | title: "专注模式 {STATUS}", 13 | message: "Focus 通过隐藏浮动组件(如导航和表情)来帮助减少干扰。", 14 | }; 15 | 16 | function Shortcuts() { 17 | const toastRef = useRef(null); 18 | const { theme, setTheme } = useTheme(); 19 | const { isQuickAccessOpen, setQuickAccessOpen } = useGlobal(); 20 | const { focusMode, setFocusMode } = useFocusMode(); 21 | 22 | // Update shortcuts to require Shift for uppercase letters 23 | useShortcut("KeyD", (event) => { 24 | if (event.shiftKey) { 25 | setTheme(theme === "dark" ? "light" : "dark"); 26 | } 27 | }); 28 | 29 | useShortcut("KeyQ", (event) => { 30 | if (event.shiftKey) { 31 | setQuickAccessOpen(!isQuickAccessOpen); 32 | } 33 | }); 34 | 35 | useShortcut("KeyF", (event) => { 36 | if (event.shiftKey) { 37 | setFocusMode(!focusMode); 38 | } 39 | }); 40 | 41 | useEffect(() => { 42 | if (toastRef.current) { 43 | toast.remove(toastRef.current.id); 44 | } 45 | if (focusMode) { 46 | toastRef.current = toast.custom((t) => ( 47 | 52 | )); 53 | } else { 54 | toastRef.current = toast.custom((t) => ( 55 | 60 | )); 61 | } 62 | }, [focusMode]); 63 | 64 | return null; 65 | } 66 | 67 | export default Shortcuts; 68 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/Toast.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import { m } from "framer-motion"; 3 | import { toast } from "react-hot-toast"; 4 | 5 | import { InfoIcon, XCircleIcon } from "@/components/Icons"; 6 | 7 | import type { Toast as TToast } from "react-hot-toast"; 8 | 9 | interface ToastProps { 10 | title: string; 11 | message: React.ReactNode; 12 | t: TToast; 13 | } 14 | 15 | function Toast({ title, message, t }: ToastProps) { 16 | return ( 17 | 26 |
27 | 28 |
29 |
30 |
33 | {title} 34 |
35 |
36 |

{message}

37 |
38 |
39 |
40 | 48 |
49 |
50 | ); 51 | } 52 | 53 | export default Toast; 54 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/Toaster.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import { ToastBar, Toaster } from "react-hot-toast"; 3 | 4 | function Toast() { 5 | return ( 6 |
11 | 21 | {(t) => } 22 | 23 |
24 | ); 25 | } 26 | 27 | export default Toast; 28 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/TwikooComments.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | interface TwikooConfig { 4 | envId: string; 5 | el: string; 6 | } 7 | 8 | interface Twikoo { 9 | init: (config: TwikooConfig) => void; 10 | } 11 | 12 | function TwikooComments() { 13 | useEffect(() => { 14 | const script = document.createElement("script"); 15 | script.src = 16 | "https://cdn.jsdelivr.net/npm/twikoo@1.6.39/dist/twikoo.min.js"; 17 | script.async = true; 18 | 19 | script.onload = () => { 20 | const { twikoo } = window as unknown as { twikoo: Twikoo }; 21 | twikoo.init({ 22 | envId: "https://twikoo.qladgk.com/", 23 | el: "#tcomment", 24 | }); 25 | }; 26 | 27 | document.body.appendChild(script); 28 | 29 | return () => { 30 | document.body.removeChild(script); 31 | }; 32 | }, []); 33 | 34 | return
; 35 | } 36 | 37 | export default TwikooComments; 38 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/analytics/BaiduAnalytics.tsx: -------------------------------------------------------------------------------- 1 | import Script from "next/script"; 2 | 3 | function BaiDuAnalytics() { 4 | return ( 5 | 51 | )} 52 | 53 | ); 54 | } 55 | 56 | export default Head; 57 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/navigations/NavIcon.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import type { ReactElement } from "react"; 4 | 5 | interface NavIconProps { 6 | href: string; 7 | icon: ReactElement; 8 | title: string; 9 | label?: string; 10 | } 11 | 12 | function NavIcon({ href, icon, title, label = "" }: NavIconProps) { 13 | return ( 14 | 34 | 37 | {icon} 38 | 39 | {label && ( 40 | 47 | {label} 48 | 49 | )} 50 | 51 | ); 52 | } 53 | 54 | export default NavIcon; 55 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/navigations/NavIconQuickAccess.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import { QuickAccessIcon } from "@/components/Icons"; 4 | import Kbd from "@/components/Kbd"; 5 | 6 | import useGlobal from "@/hooks/useGlobal"; 7 | 8 | type NavIconQuickAccessProps = { 9 | onClick?: () => void; 10 | }; 11 | 12 | // eslint-disable-next-line react/require-default-props 13 | function NavIconQuickAccess({ onClick }: NavIconQuickAccessProps) { 14 | const { setQuickAccessOpen } = useGlobal(); 15 | 16 | const handleClick = () => { 17 | setQuickAccessOpen(true); 18 | if (onClick) { 19 | onClick(); // 如果传递了外部的 onClick,则调用它 20 | } 21 | }; 22 | 23 | return ( 24 | 48 | ); 49 | } 50 | 51 | export default NavIconQuickAccess; 52 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/navigations/NavLink.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import Link from "next/link"; 3 | 4 | import type { ReactNode } from "react"; 5 | 6 | export type NavLinkProps = { 7 | title: string; 8 | href: string; 9 | icon?: ReactNode; 10 | onClick?: () => void; 11 | }; 12 | 13 | function NavLink({ 14 | title, 15 | href, 16 | icon = null, 17 | onClick = () => {}, 18 | }: NavLinkProps) { 19 | return ( 20 | 28 | {title} 29 | {icon} 30 | 31 | ); 32 | } 33 | 34 | export default NavLink; 35 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/navigations/NavLinkExpanded.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import React from "react"; 3 | 4 | import { ChevronRightIcon } from "@/components/Icons"; 5 | import NavLink from "@/components/navigations/NavLink"; 6 | 7 | import type { NavLinkProps } from "@/components/navigations/NavLink"; 8 | 9 | interface NavLinkExpandedProps { 10 | title: string; 11 | items: Array; 12 | onClick?: () => void; 13 | } 14 | 15 | function NavLinkExpanded({ 16 | title, 17 | items, 18 | onClick = () => {}, 19 | }: NavLinkExpandedProps) { 20 | return ( 21 |
22 |
27 | {title} 28 | 29 |
30 |
    31 | {items.map((item, idx) => ( 32 | 33 |
  • 34 | {/* 如果有 onClick 则传递给 NavLink */} 35 | 36 |
  • 37 | {idx !== items.length - 1 && ( 38 |
  • 39 |
    ·
    40 |
  • 41 | )} 42 |
    43 | ))} 44 |
45 |
46 | ); 47 | } 48 | 49 | export default NavLinkExpanded; 50 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/navigations/NavLogo.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import Link from "next/link"; 3 | import { useRouter } from "next/router"; 4 | 5 | import Logo from "@/components/Logo"; 6 | 7 | interface NavLogoProps { 8 | href: string; 9 | title: string; 10 | } 11 | 12 | function NavLogo({ href, title }: NavLogoProps) { 13 | const router = useRouter(); 14 | const isActive = router.pathname === href; 15 | 16 | return ( 17 | 22 | 23 | 24 | ); 25 | } 26 | 27 | export default NavLogo; 28 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/navigations/SkipNavigation.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import Portal from "@/components/Portal"; 4 | 5 | interface SkipNavigationLinkProps { 6 | title: string; 7 | slug: string; 8 | } 9 | 10 | function SkipNavigationLink({ title, slug }: SkipNavigationLinkProps) { 11 | return ( 12 | 23 | {title} 24 | 25 | ); 26 | } 27 | 28 | interface SkipNavigationProps { 29 | skipTableOfContents?: boolean; 30 | } 31 | 32 | function SkipNavigation({ skipTableOfContents = true }: SkipNavigationProps) { 33 | return ( 34 | 35 |
43 | {skipTableOfContents && ( 44 | 45 | )} 46 | 47 |
48 |
49 | ); 50 | } 51 | 52 | export default SkipNavigation; 53 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/sections/SectionContent.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import type { PropsWithChildren } from "react"; 4 | 5 | function SectionContent({ children }: PropsWithChildren) { 6 | return ( 7 |
13 |
{children}
14 |
15 | ); 16 | } 17 | 18 | export default SectionContent; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/sidebar/Card.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | interface CardProps { 4 | title: string; 5 | children: React.ReactNode; 6 | className?: string; 7 | } 8 | 9 | // eslint-disable-next-line react/require-default-props 10 | function Card({ title, children, className }: CardProps) { 11 | return ( 12 | 31 | ); 32 | } 33 | 34 | export default Card; 35 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/ui/AvatarCircles.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | interface AvatarCirclesProps { 6 | className?: string; 7 | numPeople?: number; 8 | avatarUrls: string[]; 9 | } 10 | 11 | function AvatarCircles({ 12 | numPeople = 0, 13 | className = "", 14 | avatarUrls, 15 | }: AvatarCirclesProps) { 16 | return ( 17 |
18 | {avatarUrls.map((url, index) => ( 19 | {`Avatar 26 | ))} 27 | 31 | +{numPeople} 32 | 33 |
34 | ); 35 | } 36 | 37 | export default AvatarCircles; 38 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/ui/Marquee.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | interface MarqueeProps { 4 | className?: string; 5 | reverse?: boolean; 6 | pauseOnHover?: boolean; 7 | children?: React.ReactNode; 8 | vertical?: boolean; 9 | repeat?: number; 10 | [key: string]: unknown; // 或更具体的类型 11 | } 12 | 13 | export default function Marquee({ 14 | className = "", 15 | reverse = false, 16 | pauseOnHover = false, 17 | children = null, 18 | vertical = false, 19 | repeat = 4, 20 | ...props 21 | }: MarqueeProps) { 22 | return ( 23 |
34 | {Array.from({ length: repeat }).map((_, i) => ( 35 |
45 | {children} 46 |
47 | ))} 48 |
49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /apps/gkBlog/src/components/wireframes/Skeletons.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import type { PropsWithChildren } from "react"; 4 | 5 | interface SkeletonProps { 6 | /** 7 | * Skeleton width in pixels. 8 | */ 9 | w?: number; 10 | } 11 | 12 | export function SkeletonSm({ 13 | w = 16, 14 | children = null, 15 | }: PropsWithChildren) { 16 | return ( 17 |
24 | {children} 25 |
26 | ); 27 | } 28 | 29 | export function SkeletonMd({ 30 | w = 24, 31 | children = null, 32 | }: PropsWithChildren) { 33 | return ( 34 |
41 | {children} 42 |
43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /apps/gkBlog/src/constants/app.ts: -------------------------------------------------------------------------------- 1 | // for each reaction (CLAPPING, THINGKING, AMAZED) 2 | export const MAX_REACTIONS_PER_SESSION = 15; 3 | 4 | // max shares that will be counted 5 | export const MAX_SHARES_PER_SESSION = 10; 6 | 7 | // max views that will be counted 8 | export const MAX_VIEWS_PER_SESSION = 20; 9 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents-layouts/Page.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import Head from "@/components/meta/Head"; 4 | import SkipNavigation from "@/components/navigations/SkipNavigation"; 5 | import PageHeader from "@/components/PageHeader"; 6 | 7 | import { getPageOgImageUrl } from "@/helpers/page"; 8 | 9 | import type { TPageFrontMatter } from "@/types"; 10 | import type { PropsWithChildren, ReactNode } from "react"; 11 | 12 | interface PageProps { 13 | frontMatter: TPageFrontMatter; 14 | headerImage?: ReactNode; 15 | } 16 | 17 | function Page({ 18 | frontMatter: { title, description, caption }, 19 | children = null, 20 | headerImage = null, 21 | }: PropsWithChildren) { 22 | const image = getPageOgImageUrl({ 23 | caption, 24 | title, 25 | description, 26 | }); 27 | 28 | return ( 29 | <> 30 | 31 | 32 | 38 |
39 | {children} 40 |
41 | 42 | ); 43 | } 44 | 45 | export default Page; 46 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents-layouts/PageWithMDX.tsx: -------------------------------------------------------------------------------- 1 | import WithTableOfContents from "@/components/layouts/WithTableOfContents"; 2 | import Head from "@/components/meta/Head"; 3 | import SkipNavigation from "@/components/navigations/SkipNavigation"; 4 | import PageHeader from "@/components/PageHeader"; 5 | 6 | import { getPageOgImageUrl } from "@/helpers/page"; 7 | 8 | import type { TPageFrontMatter, TTableOfContents } from "@/types"; 9 | import type { PropsWithChildren } from "react"; 10 | 11 | interface PageWithMDXProps { 12 | frontMatter: TPageFrontMatter; 13 | tableOfContents: TTableOfContents; 14 | } 15 | 16 | function PageWithMDX({ 17 | frontMatter: { title, description, caption }, 18 | tableOfContents, 19 | children = null, 20 | }: PropsWithChildren) { 21 | const image = getPageOgImageUrl({ 22 | caption, 23 | title, 24 | description, 25 | }); 26 | 27 | return ( 28 | <> 29 | 30 | 31 | 32 | 33 | {children} 34 | 35 | 36 | ); 37 | } 38 | 39 | export default PageWithMDX; 40 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents-layouts/Post/PostFooter.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import Link from "next/link"; 3 | 4 | import type { PropsWithChildren } from "react"; 5 | import { TPostFrontMatter } from "@/types"; 6 | 7 | type ChipProps = { 8 | href: string; 9 | }; 10 | 11 | function Chip({ href, children = null }: PropsWithChildren) { 12 | return ( 13 | 20 | {children} 21 | 22 | ); 23 | } 24 | 25 | interface PostFooterProps { 26 | tags: TPostFrontMatter["tags"]; 27 | category: TPostFrontMatter["category"]; 28 | } 29 | 30 | function PostFooter({ tags, category }: PostFooterProps) { 31 | return ( 32 |
39 |
40 | 文章分类在 41 | 45 | {category} 46 | 47 |
48 | {tags.map((tag) => ( 49 | 50 | #{tag} 51 | 52 | ))} 53 |
54 |
55 |
56 | ); 57 | } 58 | 59 | export default PostFooter; 60 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents-layouts/Post/PostMeta.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import { CalendarIcon, LanguageIcon } from "@/components/Icons"; 4 | 5 | import { formatDate, formatDateISO, formatLang } from "@/helpers/post"; 6 | 7 | import { TPostFrontMatter } from "@/types"; 8 | 9 | interface PostMetaProps { 10 | date: TPostFrontMatter["date"]; 11 | lang: TPostFrontMatter["lang"]; 12 | } 13 | 14 | function PostMeta({ date, lang }: PostMetaProps) { 15 | return ( 16 |
17 |
23 |
24 | 25 | 26 |
27 |
28 | 29 | {formatLang(lang)} 30 |
31 |
32 |
33 | ); 34 | } 35 | 36 | export default PostMeta; 37 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents-layouts/Project/ProjectFooter.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import { TProjectFrontMatter } from "@/types"; 4 | 5 | interface ProjectFooterProps { 6 | githubUrl?: TProjectFrontMatter["githubUrl"]; 7 | } 8 | 9 | function ProjectFooter({ githubUrl = "" }: ProjectFooterProps) { 10 | if (!githubUrl) return null; 11 | 12 | return ( 13 |
20 |
21 |
22 | Got any feedback?{" "} 23 | 29 | open an issue / discussion here. 30 | 31 |
32 |
33 |
34 | ); 35 | } 36 | 37 | export default ProjectFooter; 38 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents-layouts/Project/ProjectMeta.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import { GitHubIcon, NpmIcon } from "@/components/Icons"; 4 | 5 | import { TProjectFrontMatter } from "@/types"; 6 | 7 | interface ProjectMetaProps { 8 | githubUrl?: TProjectFrontMatter["githubUrl"]; 9 | npmUrl?: TProjectFrontMatter["npmUrl"]; 10 | } 11 | 12 | function ProjectMeta({ githubUrl = "", npmUrl = "" }: ProjectMetaProps) { 13 | if (!githubUrl && !npmUrl) return null; 14 | 15 | return ( 16 |
17 |
23 | {githubUrl && ( 24 | 30 | 31 | GitHub 32 | 33 | )} 34 | {npmUrl && ( 35 | 41 | 42 | npm 43 | 44 | )} 45 |
46 |
47 | ); 48 | } 49 | 50 | export default ProjectMeta; 51 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents-layouts/Project/index.tsx: -------------------------------------------------------------------------------- 1 | import WithReactions from "@/components/layouts/WithReactions"; 2 | import WithTableOfContents from "@/components/layouts/WithTableOfContents"; 3 | import Head from "@/components/meta/Head"; 4 | import SkipNavigation from "@/components/navigations/SkipNavigation"; 5 | import PageHeader from "@/components/PageHeader"; 6 | 7 | import { getPageOgImageUrl } from "@/helpers/page"; 8 | 9 | import ProjectFooter from "@/contents-layouts/Project/ProjectFooter"; 10 | import ProjectMeta from "@/contents-layouts/Project/ProjectMeta"; 11 | 12 | import type { TProjectFrontMatter, TTableOfContents } from "@/types"; 13 | import type { PropsWithChildren } from "react"; 14 | 15 | interface ProjectLayoutProps { 16 | frontMatter: TProjectFrontMatter; 17 | tableOfContents: TTableOfContents; 18 | } 19 | 20 | function ProjectLayout({ 21 | frontMatter: { title, description, caption, githubUrl, npmUrl }, 22 | tableOfContents, 23 | children = null, 24 | }: PropsWithChildren) { 25 | // get og image urls 26 | const image = getPageOgImageUrl({ 27 | caption, 28 | title, 29 | description, 30 | }); 31 | 32 | return ( 33 | <> 34 | 35 | 36 | 37 | 38 | 39 | {children} 40 | 41 | 42 | 43 | 44 | ); 45 | } 46 | 47 | export default ProjectLayout; 48 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/404.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import Link from "next/link"; 3 | 4 | function Error404Contents() { 5 | return ( 6 |
11 |
17 |

18 |
404
19 |
页面未找到
20 |

21 | 28 | 返回首页 29 | 30 |
31 |
32 | ); 33 | } 34 | 35 | export default Error404Contents; 36 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/500.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | function Error500Contents() { 4 | return ( 5 |
10 |
16 |

17 |
500
18 |
服务器错误
19 |

20 |
21 |
22 | ); 23 | } 24 | 25 | export default Error500Contents; 26 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/TIL/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import Contents from "@/contents/TIL/Contents.mdx"; 4 | 5 | function TILContents() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | 13 | export default TILContents; 14 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/feedback/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import TwikooComments from "@/components/TwikooComments"; 4 | 5 | function MessagesContents() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | 13 | export default MessagesContents; 14 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/index/DetailOriented.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import SectionTitle from "@/components/sections/SectionTitle"; 4 | 5 | function DetailOriented() { 6 | return ( 7 |
8 | 13 |
14 | ); 15 | } 16 | 17 | export default DetailOriented; 18 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/index/FeaturedCard.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import type { ReactElement } from "react"; 4 | 5 | interface FeaturedCardProps { 6 | icon: ReactElement; 7 | title: string; 8 | desc: string; 9 | } 10 | 11 | function FeaturedCard({ icon, title, desc }: FeaturedCardProps) { 12 | return ( 13 |
19 |
25 |
31 |
32 |
38 |
{icon}
39 |
45 | {title} 46 |
47 |
48 |
49 |
55 | {desc} 56 |
57 |
58 | ); 59 | } 60 | 61 | export default FeaturedCard; 62 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/index/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import HeaderCta from "@/contents/index/Header/HeaderCta"; 4 | import HeaderImage from "@/contents/index/Header/HeaderImage"; 5 | import HeaderTechStack from "@/contents/index/Header/HeaderTechStack"; 6 | import HeaderTitle from "@/contents/index/Header/HeaderTitle"; 7 | 8 | function Header() { 9 | return ( 10 | 39 | ); 40 | } 41 | 42 | export default Header; 43 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/index/PrettyOptimized.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import SectionTitle from "@/components/sections/SectionTitle"; 4 | 5 | function PrettyOptimized() { 6 | return ( 7 |
8 | 13 |
14 | ); 15 | } 16 | 17 | export default PrettyOptimized; 18 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/index/Quote01.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import { QuoteIcon } from "@/components/Icons"; 4 | 5 | function Quote02() { 6 | return ( 7 |
14 | 21 | 22 | 23 | 使用 24 | 25 | 28 | 35 | 36 | 42 | 博客的力量 43 | 44 | 45 | 52 | 53 | 来记录生活. 54 | 55 |
56 | ); 57 | } 58 | 59 | export default Quote02; 60 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/update/ReleaseNote.mdx: -------------------------------------------------------------------------------- 1 | export function ReleaseNote({ version, date, children }) { 2 | return ( 3 |
4 |
15 | 16 | 📦 {version} 17 | 18 | 📅 {date} 19 |
20 |
{children}
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /apps/gkBlog/src/contents/update/images/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qlAD/gkBlog/87b51fbc835b608626797255749b74ece6aefe4c/apps/gkBlog/src/contents/update/images/og-image.png -------------------------------------------------------------------------------- /apps/gkBlog/src/helpers/api.ts: -------------------------------------------------------------------------------- 1 | import { ContentType, ReactionType, ShareType } from "@prisma/client"; 2 | import axios from "axios"; 3 | 4 | import { TApiResponse } from "@/types"; 5 | 6 | export const postReaction = async ({ 7 | slug, 8 | contentType, 9 | contentTitle, 10 | type, 11 | count, 12 | section, 13 | }: { 14 | slug: string; 15 | contentType: ContentType; 16 | contentTitle: string; 17 | type: ReactionType; 18 | count: number; 19 | section: string; 20 | }) => { 21 | try { 22 | await axios.post(`/api/reactions/${slug}`, { 23 | contentType, 24 | contentTitle, 25 | type, 26 | count, 27 | section, 28 | }); 29 | } catch (err) { 30 | // 31 | } 32 | }; 33 | 34 | export const postShare = async ({ 35 | slug, 36 | contentType, 37 | contentTitle, 38 | type, 39 | }: { 40 | slug: string; 41 | contentType: ContentType; 42 | contentTitle: string; 43 | type: ShareType; 44 | }) => { 45 | try { 46 | await axios.post(`/api/shares/${slug}`, { 47 | contentType, 48 | contentTitle, 49 | type, 50 | }); 51 | } catch (err) { 52 | // 53 | } 54 | }; 55 | 56 | export const postView = async ({ 57 | slug, 58 | contentType, 59 | contentTitle, 60 | }: { 61 | slug: string; 62 | contentType: ContentType; 63 | contentTitle: string; 64 | }) => { 65 | try { 66 | await axios.post(`/api/views/${slug}`, { 67 | contentType, 68 | contentTitle, 69 | }); 70 | } catch (err) { 71 | // 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /apps/gkBlog/src/helpers/date.ts: -------------------------------------------------------------------------------- 1 | export function relativeTime(date: string | number): string { 2 | const current = new Date().getTime(); 3 | const target = new Date(date).getTime(); 4 | const diff = current - target; 5 | 6 | const minutes = Math.floor(diff / (1000 * 60)); 7 | const hours = Math.floor(diff / (1000 * 60 * 60)); 8 | const days = Math.floor(diff / (1000 * 60 * 60 * 24)); 9 | const months = Math.floor(days / 30); 10 | const years = Math.floor(days / 365); 11 | 12 | if (minutes < 1) { 13 | return "几秒前"; 14 | } 15 | if (minutes < 60) { 16 | return `${minutes} 分钟前`; 17 | } 18 | if (hours < 24) { 19 | return `${hours} 小时前`; 20 | } 21 | if (days < 30) { 22 | return `${days} 天前`; 23 | } 24 | if (months < 12) { 25 | return `${months} 个月前`; 26 | } 27 | return `${years} 年前`; 28 | } 29 | -------------------------------------------------------------------------------- /apps/gkBlog/src/helpers/page.ts: -------------------------------------------------------------------------------- 1 | import { getBaseUrl, getParams } from "@/helpers/url"; 2 | 3 | import type { TPageOgImage } from "@/types"; 4 | 5 | export const getPageOgImageUrl = ({ 6 | caption, 7 | title, 8 | description, 9 | }: TPageOgImage) => ({ 10 | default: encodeURI( 11 | `${getBaseUrl()}/api/og-page?${getParams({ caption, title, description })}`, 12 | ), 13 | }); 14 | -------------------------------------------------------------------------------- /apps/gkBlog/src/helpers/server.ts: -------------------------------------------------------------------------------- 1 | import { createHash } from "crypto"; 2 | 3 | import type { NextApiRequest } from "next"; 4 | 5 | export const getSessionId = (req: NextApiRequest) => { 6 | const ipAddress = req.headers["x-forwarded-for"] || "localhost"; 7 | 8 | // hashes the user's IP address and combines it with 9 | // a salt to create a unique session ID that preserves 10 | // the user's privacy by obscuring their IP address. 11 | const currentSessionId = createHash("md5") 12 | .update(ipAddress + process.env.SALT_IP_ADDRESS, "utf-8") 13 | .digest("hex"); 14 | 15 | return currentSessionId; 16 | }; 17 | -------------------------------------------------------------------------------- /apps/gkBlog/src/helpers/url.ts: -------------------------------------------------------------------------------- 1 | export const getBaseUrl = () => "https://www.qladgk.com"; 2 | export const getParams = ( 3 | obj: Record | undefined>, 4 | ) => 5 | Object.entries(obj) 6 | .filter((entry) => entry[1]) 7 | .map(([key, val]) => `${key}=${val}`) 8 | .join("&"); 9 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useAnimateContent.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | import { Content } from "@/contents/index/CleanIntuitive"; 4 | 5 | export const useAnimateContent = (content: Array) => { 6 | const [currentState, setCurrentState] = useState(content[0]); 7 | const [isUserClick, setIsUserClick] = useState(false); 8 | 9 | useEffect(() => { 10 | let animateState: NodeJS.Timeout | null = null; 11 | let timeOutState: NodeJS.Timeout | null = null; 12 | 13 | if (isUserClick) { 14 | timeOutState = setTimeout(() => { 15 | animateState = setInterval(() => { 16 | setCurrentState( 17 | (prev) => 18 | content[ 19 | content.indexOf(prev) < content.length - 1 20 | ? content.indexOf(prev) + 1 21 | : 0 22 | ] 23 | ); 24 | }, 1000); 25 | 26 | setIsUserClick(false); 27 | }, 5000); 28 | } else { 29 | animateState = setInterval(() => { 30 | setCurrentState( 31 | (prev) => 32 | content[ 33 | content.indexOf(prev) < content.length - 1 34 | ? content.indexOf(prev) + 1 35 | : 0 36 | ] 37 | ); 38 | }, 1500); 39 | } 40 | 41 | return () => { 42 | if (animateState) { 43 | clearInterval(animateState); 44 | } 45 | if (timeOutState) { 46 | clearTimeout(timeOutState); 47 | } 48 | }; 49 | }, [content, isUserClick, currentState]); 50 | return { setIsUserClick, currentState, setCurrentState }; 51 | }; 52 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useContentActivity.ts: -------------------------------------------------------------------------------- 1 | import useSWR from "swr"; 2 | 3 | import fetcher from "@/utils/fetcher"; 4 | 5 | import type { TContentActivity } from "@/types"; 6 | 7 | export default function useContentActivity() { 8 | const { 9 | data, 10 | error: isError, 11 | isLoading, 12 | } = useSWR("/api/activity", fetcher, { 13 | fallbackData: [], 14 | }); 15 | 16 | return { 17 | isLoading, 18 | isError, 19 | data, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useContentMeta.ts: -------------------------------------------------------------------------------- 1 | import useSWR from "swr"; 2 | 3 | import fetcher from "@/utils/fetcher"; 4 | 5 | import type { TContentMeta } from "@/types"; 6 | 7 | export default function useContentMeta() { 8 | const { 9 | data, 10 | error: isError, 11 | isLoading, 12 | } = useSWR>("/api/content", fetcher, { 13 | fallbackData: {}, 14 | }); 15 | 16 | return { 17 | isLoading, 18 | isError, 19 | data, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useCurrentUrl.ts: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | 3 | import { getBaseUrl } from "@/helpers/url"; 4 | 5 | export default function useCurrentUrl() { 6 | const { pathname } = useRouter(); 7 | 8 | return `${getBaseUrl()}${pathname}`; 9 | } 10 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useFocusMode.ts: -------------------------------------------------------------------------------- 1 | import useLocalStorageState from "use-local-storage-state"; 2 | 3 | const LOCAL_STORAGE_KEY = "ng-focus-mode"; 4 | 5 | function useFocusMode() { 6 | const [focusMode, setFocusMode] = useLocalStorageState(LOCAL_STORAGE_KEY, { 7 | defaultValue: false, 8 | }); 9 | 10 | return { 11 | focusMode, 12 | setFocusMode, 13 | }; 14 | } 15 | 16 | export default useFocusMode; 17 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useGlobal.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | 3 | import { GlobalStateContext } from "@/providers/GlobalStateProvider"; 4 | 5 | function useGlobal() { 6 | return useContext(GlobalStateContext); 7 | } 8 | 9 | export default useGlobal; 10 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useNewPosts.ts: -------------------------------------------------------------------------------- 1 | import useSWR from "swr"; 2 | 3 | import fetcher from "@/utils/fetcher"; 4 | 5 | export default function useNewPosts() { 6 | const { 7 | data, 8 | error: isError, 9 | isLoading, 10 | } = useSWR< 11 | { 12 | slug: string; 13 | title: string; 14 | createdAt: string; 15 | }[] 16 | >("/api/content/latest", fetcher, { 17 | fallbackData: [], 18 | }); 19 | 20 | return { 21 | isLoading, 22 | isError, 23 | data, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useOnScroll.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function useScroll(threshold = 0) { 4 | const [isScrolled, setScrolled] = useState(); 5 | 6 | useEffect(() => { 7 | const onScroll = () => { 8 | setScrolled(window.scrollY > threshold); 9 | }; 10 | onScroll(); 11 | 12 | document.addEventListener("scroll", onScroll, { passive: true }); 13 | return () => { 14 | document.removeEventListener("scroll", onScroll); 15 | }; 16 | }, [threshold]); 17 | 18 | return isScrolled; 19 | } 20 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useScrollSpy.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function useScrollSpy(): { 4 | currentVisibles: Record; 5 | currentSection: string; 6 | } { 7 | const [currentSection, setCurrentSection] = useState(undefined); 8 | const [currentVisibles, setCurrentVisibles] = useState< 9 | Record 10 | >({}); 11 | 12 | useEffect(() => { 13 | const itemElements = document.querySelectorAll("[data-ss]"); 14 | if (!itemElements.length) return () => {}; 15 | 16 | const observerCallback: IntersectionObserverCallback = (entries) => { 17 | const { target, isIntersecting } = entries[0]; 18 | const slug = target.getAttribute("data-ss") as string; 19 | 20 | setCurrentVisibles((prev) => ({ 21 | ...prev, 22 | [slug]: isIntersecting, 23 | })); 24 | 25 | if (isIntersecting) { 26 | setCurrentSection(slug); 27 | } 28 | }; 29 | 30 | const observers: Array = []; 31 | 32 | itemElements.forEach((item) => { 33 | const threshold: number = Number(item.dataset.ssMt) || 0; 34 | 35 | const observer = new IntersectionObserver(observerCallback, { 36 | rootMargin: `-${threshold}px 0px 0px 0px`, 37 | }); 38 | 39 | observers.push(observer); 40 | observer.observe(item); 41 | }); 42 | 43 | return () => { 44 | observers.forEach((observer) => observer.disconnect); 45 | }; 46 | }, []); 47 | 48 | return { 49 | currentSection, 50 | currentVisibles, 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useShortcut.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | function useShortcut(key: string, callback: (event: KeyboardEvent) => void) { 4 | useEffect(() => { 5 | const handleKeyDown = (event: KeyboardEvent) => { 6 | if (event.code === key) { 7 | callback(event); 8 | } 9 | }; 10 | 11 | window.addEventListener("keydown", handleKeyDown); 12 | return () => { 13 | window.removeEventListener("keydown", handleKeyDown); 14 | }; 15 | }, [key, callback]); 16 | } 17 | 18 | export default useShortcut; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/hooks/useTheme.ts: -------------------------------------------------------------------------------- 1 | import { useTheme as useNextThemes } from "next-themes"; 2 | import { useEffect, useState } from "react"; 3 | 4 | function useTheme() { 5 | const [mounted, setMounted] = useState(false); 6 | const { resolvedTheme, setTheme } = useNextThemes(); 7 | 8 | useEffect(() => { 9 | setMounted(true); 10 | }, []); 11 | 12 | return { 13 | theme: mounted ? resolvedTheme : undefined, 14 | setTheme, 15 | }; 16 | } 17 | 18 | export default useTheme; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/lib/rss.ts: -------------------------------------------------------------------------------- 1 | import RSS from "rss"; 2 | 3 | import { getSortedPosts } from "./posts"; 4 | 5 | const generateRSSFeed = () => { 6 | const feed = new RSS({ 7 | title: "qlAD 的技术笔记", // 你的博客名称 8 | description: "一名小小的计算机爱好者", // 你的博客描述 9 | feed_url: "https://www.qladgk.com/rss.xml", // 这里填写你站点的 RSS 链接 10 | site_url: "https://www.qladgk.com", // 你的站点首页 URL 11 | image_url: "https://www.qladgk.com/favicon.ico", // 你的站点 logo 图片 URL 12 | managingEditor: "editor@www.qladgk.com", 13 | webMaster: "webmaster@www.qladgk.com", 14 | pubDate: new Date(), // 可以使用文章中最新的日期 15 | language: "zh", // 中文 16 | }); 17 | 18 | const posts = getSortedPosts(); 19 | 20 | posts.forEach(({ slug, frontMatter }) => { 21 | feed.item({ 22 | title: frontMatter.title, // 使用文章的标题 23 | description: frontMatter.description, // 使用文章的描述 24 | url: `https://www.qladgk.com/blog/${slug}`, // 每篇文章的 URL 25 | guid: `https://www.qladgk.com/blog/${slug}`, // 一般与 URL 相同,确保唯一 26 | date: new Date(frontMatter.date), // 使用文章的发布日期 27 | categories: frontMatter.tags, // 使用文章的标签作为分类 28 | }); 29 | }); 30 | 31 | return feed.xml(); // 返回生成的 RSS XML 字符串 32 | }; 33 | 34 | export default generateRSSFeed; 35 | -------------------------------------------------------------------------------- /apps/gkBlog/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | import Error404Contents from "@/contents/404"; 4 | 5 | import type { ReactElement } from "react"; 6 | 7 | function Error404() { 8 | return ( 9 | <> 10 | 11 | 页面未找到 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | Error404.getLayout = function getLayout(page: ReactElement) { 21 | return page; 22 | }; 23 | 24 | export default Error404; 25 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/500.tsx: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | import Error500Contents from "@/contents/500"; 4 | 5 | import type { ReactElement } from "react"; 6 | 7 | function Error500() { 8 | return ( 9 | <> 10 | 11 | 服务器错误 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | Error500.getLayout = function getLayout(page: ReactElement) { 21 | return page; 22 | }; 23 | 24 | export default Error500; 25 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import BaiDuAnalytics from "@/components/analytics/BaiduAnalytics"; 2 | import ClarityAnalytics from "@/components/analytics/ClarityAnalytics"; 3 | import GoogleAnalytics from "@/components/analytics/GoogleAnalytics"; 4 | import RootLayout from "@/components/layouts/Root"; 5 | import WithNavigationFooter from "@/components/layouts/WithNavigationFooter"; 6 | import Provider from "@/providers"; 7 | 8 | import type { NextPage } from "next"; 9 | import type { AppProps } from "next/app"; 10 | import type { ReactElement, ReactNode } from "react"; 11 | 12 | import "@/styles/main.css"; 13 | 14 | type NextPageWithLayout

= NextPage & { 15 | getLayout?: (page: ReactElement) => ReactNode; 16 | }; 17 | 18 | type AppPropsWithLayout = AppProps & { 19 | Component: NextPageWithLayout; 20 | }; 21 | 22 | function getDefaultLayout(page: ReactElement): ReactNode { 23 | return {page}; 24 | } 25 | 26 | function App({ Component, pageProps, router }: AppPropsWithLayout) { 27 | let getLayout; 28 | 29 | if (router.query.simpleLayout) { 30 | getLayout = (page: ReactElement) =>

{page}
; 31 | } else if (Component.getLayout) { 32 | getLayout = Component.getLayout; 33 | } else { 34 | getLayout = getDefaultLayout; 35 | } 36 | 37 | return ( 38 | 39 | 40 | {/* eslint-disable-next-line react/jsx-props-no-spreading */} 41 | {getLayout()} 42 | 43 | 44 | 45 | 46 | 47 | ); 48 | } 49 | 50 | export default App; 51 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Head, Html, Main, NextScript } from "next/document"; 2 | 3 | function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | ); 14 | } 15 | 16 | export default Document; 17 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/about-me.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 你好,欢迎!👋 3 | description: 这里是我的个人介绍 4 | layout: PageWithMDX 5 | --- 6 | 7 | 我叫 **qlAD** ,是一名小小的计算机爱好者,热爱技术与创新。可以随时通过社交媒体、电子邮件或电话号码与我取得联系。 8 | 9 | ## 📚 我的技能墙 10 | 11 | - **编程语言**:JavaScript, TypeScript, Python, C 12 | - **数据库**:MySQL, MongoDB 13 | - **其他**:Git, Docker, Linux 14 | 15 | --- 16 | 17 | ## 📬 如何联系我 18 | 19 | - **电子邮件**:qlad_adgk@163.com 20 | - **GitHub**:[github.com/qlAD](https://github.com/qlAD) 21 | 22 | 💡 **提示**:你可以通过以上任意方式与我取得联系,我会尽快回复你! 23 | 24 | --- 25 | 26 | ## 🎯 个人座右铭 27 | 28 | “做技术的黑客心态加上开放共进的态度是成长和越过高山幽谷的秘籍!” 29 | 30 | --- 31 | 32 | ## 🌱 目前在干嘛 33 | 34 | - 考不完的试 35 | - 听不完的课 36 | - 做不完的题 37 | 38 | --- 39 | 40 | ## 📅 最近的项目 41 | 42 | - gkBlog 博客项目 43 | 44 | 感谢你花时间了解我!欢迎随时联系与我讨论更多合作或技术问题 😊 45 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/album.tsx: -------------------------------------------------------------------------------- 1 | import AlbumContents from "@/contents/album"; 2 | import Page from "@/contents-layouts/Page"; 3 | 4 | function Album() { 5 | return ( 6 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default Album; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/activity/index.ts: -------------------------------------------------------------------------------- 1 | import { getContentActivity } from "@/lib/meta"; 2 | 3 | import type { TApiResponse, TContentActivity } from "@/types"; 4 | import type { NextApiRequest, NextApiResponse } from "next"; 5 | 6 | export default async function handler( 7 | req: NextApiRequest, 8 | res: NextApiResponse, 9 | ) { 10 | try { 11 | if (req.method === "GET") { 12 | const contentActivity = await getContentActivity(); 13 | 14 | res.status(200).json(contentActivity); 15 | } else { 16 | res.status(405).json({ message: "Method Not Allowed" }); 17 | } 18 | } catch (err) { 19 | // eslint-disable-next-line no-console 20 | console.log(err); 21 | 22 | res.status(500).json({ message: "Internal Server Error" }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/categories.tsx: -------------------------------------------------------------------------------- 1 | import { getSortedPosts } from "@/lib/posts"; 2 | 3 | import type { NextApiRequest, NextApiResponse } from "next"; 4 | 5 | const handler = async (req: NextApiRequest, res: NextApiResponse) => { 6 | const posts = getSortedPosts(); 7 | const categoryCount: Record = {}; 8 | 9 | posts.forEach((post) => { 10 | const { category } = post.frontMatter; 11 | if (category) { 12 | categoryCount[category] = (categoryCount[category] || 0) + 1; 13 | } 14 | }); 15 | 16 | res.status(200).json(categoryCount); 17 | }; 18 | 19 | export default handler; 20 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/content/[slug].ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | import { getSessionId } from "@/helpers/server"; 4 | import { 5 | getContentMeta, 6 | getReactions, 7 | getReactionsBy, 8 | getSectionMeta, 9 | } from "@/lib/meta"; 10 | 11 | import type { TApiResponse, TContentMetaDetail } from "@/types"; 12 | import type { NextApiRequest, NextApiResponse } from "next"; 13 | 14 | export default async function handler( 15 | req: NextApiRequest, 16 | res: NextApiResponse, 17 | ) { 18 | const slug = z.string().parse(req.query.slug); 19 | const sessionId = getSessionId(req); 20 | 21 | try { 22 | if (req.method === "GET") { 23 | const meta = await getContentMeta(slug); 24 | const metaSection = await getSectionMeta(slug); 25 | const reactionsDetail = await getReactions(slug); 26 | const reactionsDetailUser = await getReactionsBy(slug, sessionId); 27 | 28 | const reactionsSum = 29 | reactionsDetail.AMAZED + 30 | reactionsDetail.CLAPPING + 31 | reactionsDetail.THINKING; 32 | 33 | res.status(200).json({ 34 | meta: { 35 | shares: meta.shares, 36 | views: meta.views, 37 | reactions: reactionsSum, 38 | reactionsDetail, 39 | }, 40 | metaUser: { 41 | reactionsDetail: reactionsDetailUser, 42 | }, 43 | metaSection, 44 | }); 45 | } else { 46 | res.status(405).json({ message: "Method Not Allowed" }); 47 | } 48 | } catch (err) { 49 | // eslint-disable-next-line no-console 50 | console.log(err); 51 | 52 | res.status(500).json({ message: "Internal Server Error" }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/content/index.ts: -------------------------------------------------------------------------------- 1 | import { getAllContentMeta } from "@/lib/meta"; 2 | 3 | import type { TApiResponse, TContentMeta } from "@/types"; 4 | import type { NextApiRequest, NextApiResponse } from "next"; 5 | 6 | export default async function handler( 7 | req: NextApiRequest, 8 | res: NextApiResponse | TApiResponse>, 9 | ) { 10 | try { 11 | if (req.method === "GET") { 12 | const result = await getAllContentMeta(); 13 | 14 | res.status(200).json(result); 15 | } else { 16 | res.status(405).json({ message: "Method Not Allowed" }); 17 | } 18 | } catch (err) { 19 | // eslint-disable-next-line no-console 20 | console.log(err); 21 | 22 | res.status(500).json({ message: "Internal Server Error" }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/content/latest.ts: -------------------------------------------------------------------------------- 1 | import { getNewPosts } from "@/lib/meta"; 2 | 3 | import type { TApiResponse } from "@/types"; 4 | import type { NextApiRequest, NextApiResponse } from "next"; 5 | 6 | export default async function handler( 7 | req: NextApiRequest, 8 | res: NextApiResponse< 9 | | { 10 | slug: string; 11 | title: string; 12 | createdAt: Date; 13 | }[] 14 | | TApiResponse 15 | >, 16 | ) { 17 | try { 18 | if (req.method === "GET") { 19 | const newPosts = await getNewPosts(); 20 | 21 | res.status(200).json(newPosts); 22 | } else { 23 | res.status(405).json({ message: "Method Not Allowed" }); 24 | } 25 | } catch (err) { 26 | // eslint-disable-next-line no-console 27 | console.log(err); 28 | 29 | res.status(500).json({ message: "Internal Server Error" }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/og-page.tsx: -------------------------------------------------------------------------------- 1 | import { ImageResponse } from "@vercel/og"; 2 | 3 | import { PageOgImage } from "@/components/meta/OgImages"; 4 | 5 | import type { NextRequest } from "next/server"; 6 | 7 | export const config = { 8 | runtime: "edge", 9 | }; 10 | 11 | const PlusJakartaSans400 = fetch( 12 | new URL("../../assets/fonts/PlusJakartaSans-Regular.ttf", import.meta.url), 13 | ).then((res) => res.arrayBuffer()); 14 | 15 | const PlusJakartaSans800 = fetch( 16 | new URL("../../assets/fonts/PlusJakartaSans-ExtraBold.ttf", import.meta.url), 17 | ).then((res) => res.arrayBuffer()); 18 | 19 | const OgImage = async (request: NextRequest) => { 20 | const { searchParams } = new URL(request.url); 21 | const get = (param: string): string => searchParams.get(param) || ""; 22 | 23 | try { 24 | const caption = get("caption"); 25 | const title = get("title"); 26 | const description = get("description"); 27 | 28 | const font400 = await PlusJakartaSans400; 29 | const font800 = await PlusJakartaSans800; 30 | 31 | return new ImageResponse( 32 | , 33 | { 34 | width: 1200, 35 | height: 630, 36 | emoji: "fluent", 37 | fonts: [ 38 | { 39 | data: font400, 40 | name: "Plus Jakarta Sans", 41 | style: "normal", 42 | weight: 400, 43 | }, 44 | { 45 | data: font800, 46 | name: "Plus Jakarta Sans", 47 | style: "normal", 48 | weight: 800, 49 | }, 50 | ], 51 | }, 52 | ); 53 | } catch (e) { 54 | return new Response(`Failed to generate the image`, { 55 | status: 500, 56 | }); 57 | } 58 | }; 59 | 60 | export default OgImage; 61 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/shares/[slug].ts: -------------------------------------------------------------------------------- 1 | import { ContentType, ShareType } from "@prisma/client"; 2 | import { z } from "zod"; 3 | 4 | import { getSessionId } from "@/helpers/server"; 5 | import { getSharesBy, setShare } from "@/lib/meta"; 6 | 7 | import { MAX_SHARES_PER_SESSION } from "@/constants/app"; 8 | 9 | import type { NextApiRequest, NextApiResponse } from "next"; 10 | 11 | export default async function handler( 12 | req: NextApiRequest, 13 | res: NextApiResponse, 14 | ) { 15 | const slug = z.string().parse(req.query.slug); 16 | const sessionId = getSessionId(req); 17 | 18 | try { 19 | if (req.method === "POST") { 20 | const contentType = z.nativeEnum(ContentType).parse(req.body.contentType); 21 | const contentTitle = z.string().parse(req.body.contentTitle); 22 | const type = z.nativeEnum(ShareType).parse(req.body.type); 23 | const currentShares = await getSharesBy(slug, sessionId); 24 | 25 | if (currentShares < MAX_SHARES_PER_SESSION) { 26 | await setShare({ 27 | slug, 28 | contentType, 29 | contentTitle, 30 | sessionId, 31 | type, 32 | }); 33 | 34 | res.status(200).json({ message: "Success" }); 35 | } else { 36 | res.status(403).json({ message: "Max limit reached" }); 37 | } 38 | } else { 39 | res.status(405).json({ message: "Method Not Allowed" }); 40 | } 41 | } catch (err) { 42 | // eslint-disable-next-line no-console 43 | console.log(err); 44 | 45 | res.status(500).json({ message: "Internal Server Error" }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/tags.tsx: -------------------------------------------------------------------------------- 1 | import { getSortedPosts } from "@/lib/posts"; 2 | 3 | import type { NextApiRequest, NextApiResponse } from "next"; 4 | 5 | const handler = (req: NextApiRequest, res: NextApiResponse) => { 6 | const posts = getSortedPosts(); 7 | const tagCount: Record = {}; 8 | 9 | posts.forEach((post) => { 10 | post.frontMatter.tags?.forEach((tag: string) => { 11 | tagCount[tag] = (tagCount[tag] || 0) + 1; 12 | }); 13 | }); 14 | 15 | res.status(200).json(tagCount); 16 | }; 17 | 18 | export default handler; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/api/views/[slug].ts: -------------------------------------------------------------------------------- 1 | import { ContentType } from "@prisma/client"; 2 | import { z } from "zod"; 3 | 4 | import { getSessionId } from "@/helpers/server"; 5 | import { getViewsBy, setView } from "@/lib/meta"; 6 | 7 | import { MAX_VIEWS_PER_SESSION } from "@/constants/app"; 8 | 9 | import type { NextApiRequest, NextApiResponse } from "next"; 10 | 11 | export default async function handler( 12 | req: NextApiRequest, 13 | res: NextApiResponse, 14 | ) { 15 | const slug = z.string().parse(req.query.slug); 16 | const sessionId = getSessionId(req); 17 | 18 | try { 19 | if (req.method === "POST") { 20 | const contentType = z.nativeEnum(ContentType).parse(req.body.contentType); 21 | const contentTitle = z.string().parse(req.body.contentTitle); 22 | const currentViews = await getViewsBy(slug, sessionId); 23 | 24 | if (currentViews < MAX_VIEWS_PER_SESSION) { 25 | await setView({ 26 | slug, 27 | contentType, 28 | contentTitle, 29 | sessionId, 30 | }); 31 | 32 | res.status(200).json({ message: "Success" }); 33 | } else { 34 | res.status(403).json({ message: "Max limit reached" }); 35 | } 36 | } else { 37 | res.status(405).json({ message: "Method Not Allowed" }); 38 | } 39 | } catch (err) { 40 | // eslint-disable-next-line no-console 41 | console.log(err); 42 | 43 | res.status(500).json({ message: "Internal Server Error" }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/blog.tsx: -------------------------------------------------------------------------------- 1 | import { getSortedPosts } from "@/lib/posts"; 2 | 3 | import BlogContents from "@/contents/blog"; 4 | import Page from "@/contents-layouts/Page"; 5 | 6 | import type { BlogContentsProps } from "@/contents/blog"; 7 | import type { GetStaticProps } from "next"; 8 | 9 | type BlogProps = { 10 | posts: BlogContentsProps["posts"]; 11 | }; 12 | 13 | function Blog({ posts }: BlogProps) { 14 | return ( 15 | 21 | 22 | 23 | ); 24 | } 25 | 26 | export const getStaticProps: GetStaticProps = async () => { 27 | const allPostsData = getSortedPosts(); 28 | 29 | return { 30 | props: { 31 | posts: allPostsData, 32 | }, 33 | }; 34 | }; 35 | 36 | export default Blog; 37 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/blog/the-2023-retrospective/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2023 年回顾 🤟 3 | description: 自由项目、工作空间、内容创建、个人网站等。 4 | date: "2023-11-02" 5 | lang: zh 6 | tags: 7 | - 年度总结 8 | - 回顾 9 | category: 回顾 10 | cover: https://cdn.qladgk.com/images/20250508165240204.png 11 | --- 12 | 13 | import Image from "@/components/mdx/Image"; 14 | 15 | cover 22 | 23 | ### 网站使用从 hugo 换到了 nextjs 24 | 25 | 经过一段时间的使用,发现 nextjs 对于静态网站的开发更加灵活,可以更加自由地定制网站的样式和功能。 26 | 27 | ### 从 md 到 mdx,内容还未迁移完成 28 | 29 | mdx 是一个 markdown 扩展,可以更加方便地编写内容,比如插入代码、图片、公式等。但是内容迁移还需要一段时间,所以文章数比较少。 30 | 31 | ### 新的域名 qladgk.com 32 | 33 | 从 qlad.blog 到 qladgk.com。其实早就想换域名了,但是 qlad.com 已经被注册了,所以一直没有动静。 34 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/copyright.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 版权信息 3 | description: 版权信息最新更新时间:2025 年 05 月 05 日 4 | layout: PageWithMDX 5 | --- 6 | 7 | ## 版权协议 8 | 9 | 为了保持文章质量,并保持互联网的开放共享精神,保持页面流量的稳定,综合考虑下本站的所有原创文章均采用 [CC 署名-非商业性使用-禁止演绎 4.0 国际](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh-hans) 标准。这篇文章主要想能够更加清楚明白地介绍本站的协议标准和要求,方便你合理地使用本站的文章。 10 | 11 | 本站无广告嵌入和商业行为。违反协议的行为不仅会损害原作者的创作热情,而且会影响整个版权环境。强烈呼吁你在转载时遵守协议。遵守协议的行为几乎不会对你的目标产生负面影响,鼓励创作环境是每个创作者的期望。 12 | 13 | ## 哪些文章适于本协议? 14 | 15 | 所有原创内容均在文章标题顶部,以及文章结尾的版权标签说明部分展示。 16 | 17 | - **原创内容的非商用转载**:必须为完整转载,并且标注出处的完整 URL 链接或访问原文相关字样的超链接。 18 | - **作为参考资料**:无需完整转载,可摘录所需部分,但需标注出处。 19 | 20 | ## 你可以做什么? 21 | 22 | 只要你遵守本页的许可,你可以自由地共享文章内容——在任何媒介以任何形式复制、发行本作品,无需通知作者。 23 | 24 | ## 你需要遵守的许可 25 | 26 | ### 署名 27 | 28 | 你必须标注内容来源,并在文章开头部分(或明显位置)提供原文章的链接(建议使用超链接提升阅读体验)。 29 | 30 | ### 禁止商用 31 | 32 | 本站内容免费向互联网所有用户提供,分享本站文章时 **禁止商业性使用**,禁止在转载页面中插入广告(如 Google 广告、百度广告),禁止使用阅读拦截行为(如要求关注公众号、下载 App 才能观看文章)。 33 | 34 | ### 禁止演绎 35 | 36 | - **作为参考资料截取部分内容**:可以无需完整转载,但需标注出处。 37 | - **分享全部内容(无修改)**:需要在文章开头部分(或明显位置)标注原文章链接(建议使用超链接)。 38 | - **分享部分截取内容或衍生创作**:本站原创文章的衍生品 **禁止公开分享和分发**。如有更好的修改建议,可以在对应文章下留言。如需衍生创作,请在评论中联系。 39 | 40 | ## 版权保护内容 41 | 42 | 包括但不限于: 43 | 44 | - 文章标题和正文 45 | - 站点图片素材 46 | 47 | ## 例外情况 48 | 49 | 本着友好互助的原则,被本站友链收录的博客允许博客文章内容的衍生品分享和分发,但仍需标注出处。 50 | 51 | 如需衍生创作授权,可以在博客文章下方留言,并标注你的网站地址。 52 | 53 | **禁止多篇文章的批量转载。** 本站文章仅发布于本站。如有侵权,请联系举报邮箱:qlad_adgk@163.com。 54 | 55 | ## 网站源代码协议 56 | 57 | 网站源代码采用 **MIT 协议**。 58 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/credits.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 致谢 3 | description: 非常感谢所有促成这个网站创作的人! 4 | layout: PageWithMDX 5 | --- 6 | 7 | import UserProfileGrid from "@/components/UserProfileGrid"; 8 | 9 | ## 赞助者 10 | 11 | 感谢打赏的人,因为你们,让我感受到写博客这件事情能够给你们创造了价值。这会让我在这条路上走得更远。 12 | 13 | 30 | 31 | --- 32 | 33 | ## 贡献者 34 | 35 | —— 暂时还没有贡献者。 36 | 37 | [如何成为贡献者?](https://github.com/qlad/gkBlog/blob/main/CONTRIBUTING.md) 38 | 39 | --- 40 | 41 | ## 特别感谢 🙌 42 | 43 | 我最感激的是: 44 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/essay.tsx: -------------------------------------------------------------------------------- 1 | import EssayContents from "@/contents/essay"; 2 | import Page from "@/contents-layouts/Page"; 3 | 4 | function Essay() { 5 | return ( 6 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default Essay; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/feedback.tsx: -------------------------------------------------------------------------------- 1 | import MessagesContents from "@/contents/feedback"; 2 | import Page from "@/contents-layouts/Page"; 3 | 4 | function Messages() { 5 | return ( 6 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default Messages; 19 | -------------------------------------------------------------------------------- /apps/gkBlog/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Head from "@/components/meta/Head"; 2 | 3 | import { getBaseUrl } from "@/helpers/url"; 4 | 5 | import IndexContents from "@/contents/index"; 6 | 7 | function Index() { 8 | const baseUrl = getBaseUrl(); 9 | 10 | const jsonLd = { 11 | "@context": "https://schema.org", 12 | "@type": "WebSite", 13 | name: "qlAD的技术笔记", 14 | description: 15 | "记录日常学习与开发中的点滴收获。分享编程实践、学习笔记和个人感悟,希望与同行共同进步,一起探索技术世界。", 16 | url: baseUrl, 17 | publisher: { 18 | "@type": "Person", 19 | name: "qlAD", 20 | url: `${baseUrl}/about-me`, 21 | }, 22 | author: { 23 | "@type": "Person", 24 | name: "qlAD", 25 | url: `${baseUrl}/about-me`, 26 | }, 27 | sameAs: ["https://github.com/qlAD"], 28 | }; 29 | 30 | return ( 31 | <> 32 |