From f158d32181503249b9dfbef7d37343bc92b56d9a Mon Sep 17 00:00:00 2001 From: prototypa Date: Mon, 2 Jan 2023 10:51:51 -0500 Subject: [PATCH] Migrate to typescript --- .eslintignore | 3 +- README.md | 6 +-- src/assets/styles/base.css | 5 +- src/components/atoms/Pagination.astro | 15 +++--- src/components/atoms/SocialShare.astro | 7 +++ src/components/atoms/Tags.astro | 7 +++ src/components/blog/Grid.astro | 5 ++ src/components/blog/GridItem.astro | 9 +++- src/components/blog/List.astro | 5 ++ src/components/blog/ListItem.astro | 9 +++- src/components/blog/SinglePost.astro | 35 +++++++++---- src/components/core/ToggleMenu.astro | 7 +++ src/components/core/ToggleTheme.astro | 7 +++ src/components/widgets/Error404.astro | 7 +-- src/components/widgets/Header.astro | 9 ++-- src/components/widgets/Hero.astro | 22 ++++---- src/components/widgets/Note.astro | 5 +- src/components/widgets/Steps.astro | 6 ++- src/content/{config.js => config.ts} | 0 src/env.d.ts | 1 + .../[category]/[...page].astro | 2 +- src/pages/[...tags]/[tag]/[...page].astro | 2 +- src/pages/{rss.xml.js => rss.xml.ts} | 0 src/utils/{directories.js => directories.ts} | 10 ++-- src/utils/{images.js => images.ts} | 4 +- src/utils/{permalinks.js => permalinks.ts} | 14 ++--- src/utils/{posts.js => posts.ts} | 52 ++++++++++++++----- src/utils/{utils.js => utils.ts} | 3 +- 28 files changed, 172 insertions(+), 85 deletions(-) rename src/content/{config.js => config.ts} (100%) create mode 100644 src/env.d.ts rename src/pages/{rss.xml.js => rss.xml.ts} (100%) rename src/utils/{directories.js => directories.ts} (65%) rename src/utils/{images.js => images.ts} (84%) rename src/utils/{permalinks.js => permalinks.ts} (79%) rename src/utils/{posts.js => posts.ts} (50%) rename src/utils/{utils.js => utils.ts} (76%) diff --git a/.eslintignore b/.eslintignore index 5c5bb8f..a7af2a5 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ dist node_modules -.github \ No newline at end of file +.github +types.generated.d.ts \ No newline at end of file diff --git a/README.md b/README.md index 35ecb87..125dd2c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ AstroWind Lighthouse Score -**AstroWind** is a free and open-source template to make your website using **[Astro](https://astro.build/) + [Tailwind CSS](https://tailwindcss.com/)**. Ready to start a new project and designed taking into account best practices. 🌟 **Most *starred* & *forked* Astro theme in 2022**. +**AstroWind** is a free and open-source template to make your website using **[Astro](https://astro.build/) + [Tailwind CSS](https://tailwindcss.com/)**. Ready to start a new project and designed taking into account best practices. 🌟 **Most _starred_ & _forked_ Astro theme in 2022**. ## Features @@ -88,7 +88,7 @@ Inside AstroWind template, you'll see the following folders and files: │ | | ├── post-slug-1.md │ | | ├── post-slug-2.mdx │ | | └── ... -│ | └-- config.js +│ | └-- config.ts │ ├── layouts/ │ | |── BaseLayout.astro │ | └── ... @@ -104,7 +104,7 @@ Inside AstroWind template, you'll see the following folders and files: | | | └── [...page].astro │ | ├── index.astro | | ├── 404.astro -| | └-- rss.xml.js +| | └-- rss.xml.ts │ ├── utils/ │ └── config.mjs ├── package.json diff --git a/src/assets/styles/base.css b/src/assets/styles/base.css index 3f666b9..009e3ad 100644 --- a/src/assets/styles/base.css +++ b/src/assets/styles/base.css @@ -17,10 +17,9 @@ } .dropdown:hover .dropdown-menu { - display: block; + display: block; } - [astro-icon].icon-light > * { stroke-width: 1.2; } @@ -34,4 +33,4 @@ [data-aw-toggle-menu].expanded g > path:last-child { @apply rotate-45 translate-y-[-8px] translate-x-[14px]; -} \ No newline at end of file +} diff --git a/src/components/atoms/Pagination.astro b/src/components/atoms/Pagination.astro index 35bb532..71cb7ea 100644 --- a/src/components/atoms/Pagination.astro +++ b/src/components/atoms/Pagination.astro @@ -1,6 +1,14 @@ --- import { Icon } from 'astro-icon'; import { getRelativeLink } from '~/utils/permalinks'; + +export interface Props { + prevUrl: string; + nextUrl: string; + prevText?: string; + nextText?: string; +} + const { prevUrl, nextUrl, prevText = 'Newer posts', nextText = 'Older posts' } = Astro.props; --- @@ -18,12 +26,7 @@ const { prevUrl, nextUrl, prevText = 'Newer posts', nextText = 'Older posts' } =

{prevText}

- +
{nextText} diff --git a/src/components/atoms/SocialShare.astro b/src/components/atoms/SocialShare.astro index 8ca485f..2acee92 100644 --- a/src/components/atoms/SocialShare.astro +++ b/src/components/atoms/SocialShare.astro @@ -1,5 +1,12 @@ --- import { Icon } from 'astro-icon'; + +export interface Props { + text: string; + url: string; + class?: string; +} + const { text, url, class: className = 'inline-block' } = Astro.props; --- diff --git a/src/components/atoms/Tags.astro b/src/components/atoms/Tags.astro index 6335d55..03728a7 100644 --- a/src/components/atoms/Tags.astro +++ b/src/components/atoms/Tags.astro @@ -1,6 +1,13 @@ --- import { getPermalink } from '~/utils/permalinks'; +import type { Post } from '~/utils/posts'; + +export interface Props { + tags: Post['tags']; + class?: string; +} + const { tags, class: className = 'text-sm' } = Astro.props; --- diff --git a/src/components/blog/Grid.astro b/src/components/blog/Grid.astro index 4806c54..95ad4d1 100644 --- a/src/components/blog/Grid.astro +++ b/src/components/blog/Grid.astro @@ -1,5 +1,10 @@ --- import Item from '~/components/blog/GridItem.astro'; +import type { Post } from '~/utils/posts'; + +export interface Props { + posts: Array; +} const { posts } = Astro.props; --- diff --git a/src/components/blog/GridItem.astro b/src/components/blog/GridItem.astro index a88f104..aa90c2b 100644 --- a/src/components/blog/GridItem.astro +++ b/src/components/blog/GridItem.astro @@ -1,11 +1,16 @@ --- -import { Picture } from '@astrojs/image/components' +import { Picture } from '@astrojs/image/components'; import { findImage } from '~/utils/images'; import { getPermalink } from '~/utils/permalinks'; -const { post } = Astro.props; +import type { Post } from '~/utils/posts'; +export interface Props { + post: Post; +} + +const { post } = Astro.props; const image = await findImage(post.image); --- diff --git a/src/components/blog/List.astro b/src/components/blog/List.astro index d150d25..cc815e4 100644 --- a/src/components/blog/List.astro +++ b/src/components/blog/List.astro @@ -1,5 +1,10 @@ --- import Item from '~/components/blog/ListItem.astro'; +import type { Post } from '~/utils/posts'; + +export interface Props { + posts: Array; +} const { posts } = Astro.props; --- diff --git a/src/components/blog/ListItem.astro b/src/components/blog/ListItem.astro index 3ac6101..830ce91 100644 --- a/src/components/blog/ListItem.astro +++ b/src/components/blog/ListItem.astro @@ -6,8 +6,13 @@ import { getPermalink } from '~/utils/permalinks'; import { findImage } from '~/utils/images'; import { getFormattedDate } from '~/utils/utils'; -const { post } = Astro.props; +import type { Post } from '~/utils/posts'; +export interface Props { + post: Post; +} + +const { post } = Astro.props; const image = await findImage(post.image); --- @@ -47,7 +52,7 @@ const image = await findImage(post.image);
diff --git a/src/components/widgets/Header.astro b/src/components/widgets/Header.astro index 1da2618..63a8be9 100644 --- a/src/components/widgets/Header.astro +++ b/src/components/widgets/Header.astro @@ -37,16 +37,19 @@ import { getHomePermalink, getBlogPermalink, getPermalink, getRelativeLink } fro
  • Features + href="#">Features
  • Profile + >Profile
  • Pricing + href="#">Pricing
  • diff --git a/src/components/widgets/Hero.astro b/src/components/widgets/Hero.astro index f48188e..19ea960 100644 --- a/src/components/widgets/Hero.astro +++ b/src/components/widgets/Hero.astro @@ -1,6 +1,6 @@ --- import { Icon } from 'astro-icon'; -import { Picture } from '@astrojs/image/components' +import { Picture } from '@astrojs/image/components'; ---
    @@ -10,16 +10,15 @@ import { Picture } from '@astrojs/image/components'

    Your website with Astro + - Tailwind CSS + Tailwind CSS

    - AstroWind is a production ready template to start your new website using Astro + Tailwind CSS. It has been - designed following Best Practices, SEO, Accessibility, ... is a production ready template to start your new website using Astro + Tailwind CSS. It + has been designed following Best Practices, SEO, Accessibility, ...

    @@ -35,10 +34,7 @@ import { Picture } from '@astrojs/image/components'
    @@ -51,7 +47,7 @@ import { Picture } from '@astrojs/image/components' widths={[400, 768, 1480]} sizes="(max-width: 767px) 400px, (max-width: 1479px) 768px, 1480px" alt="Hero Image" - aspectRatio={1480/833} + aspectRatio={1480 / 833} loading="eager" width={1480} height={833} diff --git a/src/components/widgets/Note.astro b/src/components/widgets/Note.astro index 16f3f02..dabe45f 100644 --- a/src/components/widgets/Note.astro +++ b/src/components/widgets/Note.astro @@ -4,7 +4,8 @@ import { Icon } from 'astro-icon';
    - Philosophy: Simplicity, Best - Practices and High Performance + + Philosophy: Simplicity, Best Practices and High Performance
    diff --git a/src/components/widgets/Steps.astro b/src/components/widgets/Steps.astro index 9493f64..f96c28a 100644 --- a/src/components/widgets/Steps.astro +++ b/src/components/widgets/Steps.astro @@ -1,6 +1,6 @@ --- import { Icon } from 'astro-icon'; -import { Picture } from '@astrojs/image/components' +import { Picture } from '@astrojs/image/components'; ---
    @@ -64,7 +64,9 @@ import { Picture } from '@astrojs/image/components'
    -
    +
    diff --git a/src/content/config.js b/src/content/config.ts similarity index 100% rename from src/content/config.js rename to src/content/config.ts diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..f964fe0 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/pages/[...categories]/[category]/[...page].astro b/src/pages/[...categories]/[category]/[...page].astro index d736c63..8fc1399 100644 --- a/src/pages/[...categories]/[category]/[...page].astro +++ b/src/pages/[...categories]/[category]/[...page].astro @@ -18,7 +18,7 @@ export async function getStaticPaths({ paginate }) { typeof post.category === 'string' && categories.add(post.category.toLowerCase()); }); - return Array.from(categories).map((category) => + return Array.from(categories).map((category: string) => paginate( posts.filter((post) => typeof post.category === 'string' && category === post.category.toLowerCase()), { diff --git a/src/pages/[...tags]/[tag]/[...page].astro b/src/pages/[...tags]/[tag]/[...page].astro index d4c8094..446391b 100644 --- a/src/pages/[...tags]/[tag]/[...page].astro +++ b/src/pages/[...tags]/[tag]/[...page].astro @@ -18,7 +18,7 @@ export async function getStaticPaths({ paginate }) { Array.isArray(post.tags) && post.tags.map((tag) => tags.add(tag.toLowerCase())); }); - return Array.from(tags).map((tag) => + return Array.from(tags).map((tag: string) => paginate( posts.filter((post) => Array.isArray(post.tags) && post.tags.find((elem) => elem.toLowerCase() === tag)), { diff --git a/src/pages/rss.xml.js b/src/pages/rss.xml.ts similarity index 100% rename from src/pages/rss.xml.js rename to src/pages/rss.xml.ts diff --git a/src/utils/directories.js b/src/utils/directories.ts similarity index 65% rename from src/utils/directories.js rename to src/utils/directories.ts index 6d37296..bf0dfe5 100644 --- a/src/utils/directories.js +++ b/src/utils/directories.ts @@ -4,7 +4,7 @@ import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); /** */ -export const getProjectRootDir = () => { +export const getProjectRootDir = (): string => { const mode = import.meta.env.MODE; return mode === 'production' ? path.join(__dirname, '../') : path.join(__dirname, '../../'); @@ -13,10 +13,6 @@ export const getProjectRootDir = () => { const __srcFolder = path.join(getProjectRootDir(), '/src'); /** */ -export const getRelativeUrlByFilePath = (filepath) => { - if (filepath) { - return filepath.replace(__srcFolder, ''); - } - - return null; +export const getRelativeUrlByFilePath = (filepath: string): string | URL => { + return filepath.replace(__srcFolder, ''); }; diff --git a/src/utils/images.js b/src/utils/images.ts similarity index 84% rename from src/utils/images.js rename to src/utils/images.ts index 676820a..16dba2e 100644 --- a/src/utils/images.js +++ b/src/utils/images.ts @@ -1,5 +1,5 @@ const load = async function () { - let images = []; + let images: Record Promise> | undefined = undefined; try { images = import.meta.glob('~/assets/images/**'); } catch (e) { @@ -17,7 +17,7 @@ export const fetchLocalImages = async () => { }; /** */ -export const findImage = async (imagePath) => { +export const findImage = async (imagePath?: string) => { if (typeof imagePath !== 'string') { return null; } diff --git a/src/utils/permalinks.js b/src/utils/permalinks.ts similarity index 79% rename from src/utils/permalinks.js rename to src/utils/permalinks.ts index 0882ad9..4ab1395 100644 --- a/src/utils/permalinks.js +++ b/src/utils/permalinks.ts @@ -2,7 +2,7 @@ import slugify from 'limax'; import { SITE, BLOG } from '~/config.mjs'; -const trim = (str = "", ch) => { +const trim = (str = '', ch?: string) => { let start = 0, end = str.length || 0; while (start < end && str[start] === ch) ++start; @@ -18,7 +18,7 @@ const createPath = (...params) => { const basePathname = trimSlash(SITE.basePathname); -export const cleanSlug = (text) => slugify(trimSlash(text)); +export const cleanSlug = (text: string) => slugify(trimSlash(text)); export const BLOG_BASE = cleanSlug(BLOG?.blog?.pathname); export const POST_BASE = cleanSlug(BLOG?.post?.pathname); @@ -29,7 +29,7 @@ export const TAG_BASE = cleanSlug(BLOG?.tag?.pathname); export const getCanonical = (path = '') => new URL(path, SITE.origin); /** */ -export const getPermalink = (slug = '', type = 'page') => { +export const getPermalink = (slug = '', type = 'page'): string => { const _slug = cleanSlug(slug); switch (type) { @@ -49,15 +49,15 @@ export const getPermalink = (slug = '', type = 'page') => { }; /** */ -export const getHomePermalink = () => { +export const getHomePermalink = (): string => { const permalink = getPermalink(); return permalink !== '/' ? permalink + '/' : permalink; }; /** */ -export const getRelativeLink = (link = "") => { +export const getRelativeLink = (link = ''): string => { return createPath(basePathname, trimSlash(link)); -} +}; /** */ -export const getBlogPermalink = () => getPermalink(BLOG_BASE); +export const getBlogPermalink = (): string => getPermalink(BLOG_BASE); diff --git a/src/utils/posts.js b/src/utils/posts.ts similarity index 50% rename from src/utils/posts.js rename to src/utils/posts.ts index b361085..3f15fa5 100644 --- a/src/utils/posts.js +++ b/src/utils/posts.ts @@ -1,6 +1,32 @@ import { getCollection, getEntry } from 'astro:content'; +import type { CollectionEntry } from 'astro:content'; -const getNormalizedPost = async (post) => { +export interface Post { + id: string; + slug: string; + + publishDate: Date; + title: string; + description?: string; + + image?: string; + + canonical?: string; + permalink?: string; + + draft?: boolean; + + excerpt?: string; + category?: string; + tags?: Array; + authors?: Array; + + Content: unknown; + content?: string; + readingTime: number; +} + +const getNormalizedPost = async (post: CollectionEntry<'blog'>): Promise => { const { id, slug, data } = post; const { Content, injectedFrontmatter } = await post.render(); @@ -16,7 +42,7 @@ const getNormalizedPost = async (post) => { }; }; -const load = async function () { +const load = async function (): Promise> { const posts = await getCollection('blog'); const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post)); @@ -27,23 +53,25 @@ const load = async function () { return results; }; -let _posts; +let _posts: Array; /** */ -export const fetchPosts = async () => { - _posts = _posts || load(); +export const fetchPosts = async (): Promise> => { + if (!_posts) { + _posts = await load(); + } - return await _posts; + return _posts; }; /** */ -export const findPostsBySlugs = async (slugs) => { +export const findPostsBySlugs = async (slugs: Array): Promise> => { if (!Array.isArray(slugs)) return []; const posts = await fetchPosts(); - return slugs.reduce(function (r, slug) { - posts.some(function (post) { + return slugs.reduce(function (r: Array, slug: string) { + posts.some(function (post: Post) { return slug === post.slug && r.push(post); }); return r; @@ -51,11 +79,11 @@ export const findPostsBySlugs = async (slugs) => { }; /** */ -export const findPostsByIds = async (ids) => { +export const findPostsByIds = async (ids: Array): Promise> => { if (!Array.isArray(ids)) return []; return await Promise.all( - ids.map(async (id) => { + ids.map(async (id: never) => { const post = await getEntry('blog', id); return await getNormalizedPost(post); }) @@ -63,7 +91,7 @@ export const findPostsByIds = async (ids) => { }; /** */ -export const findLatestPosts = async ({ count }) => { +export const findLatestPosts = async ({ count }: { count?: number }): Promise> => { const _count = count || 4; const posts = await fetchPosts(); diff --git a/src/utils/utils.js b/src/utils/utils.ts similarity index 76% rename from src/utils/utils.js rename to src/utils/utils.ts index 1fdf5c5..f0eaeff 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-mixed-spaces-and-tabs */ /** */ export const getFormattedDate = (date) => date @@ -6,4 +7,4 @@ export const getFormattedDate = (date) => month: 'short', day: 'numeric', }) - : ''; \ No newline at end of file + : '';