From 2e16e75be918ed0244a0b1b679d8e938dabec492 Mon Sep 17 00:00:00 2001 From: Duyet Le Date: Fri, 1 Nov 2024 13:07:00 +0700 Subject: [PATCH] feat(blog): update home --- .../design-patterns-he-thong-23-mau-design.md | 3 +- .../02/linux-giao-dien-phang-cho-ubuntu.md | 1 + apps/blog/_posts/2015/02/phpmyadmin.md | 1 + apps/blog/_posts/2015/02/waterfall.md | 2 +- ...igdata-cai-dat-apache-spark-tren-ubuntu.md | 2 +- ...h-thac-nuoc-mo-hinh-mau-mo-hinh-xoan-oc.md | 1 + ...g-data-explained-in-less-than-2-minutes.md | 2 +- ...ta-getting-started-with-spark-in-python.md | 2 +- .../04/database-tim-hieu-ve-csdl-redis.md | 2 +- ...mongodb-cach-thiet-lap-e-app-server-ket.md | 2 +- ...pen-source-tim-hieu-ve-giay-phep-apache.md | 2 +- ...php-bai-1-tong-quan-ve-web-va-thiet-lap.md | 3 +- ...-chat-trong-viec-theo-doi-tien-do-du-an.md | 3 +- .../2015/04/tim-hieu-ve-giay-phep-gnu.md | 1 - .../2015/04/tim-hieu-ve-giay-phep-mit.md | 2 +- ...big-data-monitoring-spark-with-graphite.md | 2 +- .../web-20-nen-tang-blogging-va-publishing.md | 3 +- ...developer-roadshow-ho-chi-minh-viet-nam.md | 2 +- .../11/google-big-data-meetup-in-saigon.md | 2 +- .../_posts/2015/12/angular-2-co-gi-moi.md | 2 +- .../2015/12/docker-la-gi-co-ban-ve-docker.md | 1 - .../12/map-reduce-va-bai-toan-wordcount.md | 2 +- .../02/columnar-database-va-graph-database.md | 2 - .../02/docker-cai-at-odoo-89-tren-docker.md | 3 - .../2016/02/game-boy-emulator-in-terminal.md | 2 +- apps/blog/_posts/2016/02/graph-database.md | 4 +- .../blog/_posts/2016/05/dockerizing-nodejs.md | 1 - ...hieu-ve-du-lieu-trong-the-thao-hien-dai.md | 1 - .../_posts/2016/07/javascript-weekly-7_22.md | 1 - apps/blog/_posts/2016/10/try-ubuntu-on-web.md | 1 - apps/blog/_posts/2017/01/botpress-p2.md | 6 +- apps/blog/_posts/2017/01/botpress.md | 9 ++- apps/blog/_posts/2017/07/urls-are-ui.md | 1 - apps/blog/_posts/2018/11/api.duyet.net.md | 10 +-- .../_posts/2019/05/pricetrack-cashback.md | 3 - .../2019/08/migrate-blogger-to-gatsby.md | 2 +- apps/blog/_posts/2021/08/zx.md | 1 - apps/blog/_posts/2022/08/rust-indoc.md | 2 +- apps/blog/_posts/2022/08/rust-rayon.md | 2 +- .../_posts/2023/05/migrate-blog-to-nextjs.md | 2 - .../app/[year]/[month]/[slug]/meta/meta.tsx | 5 +- apps/blog/app/feed/page.tsx | 44 +++++++++++++ apps/blog/app/page.tsx | 61 +++++++++--------- apps/blog/app/tags/page.tsx | 11 ++-- apps/blog/components/year-post.tsx | 10 ++- packages/components/CommentContent.tsx | 2 +- packages/libs/date.test.ts | 64 +++++++++++++++++++ packages/libs/date.ts | 15 +++++ packages/libs/dateRelative.ts | 11 ---- packages/libs/getPost.ts | 13 ++-- packages/libs/index.ts | 2 +- packages/libs/tags.test.ts | 28 ++++++++ packages/libs/tags.ts | 16 +++++ 53 files changed, 259 insertions(+), 119 deletions(-) create mode 100644 apps/blog/app/feed/page.tsx create mode 100644 packages/libs/date.test.ts create mode 100644 packages/libs/date.ts delete mode 100644 packages/libs/dateRelative.ts create mode 100644 packages/libs/tags.test.ts create mode 100644 packages/libs/tags.ts diff --git a/apps/blog/_posts/2015/02/design-patterns-he-thong-23-mau-design.md b/apps/blog/_posts/2015/02/design-patterns-he-thong-23-mau-design.md index 121b38c8..30d86b6e 100644 --- a/apps/blog/_posts/2015/02/design-patterns-he-thong-23-mau-design.md +++ b/apps/blog/_posts/2015/02/design-patterns-he-thong-23-mau-design.md @@ -4,6 +4,7 @@ date: '2015-02-23' author: Duyet tags: - Design Patterns +category: Software Engineering modified_time: '2015-02-23T22:40:07.138+07:00' slug: /2015/02/design-patterns-he-thong-23-mau-design.html description: Hệ thống các mẫu design pattern hiện có 23 mẫu được định nghĩa trong cuốn Design patterns Elements of Reusable Object Oriented Software @@ -17,7 +18,7 @@ Các tác giả của cuốn sách là **Erich Gamma**, **Richard Helm**, **Ralp ## Danh sách 23 mẫu - +
diff --git a/apps/blog/_posts/2015/02/linux-giao-dien-phang-cho-ubuntu.md b/apps/blog/_posts/2015/02/linux-giao-dien-phang-cho-ubuntu.md index 6ee784d3..a86b354f 100644 --- a/apps/blog/_posts/2015/02/linux-giao-dien-phang-cho-ubuntu.md +++ b/apps/blog/_posts/2015/02/linux-giao-dien-phang-cho-ubuntu.md @@ -6,6 +6,7 @@ tags: - Linux - Ubuntu - Tools +category: Linux modified_time: '2015-02-17T19:48:16.078+07:00' thumbnail: https://4.bp.blogspot.com/-NPt92Fq9HCQ/VOMvXySpZSI/AAAAAAAACIA/12wdtDOP7ZA/s1600/Screenshot%2Bfrom%2B2015-02-17%2B19%3A07%3A47.png slug: /2015/02/linux-giao-dien-phang-cho-ubuntu.html diff --git a/apps/blog/_posts/2015/02/phpmyadmin.md b/apps/blog/_posts/2015/02/phpmyadmin.md index 7f0cdcf1..88fcd5a9 100644 --- a/apps/blog/_posts/2015/02/phpmyadmin.md +++ b/apps/blog/_posts/2015/02/phpmyadmin.md @@ -6,6 +6,7 @@ tags: - SQL - PHPMyAdmin - MySQL +category: Software Engineering modified_time: '2015-02-15T23:05:02.138+07:00' thumbnail: https://1.bp.blogspot.com/-RIl_Pz6Y1Fo/VODDEddfGiI/AAAAAAAACHw/wibuZ6SUfAQ/s1600/Screenshot%2Bfrom%2B2015-02-15%2B22%3A59%3A44.png slug: /2015/02/phpmyadmin.html diff --git a/apps/blog/_posts/2015/02/waterfall.md b/apps/blog/_posts/2015/02/waterfall.md index 7ae05403..0a3c8636 100644 --- a/apps/blog/_posts/2015/02/waterfall.md +++ b/apps/blog/_posts/2015/02/waterfall.md @@ -3,9 +3,9 @@ title: Mô hình thác nước (Waterfall Model) date: '2015-02-24' author: Duyet tags: - - Phát triển phần mềm - Software Engineering - Software + - Design Patterns modified_time: '2015-03-14T01:06:34.258+07:00' slug: /2015/02/waterfall.html category: Software Engineering diff --git a/apps/blog/_posts/2015/03/bigdata-cai-dat-apache-spark-tren-ubuntu.md b/apps/blog/_posts/2015/03/bigdata-cai-dat-apache-spark-tren-ubuntu.md index 2bcbbcbe..a30b98f9 100644 --- a/apps/blog/_posts/2015/03/bigdata-cai-dat-apache-spark-tren-ubuntu.md +++ b/apps/blog/_posts/2015/03/bigdata-cai-dat-apache-spark-tren-ubuntu.md @@ -6,7 +6,7 @@ tags: - Apache Spark - Apache Hadoop - Python - - BigData + - Big Data modified_time: '2018-09-01T22:28:00.347+07:00' thumbnail: https://1.bp.blogspot.com/-Ruz5XvIPJZo/VS5s2ElpdQI/AAAAAAAACQ0/G7LCMJ0klNk/s1600/download-spark.png slug: /2015/03/bigdata-cai-dat-apache-spark-tren-ubuntu.html diff --git a/apps/blog/_posts/2015/03/so-sanh-cac-mo-hinh-thac-nuoc-mo-hinh-mau-mo-hinh-xoan-oc.md b/apps/blog/_posts/2015/03/so-sanh-cac-mo-hinh-thac-nuoc-mo-hinh-mau-mo-hinh-xoan-oc.md index b16beae5..f5b2d5d0 100644 --- a/apps/blog/_posts/2015/03/so-sanh-cac-mo-hinh-thac-nuoc-mo-hinh-mau-mo-hinh-xoan-oc.md +++ b/apps/blog/_posts/2015/03/so-sanh-cac-mo-hinh-thac-nuoc-mo-hinh-mau-mo-hinh-xoan-oc.md @@ -4,6 +4,7 @@ date: '2015-03-15' author: Duyet tags: - Software Engineering + - Design Patterns modified_time: '2015-03-15T23:58:50.492+07:00' slug: /2015/03/so-sanh-cac-mo-hinh-thac-nuoc-mo-hinh-mau-mo-hinh-xoan-oc.html category: Software Engineering diff --git a/apps/blog/_posts/2015/04/big-data-explained-in-less-than-2-minutes.md b/apps/blog/_posts/2015/04/big-data-explained-in-less-than-2-minutes.md index 3af09c33..0c324045 100644 --- a/apps/blog/_posts/2015/04/big-data-explained-in-less-than-2-minutes.md +++ b/apps/blog/_posts/2015/04/big-data-explained-in-less-than-2-minutes.md @@ -3,7 +3,7 @@ title: Big Data - Explained in Less Than 2 Minutes - To Absolutely Anyone date: '2015-04-12' author: Duyet tags: - - BigData + - Big Data modified_time: '2015-04-12T18:28:37.128+07:00' thumbnail: https://2.bp.blogspot.com/-91L8Jd3M3u4/VSpWUia7JaI/AAAAAAAACQY/LcrkDeteKiA/s1600/AAEAAQAAAAAAAAMxAAAAJDk1ZTU1YTg0LWU0ZGQtNDRiYi1iM2UxLWNmY2FhYjhiMzgxMQ.jpg slug: /2015/04/big-data-explained-in-less-than-2-minutes.html diff --git a/apps/blog/_posts/2015/04/bigdata-getting-started-with-spark-in-python.md b/apps/blog/_posts/2015/04/bigdata-getting-started-with-spark-in-python.md index 148591ac..0328fc3e 100644 --- a/apps/blog/_posts/2015/04/bigdata-getting-started-with-spark-in-python.md +++ b/apps/blog/_posts/2015/04/bigdata-getting-started-with-spark-in-python.md @@ -5,7 +5,7 @@ author: Duyet tags: - Python - Apache Spark - - BigData + - Big Data modified_time: '2015-04-18T20:48:17.707+07:00' thumbnail: https://1.bp.blogspot.com/-Y0pygPjEUNs/VTJddlh9IfI/AAAAAAAACTQ/_LKZZPXV9Wk/s1600/delays_large.png slug: /2015/04/bigdata-getting-started-with-spark-in-python.html diff --git a/apps/blog/_posts/2015/04/database-tim-hieu-ve-csdl-redis.md b/apps/blog/_posts/2015/04/database-tim-hieu-ve-csdl-redis.md index 62c1342c..a4140ca1 100644 --- a/apps/blog/_posts/2015/04/database-tim-hieu-ve-csdl-redis.md +++ b/apps/blog/_posts/2015/04/database-tim-hieu-ve-csdl-redis.md @@ -4,7 +4,7 @@ date: '2015-04-06' author: Duyet tags: - Redis - - CSDL + - Database - NoSQL modified_time: '2015-04-06T00:32:31.095+07:00' thumbnail: https://1.bp.blogspot.com/-5k958LlJol8/VSFvGnofvCI/AAAAAAAACOY/WM4CxLtpcOU/s1600/redis.png diff --git a/apps/blog/_posts/2015/04/mongodb-cach-thiet-lap-e-app-server-ket.md b/apps/blog/_posts/2015/04/mongodb-cach-thiet-lap-e-app-server-ket.md index 4c668ce2..f602517b 100644 --- a/apps/blog/_posts/2015/04/mongodb-cach-thiet-lap-e-app-server-ket.md +++ b/apps/blog/_posts/2015/04/mongodb-cach-thiet-lap-e-app-server-ket.md @@ -5,7 +5,7 @@ author: Duyet tags: - Linux - MongoDb -- Server +- Tutorial - Ubuntu modified_time: '2016-02-03T13:05:06.878+07:00' slug: /2015/04/mongodb-cach-thiet-lap-e-app-server-ket.html diff --git a/apps/blog/_posts/2015/04/open-source-tim-hieu-ve-giay-phep-apache.md b/apps/blog/_posts/2015/04/open-source-tim-hieu-ve-giay-phep-apache.md index c7712c39..5360236e 100644 --- a/apps/blog/_posts/2015/04/open-source-tim-hieu-ve-giay-phep-apache.md +++ b/apps/blog/_posts/2015/04/open-source-tim-hieu-ve-giay-phep-apache.md @@ -4,7 +4,7 @@ date: '2015-04-11' author: Duyet tags: - Open Source - - Giấy phép nguồn mở + - License modified_time: '2015-04-11T14:13:30.700+07:00' thumbnail: https://3.bp.blogspot.com/-1HhLBU4pQYg/VSi7A9h4lRI/AAAAAAAACPo/ujnaYYl6GV4/s1600/mantle-asf.png slug: /2015/04/open-source-tim-hieu-ve-giay-phep-apache.html diff --git a/apps/blog/_posts/2015/04/php-bai-1-tong-quan-ve-web-va-thiet-lap.md b/apps/blog/_posts/2015/04/php-bai-1-tong-quan-ve-web-va-thiet-lap.md index 4a3d8efc..3bd77bd1 100644 --- a/apps/blog/_posts/2015/04/php-bai-1-tong-quan-ve-web-va-thiet-lap.md +++ b/apps/blog/_posts/2015/04/php-bai-1-tong-quan-ve-web-va-thiet-lap.md @@ -3,7 +3,8 @@ title: PHP - Tổng quan về Web và thiết lập môi trường để lập t date: '2015-04-16' author: Duyet tags: - - Training + - Web + - Tutorial - PHP modified_time: '2015-04-18T20:57:32.802+07:00' thumbnail: https://4.bp.blogspot.com/-QxU1LVBUcsA/VS6XNXt1ozI/AAAAAAAACRk/Og_wF5j7WDM/s1600/mohinh01.jpg diff --git a/apps/blog/_posts/2015/04/slack-cong-cu-chat-trong-viec-theo-doi-tien-do-du-an.md b/apps/blog/_posts/2015/04/slack-cong-cu-chat-trong-viec-theo-doi-tien-do-du-an.md index c5e5fc0e..77fa40d3 100644 --- a/apps/blog/_posts/2015/04/slack-cong-cu-chat-trong-viec-theo-doi-tien-do-du-an.md +++ b/apps/blog/_posts/2015/04/slack-cong-cu-chat-trong-viec-theo-doi-tien-do-du-an.md @@ -3,8 +3,7 @@ title: Slack - công cụ chat trong việc theo dõi tiến độ công việc date: '2015-04-26' author: Duyet tags: - - Chat - - Github + - Tools modified_time: '2015-04-26T00:42:36.740+07:00' thumbnail: https://4.bp.blogspot.com/-L2pkSjtbhqQ/VTvQbexFy_I/AAAAAAAACWU/cUhMb50WKnA/s1600/2377299_slack-500.jpg slug: /2015/04/slack-cong-cu-chat-trong-viec-theo-doi-tien-do-du-an.html diff --git a/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-gnu.md b/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-gnu.md index 7623626c..0c68b209 100644 --- a/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-gnu.md +++ b/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-gnu.md @@ -4,7 +4,6 @@ date: '2015-04-11' author: Duyet tags: - Open Source - - Giấy phép nguồn mở - License modified_time: '2015-04-11T13:03:51.623+07:00' thumbnail: https://4.bp.blogspot.com/-LlEOmpqG7Dg/VSi4YDNEClI/AAAAAAAACPU/VZ-xgKDBd8E/s1600/719px-gnu_general_public_license_3_logo-svg2.png diff --git a/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-mit.md b/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-mit.md index 84cb13bb..9e563319 100644 --- a/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-mit.md +++ b/apps/blog/_posts/2015/04/tim-hieu-ve-giay-phep-mit.md @@ -4,7 +4,7 @@ date: '2015-04-11' author: Duyet tags: - Open Source - - Giấy phép nguồn mở + - License - MIT modified_time: '2015-04-11T13:08:57.544+07:00' slug: /2015/04/tim-hieu-ve-giay-phep-mit.html diff --git a/apps/blog/_posts/2015/07/big-data-monitoring-spark-with-graphite.md b/apps/blog/_posts/2015/07/big-data-monitoring-spark-with-graphite.md index 62122370..3ac57e58 100644 --- a/apps/blog/_posts/2015/07/big-data-monitoring-spark-with-graphite.md +++ b/apps/blog/_posts/2015/07/big-data-monitoring-spark-with-graphite.md @@ -5,7 +5,7 @@ author: Duyet tags: - Apache Spark - Apache Spark - - BigData + - Big Data modified_time: '2015-07-14T13:00:07.257+07:00' thumbnail: https://3.bp.blogspot.com/-ytrI0VvmxgE/VaSiReFjsmI/AAAAAAAACl0/JSOfOs9-Pas/s1600/ss-tasks-3.png slug: /2015/07/big-data-monitoring-spark-with-graphite.html diff --git a/apps/blog/_posts/2015/07/web-20-nen-tang-blogging-va-publishing.md b/apps/blog/_posts/2015/07/web-20-nen-tang-blogging-va-publishing.md index 704bdbd9..9fa95bcf 100644 --- a/apps/blog/_posts/2015/07/web-20-nen-tang-blogging-va-publishing.md +++ b/apps/blog/_posts/2015/07/web-20-nen-tang-blogging-va-publishing.md @@ -3,8 +3,7 @@ title: Web - 20 nền tảng blogging và publishing tốt nhất trong năm 201 date: '2015-07-20' author: Duyet tags: - - Blog - - Top + - Web modified_time: '2015-07-20T23:08:05.936+07:00' slug: /2015/07/web-20-nen-tang-blogging-va-publishing.html category: Web diff --git a/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md b/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md index 651441e9..58bf17f5 100644 --- a/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md +++ b/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md @@ -5,7 +5,7 @@ title: date: '2015-08-27' author: Duyet tags: - - Roadshow + - Events - Google - Google Cloud modified_time: '2015-08-28T23:34:31.605+07:00' diff --git a/apps/blog/_posts/2015/11/google-big-data-meetup-in-saigon.md b/apps/blog/_posts/2015/11/google-big-data-meetup-in-saigon.md index 63122b40..2c349a4a 100644 --- a/apps/blog/_posts/2015/11/google-big-data-meetup-in-saigon.md +++ b/apps/blog/_posts/2015/11/google-big-data-meetup-in-saigon.md @@ -5,7 +5,7 @@ author: Duyet tags: - Events - Google - - BigData + - Big Data modified_time: '2016-04-04T17:00:42.706+07:00' slug: /2015/11/google-big-data-meetup-in-saigon.html category: News diff --git a/apps/blog/_posts/2015/12/angular-2-co-gi-moi.md b/apps/blog/_posts/2015/12/angular-2-co-gi-moi.md index de911875..0b4c30ae 100644 --- a/apps/blog/_posts/2015/12/angular-2-co-gi-moi.md +++ b/apps/blog/_posts/2015/12/angular-2-co-gi-moi.md @@ -3,7 +3,7 @@ title: Angular 2 có gì mới? date: '2015-12-20' author: Duyet tags: - - JavaScript Framework + - Javascript Framework - Javascript modified_time: '2016-01-11T02:00:01.346+07:00' thumbnail: https://1.bp.blogspot.com/-ns1tQ1-Aw4E/VnZPOxT1x7I/AAAAAAAAMGI/0am16xApXRU/s1600/angularjs_logo.svg_-650x401.png diff --git a/apps/blog/_posts/2015/12/docker-la-gi-co-ban-ve-docker.md b/apps/blog/_posts/2015/12/docker-la-gi-co-ban-ve-docker.md index d46db040..8e93c85f 100644 --- a/apps/blog/_posts/2015/12/docker-la-gi-co-ban-ve-docker.md +++ b/apps/blog/_posts/2015/12/docker-la-gi-co-ban-ve-docker.md @@ -4,7 +4,6 @@ date: '2015-12-20' author: Duyet tags: - Docker - - Dockerfile modified_time: '2018-09-10T17:28:07.923+07:00' thumbnail: https://4.bp.blogspot.com/-_yUdu_nrol8/VnZeC8EMsdI/AAAAAAAAMG0/Qiij482W6lg/s1600/product%2B-%2Bengine.png slug: /2015/12/docker-la-gi-co-ban-ve-docker.html diff --git a/apps/blog/_posts/2015/12/map-reduce-va-bai-toan-wordcount.md b/apps/blog/_posts/2015/12/map-reduce-va-bai-toan-wordcount.md index cb1532bf..78a3ab5e 100644 --- a/apps/blog/_posts/2015/12/map-reduce-va-bai-toan-wordcount.md +++ b/apps/blog/_posts/2015/12/map-reduce-va-bai-toan-wordcount.md @@ -4,7 +4,7 @@ date: '2015-12-02' author: Duyet tags: - Apache Spark - - BigData + - Big Data - Big Data modified_time: '2016-01-11T02:00:48.839+07:00' thumbnail: https://3.bp.blogspot.com/-i_xNRnGm_pY/Vl8HH5-TM0I/AAAAAAAAKKU/K1W4w2i2f5E/s1600/big-data-cloud-e1383271750410-460x394.png diff --git a/apps/blog/_posts/2016/02/columnar-database-va-graph-database.md b/apps/blog/_posts/2016/02/columnar-database-va-graph-database.md index 0dc592ca..2135eadf 100644 --- a/apps/blog/_posts/2016/02/columnar-database-va-graph-database.md +++ b/apps/blog/_posts/2016/02/columnar-database-va-graph-database.md @@ -4,8 +4,6 @@ date: '2016-02-03' author: Duyet tags: - Database - - Graph - - BigData - Graph Database - Big Data modified_time: '2016-02-03T16:34:19.787+07:00' diff --git a/apps/blog/_posts/2016/02/docker-cai-at-odoo-89-tren-docker.md b/apps/blog/_posts/2016/02/docker-cai-at-odoo-89-tren-docker.md index 3b233829..97bf930a 100644 --- a/apps/blog/_posts/2016/02/docker-cai-at-odoo-89-tren-docker.md +++ b/apps/blog/_posts/2016/02/docker-cai-at-odoo-89-tren-docker.md @@ -5,9 +5,6 @@ author: Duyet tags: - Tutorial - Docker - - Dockerfile - - Odoo - - DevOps modified_time: '2016-02-10T12:46:43.686+07:00' thumbnail: https://3.bp.blogspot.com/-wtT1nv3Ugjw/VrGtMM6_XVI/AAAAAAAAPC8/l7qi3IkqGCg/s1600/odoo-docker-big-_495x160.jpg slug: /2016/02/docker-cai-at-odoo-89-tren-docker.html diff --git a/apps/blog/_posts/2016/02/game-boy-emulator-in-terminal.md b/apps/blog/_posts/2016/02/game-boy-emulator-in-terminal.md index 6d07953c..93acd9d3 100644 --- a/apps/blog/_posts/2016/02/game-boy-emulator-in-terminal.md +++ b/apps/blog/_posts/2016/02/game-boy-emulator-in-terminal.md @@ -3,7 +3,7 @@ title: Game Boy Emulator Terminal date: '2016-02-28' author: Duyet tags: - - Terminal + - Read - PHP modified_time: '2016-05-02T19:41:54.973+07:00' thumbnail: https://4.bp.blogspot.com/-NJDpViHfUg4/VtKOGcA-wEI/AAAAAAAAQes/dI5hCCos2CA/s1600/yq3uxuyqhyfjdb9q460h.gif diff --git a/apps/blog/_posts/2016/02/graph-database.md b/apps/blog/_posts/2016/02/graph-database.md index 91829674..f1493ab3 100644 --- a/apps/blog/_posts/2016/02/graph-database.md +++ b/apps/blog/_posts/2016/02/graph-database.md @@ -4,10 +4,8 @@ date: '2016-02-03' author: Duyet tags: - Database - - Neo4j - - BigData - - Graph Database - Big Data + - Graph Database modified_time: '2016-02-03T17:14:05.023+07:00' thumbnail: https://2.bp.blogspot.com/-Wq61rnHCVQk/VrHL_XD9alI/AAAAAAAAPEE/8DjlqxdZ5dE/s1600/Wikipedia_multilingual_network_graph_July_2013.svg.png slug: /2016/02/graph-database.html diff --git a/apps/blog/_posts/2016/05/dockerizing-nodejs.md b/apps/blog/_posts/2016/05/dockerizing-nodejs.md index 3b39de0e..e258c9b2 100644 --- a/apps/blog/_posts/2016/05/dockerizing-nodejs.md +++ b/apps/blog/_posts/2016/05/dockerizing-nodejs.md @@ -5,7 +5,6 @@ author: Duyet tags: - Node.js - Docker - - Dockerfile - Tutorial modified_time: '2018-09-10T17:23:15.023+07:00' thumbnail: https://1.bp.blogspot.com/-PdJFod9lQSU/VyYyDa_nEnI/AAAAAAAAUaE/CpGySWOh_TMGvZGjYqpcSHtTft7yi7tjwCK4B/s1600/1-_MtS4HqN2srTcrSyet61DQ.jpeg diff --git a/apps/blog/_posts/2016/06/tim-hieu-ve-du-lieu-trong-the-thao-hien-dai.md b/apps/blog/_posts/2016/06/tim-hieu-ve-du-lieu-trong-the-thao-hien-dai.md index a38baaad..eae331c9 100644 --- a/apps/blog/_posts/2016/06/tim-hieu-ve-du-lieu-trong-the-thao-hien-dai.md +++ b/apps/blog/_posts/2016/06/tim-hieu-ve-du-lieu-trong-the-thao-hien-dai.md @@ -3,7 +3,6 @@ title: Tìm hiểu về dữ liệu trong thể thao hiện đại date: '2016-06-29' author: Duyet tags: - - Hệ thống thông tin - Information System - Data modified_time: '2016-06-29T23:08:54.053+07:00' diff --git a/apps/blog/_posts/2016/07/javascript-weekly-7_22.md b/apps/blog/_posts/2016/07/javascript-weekly-7_22.md index 133321ca..f6d58901 100644 --- a/apps/blog/_posts/2016/07/javascript-weekly-7_22.md +++ b/apps/blog/_posts/2016/07/javascript-weekly-7_22.md @@ -9,7 +9,6 @@ tags: - Javascript Weekly - React - Node.js - - Electron modified_time: '2016-07-22T15:14:43.289+07:00' thumbnail: https://4.bp.blogspot.com/-aCVU91X9N2E/V5HPwsra5lI/AAAAAAAAaJU/O6M7sA63ap0c1degbSZcyUTLXnY3hx_AACK4B/s1600/hyperterm.gif slug: /2016/07/javascript-weekly-7_22.html diff --git a/apps/blog/_posts/2016/10/try-ubuntu-on-web.md b/apps/blog/_posts/2016/10/try-ubuntu-on-web.md index f64e7877..98504836 100644 --- a/apps/blog/_posts/2016/10/try-ubuntu-on-web.md +++ b/apps/blog/_posts/2016/10/try-ubuntu-on-web.md @@ -5,7 +5,6 @@ author: Duyet tags: - Open Source - Ubuntu - - Website - Web modified_time: '2016-10-09T00:55:36.863+07:00' thumbnail: https://2.bp.blogspot.com/-N0_V8u-o7Ls/V_kxVyBj8hI/AAAAAAAAe04/A7CAQaAIsiUtb8i1MueiOjg4EVgvrsN9gCLcB/s1600/Screenshot%2Bfrom%2B2016-10-09%2B00-46-15.png diff --git a/apps/blog/_posts/2017/01/botpress-p2.md b/apps/blog/_posts/2017/01/botpress-p2.md index 01699837..562767ef 100644 --- a/apps/blog/_posts/2017/01/botpress-p2.md +++ b/apps/blog/_posts/2017/01/botpress-p2.md @@ -3,9 +3,9 @@ title: 'Chatbot với Botpress - Phần 2: Coding' date: '2017-01-24' author: Duyet tags: - - Javascript Framework - - Javascript - Node.js + - Javascript Framework + - Chatbot modified_time: '2018-09-10T17:24:58.329+07:00' thumbnail: https://3.bp.blogspot.com/-GXx1lZwBtgg/WIbK6HLTO8I/AAAAAAAAimw/B9qbrjjIQIMC2CxXk1O-xqYAbTMOe4rogCLcB/s1600/screenshot-ui.png slug: /2017/01/botpress-p2.html @@ -194,7 +194,7 @@ ChatBot không chỉ phải biết trả lời theo từ khóa mà còn phải h Nếu có thời gian mình sẽ viết 1 bài tự build ra model cho Bot để có thể đọc hiểu và trả lời ở mức cơ bản. -Xem phần 1: [Chatbot với Botpress - Phần 1: Init Chatbot](https://blog.duyet.net/2017/01/botpress.html#.WJP5QxJ97_g) +Xem phần 1: [Chatbot với Botpress - Phần 1: Init Chatbot](https://blog.duyet.net/2017/01/botpress.html) ## Tham khảo diff --git a/apps/blog/_posts/2017/01/botpress.md b/apps/blog/_posts/2017/01/botpress.md index aa3b19c1..92ab1d26 100644 --- a/apps/blog/_posts/2017/01/botpress.md +++ b/apps/blog/_posts/2017/01/botpress.md @@ -25,7 +25,7 @@ Mình thấy Node.js là ngôn ngữ được sử dụng khá phổ biến đ - Trang chủ: [https://botpress.io](https://botpress.io/) -- Xem phần 2: [Chatbot với Botpress - Phần 2: Coding](https://blog.duyet.net/2017/01/botpress-p2.html#.WJP5EhJ97_g) +- Xem phần 2: [Chatbot với Botpress - Phần 2: Coding](https://blog.duyet.net/2017/01/botpress-p2.html) ## Cài đặt và init Bot @@ -100,9 +100,8 @@ Bên dưới là một số mục tùy chọn: - Auto response: Nội dung Auto response - Greeting text: Nội dung chào. - Persistent menu: Menu điều hướng trong Messenger. Có 2 dạng: - -- Postback: một Postback sẽ gọi ra 1 hàm tương ứng. -- URL. + - Postback: một Postback sẽ gọi ra 1 hàm tương ứng. + - URL. Sau khi thiết lập sơ sơ, lưu lại và vào messenger chat thử, mình sẽ giải thích các tùy chọn ở trên như sau: @@ -142,4 +141,4 @@ Botpress khá là hay, giúp ta tạo được bot trong thời gian ngắn, tí Chúc bạn thành công, mọi thắc mắc vui lòng comment tại bên dưới. -Xem tiếp phần 2: [Chatbot với Botpress - Phần 2: Coding](https://blog.duyet.net/2017/01/botpress-p2.html#.WJP5EhJ97_g) +Xem tiếp phần 2: [Chatbot với Botpress - Phần 2: Coding](https://blog.duyet.net/2017/01/botpress-p2.html) diff --git a/apps/blog/_posts/2017/07/urls-are-ui.md b/apps/blog/_posts/2017/07/urls-are-ui.md index 9551fd24..c0bad0dd 100644 --- a/apps/blog/_posts/2017/07/urls-are-ui.md +++ b/apps/blog/_posts/2017/07/urls-are-ui.md @@ -4,7 +4,6 @@ date: '2017-07-20' author: Duyet tags: - Web Design - - Website - UX - Web modified_time: '2017-07-20T22:29:37.063+07:00' diff --git a/apps/blog/_posts/2018/11/api.duyet.net.md b/apps/blog/_posts/2018/11/api.duyet.net.md index d5d87afd..758e677e 100644 --- a/apps/blog/_posts/2018/11/api.duyet.net.md +++ b/apps/blog/_posts/2018/11/api.duyet.net.md @@ -7,13 +7,9 @@ tags: modified_time: '2018-11-18T00:17:49.832+07:00' thumbnail: https://1.bp.blogspot.com/-pkcT4MaSHys/W_BMQuealsI/AAAAAAAA1Ok/ieTSBcaC6u8KEzcVgbDmdS23UOuikzfdACLcBGAs/s720/Screen%2BShot%2B2018-11-18%2Bat%2B12.12.11%2BAM.png slug: '/2018/11/api.duyet.net.html' +category: Project --- -Dìa diaaa, [https://api.duyet.net](https://api.duyet.net/) is now online again! -![](https://1.bp.blogspot.com/-pkcT4MaSHys/W_BMQuealsI/AAAAAAAA1Ok/ieTSBcaC6u8KEzcVgbDmdS23UOuikzfdACLcBGAs/s1600/Screen%2BShot%2B2018-11-18%2Bat%2B12.12.11%2BAM.png) - - +[https://api.duyet.net](https://api.duyet.net/) is now online. -[Make a Request](https://github.com/duyet-website/api.duyet.net/issues/new) about your new API idea, I will make it become true. - -[![](https://2.bp.blogspot.com/-0o5LUYo14zA/W_BNBhGJgtI/AAAAAAAA1Ow/yABIEx60a040NNdniGkylbdaP6Jub0DAACK4BGAYYCw/s320/hell_yeah.jpg)](https://2.bp.blogspot.com/-0o5LUYo14zA/W_BNBhGJgtI/AAAAAAAA1Ow/yABIEx60a040NNdniGkylbdaP6Jub0DAACK4BGAYYCw/s1600/hell_yeah.jpg) +![](https://1.bp.blogspot.com/-pkcT4MaSHys/W_BMQuealsI/AAAAAAAA1Ok/ieTSBcaC6u8KEzcVgbDmdS23UOuikzfdACLcBGAs/s1600/Screen%2BShot%2B2018-11-18%2Bat%2B12.12.11%2BAM.png) diff --git a/apps/blog/_posts/2019/05/pricetrack-cashback.md b/apps/blog/_posts/2019/05/pricetrack-cashback.md index b1bfec37..10cdce1a 100644 --- a/apps/blog/_posts/2019/05/pricetrack-cashback.md +++ b/apps/blog/_posts/2019/05/pricetrack-cashback.md @@ -5,9 +5,6 @@ author: Duyet category: Project tags: - Firebase -- Firebase Functions -- Firebase Hosting -- Side Project - Side Project thumbnail: https://1.bp.blogspot.com/-YI_vbZhajkU/XNl4r1H3CRI/AAAAAAABAgI/eZRSFuf3RXQsltqLb2_ObS_lWlE475n5wCLcBGAs/s1600/screenshot-detail.png diff --git a/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md b/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md index 0445e1d3..d84afa99 100644 --- a/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md +++ b/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md @@ -4,7 +4,7 @@ date: '2019-08-07' author: Duyet category: Story tags: - - Story + - Side Project - Javascript thumbnail: https://images.unsplash.com/photo-1470175369463-7bb9f41e614b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1652&q=80 diff --git a/apps/blog/_posts/2021/08/zx.md b/apps/blog/_posts/2021/08/zx.md index cee1a301..de6a9bcd 100644 --- a/apps/blog/_posts/2021/08/zx.md +++ b/apps/blog/_posts/2021/08/zx.md @@ -5,7 +5,6 @@ author: Duyet category: Productivity tags: - Data Engineering - - Bash - Linux slug: /2021/08/zx.html thumbnail: https://1.bp.blogspot.com/-UxQmomMaIJA/YSn3KPNcrQI/AAAAAAACNMA/nBsVLSi2dYUFx9QK1zWX8-s0ViiNSHLAQCLcBGAsYHQ/s0/zx-thumb.png diff --git a/apps/blog/_posts/2022/08/rust-indoc.md b/apps/blog/_posts/2022/08/rust-indoc.md index 74114c5b..3352999f 100644 --- a/apps/blog/_posts/2022/08/rust-indoc.md +++ b/apps/blog/_posts/2022/08/rust-indoc.md @@ -7,7 +7,7 @@ tags: - Rust - Vietnamese - Rust Tiếng Việt - - Crates + - Rust Crates slug: /2022/08/rust-indoc.html twitterCommentUrl: https://twitter.com/search?q=https%3A%2F%2Fblog.duyet.net%2F2022%2F08%2Frust-indoc.html description: indoc là một crate nhỏ nhưng hữu ích giúp canh lề (indented documents). indoc!() macro nhận multiline string và un-indents lúc compile time, xoá tất cả khoảng trắng đầu tiên trên cách dòng dựa theo dòng đầu tiên. diff --git a/apps/blog/_posts/2022/08/rust-rayon.md b/apps/blog/_posts/2022/08/rust-rayon.md index c91d2dc7..aca4a69e 100644 --- a/apps/blog/_posts/2022/08/rust-rayon.md +++ b/apps/blog/_posts/2022/08/rust-rayon.md @@ -7,7 +7,7 @@ tags: - Rust - Vietnamese - Rust Tiếng Việt - - Crates + - Rust Crates slug: /2022/08/rust-rayon.html twitterCommentUrl: https://twitter.com/search?q=https%3A%2F%2Fblog.duyet.net%2F2022%2F08%2Frust-rayon.html description: rayon là thư viện data-parallelism cho Rust, gọn nhẹ và dễ dàng convert từ code tính toán tuần tự sang song song mà vẫn đảm bảo không lỗi data-race. diff --git a/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md b/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md index d6d2984c..c96e980b 100644 --- a/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md +++ b/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md @@ -6,9 +6,7 @@ category: Project tags: - Side Project - Web - - Blog - React - - Rust - Vercel slug: /2023/05/migrate-blog-to-nextjs.html thumbnail: https://i.imgur.com/980XhnE.png diff --git a/apps/blog/app/[year]/[month]/[slug]/meta/meta.tsx b/apps/blog/app/[year]/[month]/[slug]/meta/meta.tsx index 3dae4f30..fd320109 100644 --- a/apps/blog/app/[year]/[month]/[slug]/meta/meta.tsx +++ b/apps/blog/app/[year]/[month]/[slug]/meta/meta.tsx @@ -1,10 +1,11 @@ +import Link from 'next/link' + import Icons from '@duyet/components/Icons' import type { Post } from '@duyet/interfaces' -import distanceToNow from '@duyet/libs/dateRelative' +import { distanceToNow } from '@duyet/libs/date' import { getSeries } from '@duyet/libs/getSeries' import { getSlug } from '@duyet/libs/getSlug' import { cn } from '@duyet/libs/utils' -import Link from 'next/link' import { SeriesBox } from '../../../../../components/series' interface ContentProps { diff --git a/apps/blog/app/feed/page.tsx b/apps/blog/app/feed/page.tsx new file mode 100644 index 00000000..c712cbec --- /dev/null +++ b/apps/blog/app/feed/page.tsx @@ -0,0 +1,44 @@ +import Link from 'next/link' + +import Container from '@duyet/components/Container' +import Feed from '@duyet/components/Feed' +import Header from '@duyet/components/Header' +import { getAllPosts } from '@duyet/libs/getPost' + +type Params = Promise> + +async function getPosts(params: Params) { + const { page } = await params + const pageNumber = page ? parseInt(page) - 1 : 0 + + return getAllPosts( + [ + 'date', + 'slug', + 'title', + 'excerpt', + 'thumbnail', + 'category', + 'category_slug', + ], + pageNumber * 10 + 10, + ) +} + +export default async function Page({ params }: { params: Params }) { + const posts = await getPosts(params) + + return ( + <> +
+ + + +
+ See more +
+ +
+ + ) +} diff --git a/apps/blog/app/page.tsx b/apps/blog/app/page.tsx index b0d1d639..e3b67948 100644 --- a/apps/blog/app/page.tsx +++ b/apps/blog/app/page.tsx @@ -1,42 +1,43 @@ -import Container from '@duyet/components/Container' -import Feed from '@duyet/components/Feed' -import Header from '@duyet/components/Header' -import { getAllPosts } from '@duyet/libs/getPost' import Link from 'next/link' -type Params = Promise> - -async function getPosts(params: Params) { - const { page } = await params - const pageNumber = page ? parseInt(page) - 1 : 0 +import Container from '@duyet/components/Container' +import Header from '@duyet/components/Header' +import { getPostsByAllYear } from '@duyet/libs/getPost' +import { YearPost } from '../components/year-post' - return getAllPosts( - [ - 'date', - 'slug', - 'title', - 'excerpt', - 'thumbnail', - 'category', - 'category_slug', - ], - pageNumber * 10 + 10, +export default async function Page() { + const postsByYear = getPostsByAllYear(['slug', 'title', 'date', 'category']) + const postCount = Object.values(postsByYear).reduce( + (acc, yearPosts) => acc + yearPosts.length, + 0, ) -} -export default async function Page({ params }: { params: Params }) { - const posts = await getPosts(params) + const years = Object.keys(postsByYear).map(Number) + const pastYears = new Date().getFullYear() - Math.min(...years) return ( <> -
+
- - -
- See more -
- +
+ Lists all {postCount} posts of the past {pastYears} years of blogging. + You can jump straight to the{' '} + + /feed + {' '} + for latest posts or also explore{' '} + + by the topics + + . +
+
+ {Object.keys(postsByYear) + .sort((a: string, b: string) => parseInt(b) - parseInt(a)) + .map((year: string) => ( + + ))} +
) diff --git a/apps/blog/app/tags/page.tsx b/apps/blog/app/tags/page.tsx index 781a6e72..a9be5499 100644 --- a/apps/blog/app/tags/page.tsx +++ b/apps/blog/app/tags/page.tsx @@ -37,7 +37,7 @@ export default function Tags() { {sortedAlpha.map((alpha) => (

{alpha}

- +
))} @@ -45,17 +45,16 @@ export default function Tags() { ) } -function TagCounts({ tags }: { tags: TagCount }) { +function TagList({ tags }: { tags: TagCount }) { return (
{Object.entries(tags).map(([tag, count]) => (
-

{tag}

+

{tag}

({count})
diff --git a/apps/blog/components/year-post.tsx b/apps/blog/components/year-post.tsx index b2e1756b..677245c3 100644 --- a/apps/blog/components/year-post.tsx +++ b/apps/blog/components/year-post.tsx @@ -1,7 +1,9 @@ +import Link from 'next/link' + import type { Post } from '@duyet/interfaces' +import { dateFormat } from '@duyet/libs/date' import { getPostsByYear } from '@duyet/libs/getPost' import { cn } from '@duyet/libs/utils' -import Link from 'next/link' export interface YearPostProps { year: number @@ -35,11 +37,13 @@ export function YearPost({ year, className }: YearPostProps) { className="flex flex-row items-center justify-between gap-2" key={post.slug} > - + {post.title}
- + ))}
diff --git a/packages/components/CommentContent.tsx b/packages/components/CommentContent.tsx index f4d7426d..1bbb5855 100644 --- a/packages/components/CommentContent.tsx +++ b/packages/components/CommentContent.tsx @@ -3,7 +3,7 @@ import Image from "next/image"; import type { Comment } from "@duyet/interfaces"; -import distanceToNow from "@duyet/libs/dateRelative"; +import { distanceToNow } from "@duyet/libs/date"; import { cn } from "@duyet/libs/utils"; type CommentProps = { diff --git a/packages/libs/date.test.ts b/packages/libs/date.test.ts new file mode 100644 index 00000000..23616e18 --- /dev/null +++ b/packages/libs/date.test.ts @@ -0,0 +1,64 @@ +import { distanceFormat, distanceToNow, dateFormat } from './date' + +describe('distanceToNow', () => { + it('should format future date with suffix', () => { + const futureDate = new Date(Date.now() + 24 * 60 * 60 * 1000) // tomorrow + expect(distanceToNow(futureDate)).toBe('in 1 day') + }) + + it('should format past date with suffix', () => { + const pastDate = new Date(Date.now() - 24 * 60 * 60 * 1000) // yesterday + expect(distanceToNow(pastDate)).toBe('1 day ago') + }) + + it('should handle numeric timestamp', () => { + const timestamp = Date.now() - 60 * 60 * 1000 // 1 hour ago + expect(distanceToNow(timestamp)).toBe('1 hour ago') + }) +}) + +describe('distanceFormat', () => { + it('should format distance between two dates', () => { + const date1 = new Date('2024-01-01') + const date2 = new Date('2024-01-02') + expect(distanceFormat(date1, date2)).toBe('1 day') + }) + + it('should format longer time periods', () => { + const date1 = new Date('2024-01-01') + const date2 = new Date('2024-02-01') + expect(distanceFormat(date1, date2)).toBe('about 1 month') + }) + + it('should handle same dates', () => { + const date = new Date('2024-01-01') + expect(distanceFormat(date, date)).toBe('less than a minute') + }) +}) + +describe('dateFormat', () => { + it('should format date with yyyy-MM-dd pattern', () => { + const date = new Date('2024-03-15') + expect(dateFormat(date, 'yyyy-MM-dd')).toBe('2024-03-15') + }) + + it('should format date with dd/MM/yyyy pattern', () => { + const date = new Date('2024-03-15') + expect(dateFormat(date, 'dd/MM/yyyy')).toBe('15/03/2024') + }) + + it('should format date with time using HH:mm pattern', () => { + const date = new Date('2024-03-15T14:30:00') + expect(dateFormat(date, 'HH:mm')).toBe('14:30') + }) + + it('should format full date and time', () => { + const date = new Date('2024-03-15T14:30:00') + expect(dateFormat(date, 'yyyy-MM-dd HH:mm:ss')).toBe('2024-03-15 14:30:00') + }) + + it('should format with custom text pattern', () => { + const date = new Date('2024-03-15') + expect(dateFormat(date, 'MMMM do, yyyy')).toBe('March 15th, 2024') + }) +}) diff --git a/packages/libs/date.ts b/packages/libs/date.ts new file mode 100644 index 00000000..8649c1b0 --- /dev/null +++ b/packages/libs/date.ts @@ -0,0 +1,15 @@ +import { formatDistance, formatDistanceToNowStrict, format } from "date-fns"; + +export function distanceToNow(dateTime: number | Date): string { + return formatDistanceToNowStrict(dateTime, { + addSuffix: true, + }); +} + +export function distanceFormat(from: Date, to: Date): string { + return formatDistance(from, to); +} + +export function dateFormat(date: Date, formatString: string): string { + return format(date, formatString); +} \ No newline at end of file diff --git a/packages/libs/dateRelative.ts b/packages/libs/dateRelative.ts deleted file mode 100644 index 481676fe..00000000 --- a/packages/libs/dateRelative.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { formatDistance, formatDistanceToNowStrict } from "date-fns"; - -export default function distanceToNow(dateTime: number | Date) { - return formatDistanceToNowStrict(dateTime, { - addSuffix: true, - }); -} - -export function distanceFormat(from: Date, to: Date) { - return formatDistance(from, to); -} diff --git a/packages/libs/getPost.ts b/packages/libs/getPost.ts index e77efdbd..628c6fca 100644 --- a/packages/libs/getPost.ts +++ b/packages/libs/getPost.ts @@ -2,6 +2,7 @@ import matter from "gray-matter"; import getSlug from "./getSlug"; import type { TagCount, Post, CategoryCount } from "@duyet/interfaces"; +import { normalizeTag } from "./tags"; const nodeFs = () => require("fs"); const nodeJoin = () => require("path").join; @@ -80,28 +81,28 @@ export function getPostByPath(fullPath: string, fields: string[] = []): Post { } if (field === "title") { - post[field] = data.title; + post["title"] = data.title; } if (field === "path") { - post[field] = fullPath; + post["path"] = fullPath; } if (field === "content") { - post[field] = content; + post["content"] = content; } if (field === "category") { // Some posts have a category of "null" so we need to handle that - post[field] = data.category || post[field]; + post["category"] = data.category || post[field]; } if (field === "category_slug") { - post[field] = getSlug(data.category || post[field]); + post["category_slug"] = getSlug(data.category || post[field]); } if (field === "tags") { - post[field] = data.tags || []; + post["tags"] = (data.tags || []).map(normalizeTag); post["tags_slug"] = post[field].map((tag: string) => getSlug(tag)); } diff --git a/packages/libs/index.ts b/packages/libs/index.ts index eea3d6de..3fd1cdaa 100644 --- a/packages/libs/index.ts +++ b/packages/libs/index.ts @@ -1,6 +1,6 @@ export * from "./clearUrl"; export * from "./comment"; -export * from "./dateRelative"; +export * from "./date"; export * from "./fetcher"; export * from "./getPost"; export * from "./getSlug"; diff --git a/packages/libs/tags.test.ts b/packages/libs/tags.test.ts new file mode 100644 index 00000000..a3e57c31 --- /dev/null +++ b/packages/libs/tags.test.ts @@ -0,0 +1,28 @@ +import { normalizeTag } from './tags'; + +describe('normalizeTag', () => { + it('should capitalize first letter of single word', () => { + expect(normalizeTag('javascript')).toBe('Javascript'); + expect(normalizeTag('JAVASCRIPT')).toBe('Javascript'); + expect(normalizeTag('javaScript')).toBe('Javascript'); + }); + + it('should capitalize first letter of each word', () => { + expect(normalizeTag('javascript framework')).toBe('Javascript Framework'); + expect(normalizeTag('JAVASCRIPT FRAMEWORK')).toBe('Javascript Framework'); + expect(normalizeTag('javaScript frameWork')).toBe('Javascript Framework'); + }); + + it('should handle empty string', () => { + expect(normalizeTag('')).toBe(''); + }); + + it('should handle multiple spaces between words', () => { + expect(normalizeTag('javascript framework')).toBe('Javascript Framework'); + }); + + it('should handle special characters', () => { + expect(normalizeTag('node.js')).toBe('Node.js'); + expect(normalizeTag('c++')).toBe('C++'); + }); +}); \ No newline at end of file diff --git a/packages/libs/tags.ts b/packages/libs/tags.ts new file mode 100644 index 00000000..c1f6e7bb --- /dev/null +++ b/packages/libs/tags.ts @@ -0,0 +1,16 @@ +/** + * Normalizes the tags. e.g. "JavaScript" => "Javascript", "JavaScript framework" => "Javascript Framework", ... + * + * @param tag string + */ +export function normalizeTag(tag: string): string { + const normalizedTag = tag + .split(' ') + .filter((word) => word.length > 0) + .map((word) => { + return word[0].toUpperCase() + word.toLowerCase().substring(1) + }) + .join(' ') + + return normalizedTag +}
STT