Skip to content

Commit

Permalink
✨ Adds Published and Modified Dates (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
payapula authored Jun 10, 2024
1 parent ddd302e commit 12618fa
Show file tree
Hide file tree
Showing 20 changed files with 17,738 additions and 16,751 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ lib
# Refer to comments of this answer = https://stackoverflow.com/a/66260842/5155530
.eslintrc.js
next-sitemap.config.js
next.config.js
next.config.js
scripts/
9 changes: 9 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Check if there are any changes in the "_posts" directory.
if git diff --cached --name-only | grep -q "_posts/"
then
# Run generateTs if changes are detected.
echo "Changes detected in _posts directory. Running the script..."
npm run generateTs
else
echo "No changes in _posts directory. Skipping the script..."
fi
49 changes: 41 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
# Website

Portfolio Website & tech blog of Payapula
Portfolio Website & tech blog of Bharathi Kannan
Live at https://www.bharathikannan.com/

---

## Tech Stack
## 🚀 Tech Stack

- [Next JS](https://nextjs.org/)
- [Chakra UI](https://chakra-ui.com/)
- [Next MDX Remote](https://github.com/hashicorp/next-mdx-remote)

---

## Resources
## 📘 Resources

- [MDX Embed](https://www.mdx-embed.com/?path=/docs/mdx-embed--page)
- [Blog Example with next mdx remote](https://github.com/vercel/next.js/tree/canary/examples/with-mdx-remote)

---

## Inspirations
## 🙏🏽 Inspirations

- [Kent C Dodds Blog](https://github.com/kentcdodds/kentcdodds.com)
- [Leerob Blog](https://github.com/leerob/leerob.io)
Expand All @@ -34,15 +34,15 @@ Please refer to [Projects](https://github.com/payapula/blog/projects)

---

## Installation
## 📍 Installation

`npm install`

`npm run dev`

---

## View Preview Locally on Mobile
## 📲 View Preview Locally on Mobile

Windows:

Expand All @@ -56,7 +56,7 @@ Open that address on the mobile with the same portnumber.

Ex: `192.168.1.9:3001`

## Bundle Analyzer
## 🧵 Bundle Analyzer

`npm run analyze`

Expand All @@ -71,7 +71,7 @@ Make sure you have installed source-map-explorer:

`npm install -g source-map-explorer`

## Sitemap
## 📕 Sitemap

Sitemap file gets updated automatically by this awesome package - [next-sitemap](https://github.com/iamvishnusankar/next-sitemap)

Expand All @@ -80,6 +80,39 @@ Sitemap file gets updated automatically by this awesome package - [next-sitemap]
- `npm run build` would be executed during deployment.
- After build `postbuild` script would be executed, which updates sitemaps.

## 🧪 Playwright Tests

### Screenshots

Its tricky to generate screenshots when tests are running in Github actions.

To update screenshots for blog posts in CI (Github actions), we need to build the
screenshots via docker in local.

👉 Check this [PR for instructions on first time set up](https://github.com/payapula/blog/pull/82).

#### To update Screenshots

##### For local mac

Run `npx playwright test --update-snapshots`, it will generate new screenshot files for `-darwin.png`

##### For CI (linux)

1. On root of the project directory, open a terminal (/blog).
2. Run `docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.33.0-jammy /bin/bash`.
- This will sync the local folder with docker folder
3. `rm -rf node_modules` - Deletes node_modules
- This is to do fresh installation of node modules based on linux platform.
4. `npm install`
5. `npx playwright install --with-deps` - Reinstall playwright dependencies
6. `npx playwright test --update-snapshots` - Runs and updates screenshots
- This step will generate new screenshots based on linux platform (`-linux.png`).
7. Commit the same to the repository.

The downside of this approach is, after updating linux screenshots, on local we again need
to remove `node_modules` and do fresh `npm install` for running the app.

## Notes

Eslint, Prettier Configs provided by [Arpit Bharti](https://dev.to/onygami/eslint-and-prettier-for-react-apps-bonus-next-js-and-typescript-3e46)
2 changes: 1 addition & 1 deletion _posts/context-redux-composition.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: 'Context, Redux or Composition?'
excerpt: "Which is the better way to solve prop drilling? Let us talk about it in this post by solving the same problem
in three different ways."
date: '2023-02-16'
description: "Sharing my experience on the recent react interview question and the feedback I received."
description: "Sharing my experience on the recent react interview question and the feedback I had received."
cover:
src: '/assets/blog/context-redux-composition/drilling-cover.jpg'
alt: 'Pump-jack mining crude oil with the sunset'
Expand Down
2 changes: 1 addition & 1 deletion _posts/minimizing-lodash-bundle-size.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ var lodash = import('lodash');
lodash.sum([1, 2, 3, 3])
```

So, with the named exports it is not possible for the bundlers like webpack to treeshake the unwanted code, and we
So, with the named exports it is not possible for the bundlers like webpack to tree shake the unwanted code, and we
end up shipping entire lodash utilities to the user.

You can avoid this by directly importing the utility you need from lodash like this
Expand Down
81 changes: 53 additions & 28 deletions components/post/post-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,61 @@ import siteConfig from 'configs/site-configs';
const responsiveTwitterSize = { base: 3, md: 5 };
const responsiveGithubSize = { base: 3, md: 6 };

function PostFooter({ slug }: { slug: string }): ReactElement {
interface PostFooterProps {
slug: string;
dates: {
createdDate: string;
modifiedDate: string;
};
}

function TimeStamp({ date, text }: { text: string; date: string }): ReactElement {
return (
<Flex mt={5} justify="space-between" h="25px">
<Box textAlign="center">
<ChakraLink
href={`https://twitter.com/search?q=${siteConfig.general.siteUrl}/blog/${slug}`}>
Let&apos;s Discuss On Twitter
</ChakraLink>
<Icon
as={FaLocationArrow}
w={responsiveTwitterSize}
h={responsiveTwitterSize}
ml="2"
cursor="pointer"
title="Twitter"
color="#1ea1f2"
/>
</Box>
<Box ml="auto" textAlign="center">
<Icon
as={FaGithub}
w={responsiveGithubSize}
h={responsiveGithubSize}
cursor="pointer"
title="GitHub"
/>
<ChakraLink ml={3} href={`${siteConfig.general.editUrl}/${slug}.mdx`}>
Edit this Post On GitHub
</ChakraLink>
<Box as="p" textAlign={'center'} fontSize={{ base: 'sm', md: 'md' }}>
{text}
<Box as="span" fontWeight={'bold'} ml={2}>
{date}
</Box>
</Box>
);
}

function PostFooter({ slug, dates: { createdDate, modifiedDate } }: PostFooterProps): ReactElement {
return (
<Flex direction={'column'} mt={5}>
<Flex justify={'space-between'}>
<TimeStamp text="Published:" date={createdDate} />
<TimeStamp text="Updated:" date={modifiedDate} />
</Flex>
<Flex mt={5} justify="space-between" h="25px">
<Box textAlign="center">
<ChakraLink
href={`https://twitter.com/search?q=${siteConfig.general.siteUrl}/blog/${slug}`}>
Let&apos;s Discuss On Twitter
</ChakraLink>
<Icon
as={FaLocationArrow}
w={responsiveTwitterSize}
h={responsiveTwitterSize}
ml="2"
cursor="pointer"
title="Twitter"
color="#1ea1f2"
/>
</Box>
<Box ml="auto" textAlign="center">
<Icon
as={FaGithub}
w={responsiveGithubSize}
h={responsiveGithubSize}
cursor="pointer"
title="GitHub"
/>
<ChakraLink ml={3} href={`${siteConfig.general.editUrl}/${slug}.mdx`}>
Edit this Post On GitHub
</ChakraLink>
</Box>
</Flex>
</Flex>
);
}
Expand Down
47 changes: 47 additions & 0 deletions lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ import PostType from 'types/post';
import { OverrideProps } from 'types/utils';

const postsDirectory = join(process.cwd(), '_posts');
const timestampsFile = join(process.cwd(), 'timestamps.json');

function getCreatedAndModifiedDateFromGit(realSlug: string) {
let createdDate = '',
modifiedDate = '';
try {
const timestamps = JSON.parse(fs.readFileSync(timestampsFile, 'utf8'));
const currentPostPath = `_posts/${realSlug}.mdx`;
const { created, modified } = timestamps[currentPostPath];
createdDate = unixTimeStampToDate(created);
modifiedDate = unixTimeStampToDate(modified);
} catch (error) {
console.error('Unable to read timestamps file');
}

return {
createdDate,
modifiedDate
};
}

export function getPostSlugs() {
return fs.readdirSync(postsDirectory);
Expand All @@ -15,10 +35,30 @@ type RawPostType = OverrideProps<PostType, { content: string }>;

type PostKey = keyof PostType;

function unixTimeStampToDate(unixTimeStamp: number) {
const dt = new Date(unixTimeStamp * 1000);
return dt.toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
}

export function getPostBySlug(slug: string, fields: PostKey[] = []): Partial<RawPostType> {
const realSlug = slug.replace(/\.mdx$/, '');
const fullPath = join(postsDirectory, `${realSlug}.mdx`);
const fileContents = fs.readFileSync(fullPath, 'utf8');

let createdDate = '',
modifiedDate = '';

// Ensure to read timestamps files only when they are needed
if (fields.includes('createdDate') || fields.includes('modifiedDate')) {
const dates = getCreatedAndModifiedDateFromGit(realSlug);
createdDate = dates.createdDate;
modifiedDate = dates.modifiedDate;
}

const { data, content } = matter(fileContents);

// We are just sending requested fields, hence Parital<> is used
Expand All @@ -33,6 +73,13 @@ export function getPostBySlug(slug: string, fields: PostKey[] = []): Partial<Raw
items[field] = content;
}

if (field === 'createdDate') {
items[field] = createdDate;
}
if (field === 'modifiedDate') {
items[field] = modifiedDate;
}

if (data[field]) {
items[field] = data[field];
}
Expand Down
Loading

0 comments on commit 12618fa

Please sign in to comment.