diff --git a/README.md b/README.md index 31e7a05..c3714c2 100644 --- a/README.md +++ b/README.md @@ -149,11 +149,21 @@ const CONFIG = { trailingSlash: false, // Generate permalinks with or without "/" at the end title: 'Example - This is the homepage title of Example', // default seo title - description: 'This is the homepage description of Example', // default seo descriptio + description: 'This is the homepage description of Example', // default seo description defaultImage: 'image.jpg', // default seo image defaultTheme: 'system', // Values: "system" | "light" | "dark" | "light:only" | "dark:only" + language: 'en', // default language + textDirection: 'ltr', // default html text direction + + dateFormatter: new Intl.DateTimeFormat('en', { // date format + year: 'numeric', + month: 'short', + day: 'numeric', + timeZone: 'UTC', + }), + googleAnalyticsId: false, // or "G-XXXXXXXXXX", googleSiteVerificationId: false, // or some value, diff --git a/src/config.mjs b/src/config.mjs index 93c858b..aae38ea 100644 --- a/src/config.mjs +++ b/src/config.mjs @@ -13,6 +13,16 @@ const CONFIG = { defaultTheme: 'system', // Values: "system" | "light" | "dark" | "light:only" | "dark:only" + language: 'en', + textDirection: 'ltr', + + dateFormatter: new Intl.DateTimeFormat('en', { + year: 'numeric', + month: 'short', + day: 'numeric', + timeZone: 'UTC', + }), + googleAnalyticsId: false, // or "G-XXXXXXXXXX", googleSiteVerificationId: 'orcPxI47GSa-cRvY11tUe6iGg2IO_RPvnA1q95iEM3M', @@ -48,3 +58,4 @@ const CONFIG = { export const SITE = { ...CONFIG, blog: undefined }; export const BLOG = CONFIG.blog; +export const DATE_FORMATTER = CONFIG.dateFormatter; \ No newline at end of file diff --git a/src/content/blog/astrowind-template-in-depth.md b/src/content/blog/astrowind-template-in-depth.md index 101de36..719ff31 100644 --- a/src/content/blog/astrowind-template-in-depth.md +++ b/src/content/blog/astrowind-template-in-depth.md @@ -1,11 +1,14 @@ --- -publishDate: 'Aug 08 2022' -title: 'AstroWind template in depth' -description: 'Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti.' -image: '~/assets/images/old.jpg' -category: 'Tutorials' -tags: [astro, tailwind css, front-end] -canonical: https://astrowind.vercel.app/astrowind-template-in-depth # When posting content to multiple platforms at the same time (such as this website and Medium) and want to specify the ultimate authority. Remove it to automatically generate canonical +publishDate: 2023-01-08T00:00:00Z +title: AstroWind template in depth +description: Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti. +image: ~/assets/images/old.jpg +category: Tutorials +tags: + - astro + - tailwind css + - front-end +canonical: https://astrowind.vercel.app/astrowind-template-in-depth --- ## Dictum integer fusce ac ridiculus et odio sollicitudin diam at diff --git a/src/content/blog/get-started-website-with-astro-tailwind-css.md b/src/content/blog/get-started-website-with-astro-tailwind-css.md index f993af6..9d87db2 100644 --- a/src/content/blog/get-started-website-with-astro-tailwind-css.md +++ b/src/content/blog/get-started-website-with-astro-tailwind-css.md @@ -1,12 +1,14 @@ --- -publishDate: 'Aug 12 2022' -title: 'Get started with AstroWind to create a website using Astro and Tailwind CSS' -description: 'Lorem ipsum dolor sit amet' -excerpt: 'Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat' -image: '~/assets/images/steps.jpg' -category: 'Tutorials' -tags: [astro, tailwind css] -canonical: https://astrowind.vercel.app/get-started-website-with-astro-tailwind-css # When posting content to multiple platforms at the same time (such as this website and Medium) and want to specify the ultimate authority. Remove it to automatically generate canonical +publishDate: 2023-01-12T00:00:00Z +title: Get started with AstroWind to create a website using Astro and Tailwind CSS +description: Lorem ipsum dolor sit amet +excerpt: Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat +image: ~/assets/images/steps.jpg +category: Tutorials +tags: + - astro + - tailwind css +canonical: https://astrowind.vercel.app/get-started-website-with-astro-tailwind-css --- Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/src/content/blog/how-to-customize-astrowind-to-your-brand.md b/src/content/blog/how-to-customize-astrowind-to-your-brand.md index dce9947..2b6c38f 100644 --- a/src/content/blog/how-to-customize-astrowind-to-your-brand.md +++ b/src/content/blog/how-to-customize-astrowind-to-your-brand.md @@ -1,10 +1,13 @@ --- -publishDate: 'Aug 10 2022' -title: 'How to customize AstroWind template to suit your branding' -description: 'Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat' -image: '~/assets/images/colors.jpg' -tags: [astro, tailwind css, theme] -canonical: https://astrowind.vercel.app/how-to-customize-astrowind-to-your-brand # When posting content to multiple platforms at the same time (such as this website and Medium) and want to specify the ultimate authority. Remove it to automatically generate canonical +publishDate: 2023-01-06T00:00:00Z +title: How to customize AstroWind template to suit your branding +description: Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat +image: ~/assets/images/colors.jpg +tags: + - astro + - tailwind css + - theme +canonical: https://astrowind.vercel.app/how-to-customize-astrowind-to-your-brand --- ## Congue justo vulputate nascetur convallis varius orci fringilla nulla pharetr diff --git a/src/content/blog/markdown-elements-demo-post.mdx b/src/content/blog/markdown-elements-demo-post.mdx index 90392cb..8b4637b 100644 --- a/src/content/blog/markdown-elements-demo-post.mdx +++ b/src/content/blog/markdown-elements-demo-post.mdx @@ -1,9 +1,12 @@ --- -publishDate: 'Aug 02 2022' -title: 'Markdown elements demo post' -description: 'Lorem ipsum dolor sit amet' -excerpt: 'Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat' -tags: [markdown, blog, Astro] +publishDate: 2023-01-02T00:00:00Z +title: Markdown elements demo post +description: Lorem ipsum dolor sit amet +excerpt: Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat +tags: + - markdown + - blog + - Astro --- import Logo from '~/components/common/Logo.astro'; diff --git a/src/content/blog/useful-resources-to-create-websites.md b/src/content/blog/useful-resources-to-create-websites.md index 2503dff..88f870f 100644 --- a/src/content/blog/useful-resources-to-create-websites.md +++ b/src/content/blog/useful-resources-to-create-websites.md @@ -1,9 +1,12 @@ --- -publishDate: 'Aug 09 2022' -title: 'Useful tools and resources to create a professional website' -description: 'Nibh senectus lacinia volutpat nostra taciti ac posuere, dictum ultricies dictumst luctus in vehicula, mus molestie venenatis penatibus ridiculus elementum. Phasellus sollicitudin dignissim parturient.' -image: '~/assets/images/tools.jpg' -tags: [front-end, tools, resources] +publishDate: 2023-01-09T00:00:00Z +title: Useful tools and resources to create a professional website +description: Nibh senectus lacinia volutpat nostra taciti ac posuere, dictum ultricies dictumst luctus in vehicula, mus molestie venenatis penatibus ridiculus elementum. Phasellus sollicitudin dignissim parturient. +image: ~/assets/images/tools.jpg +tags: + - front-end + - tools + - resources --- ## Magna nunc senectus torquent per fusce sapien ligula tempus cra diff --git a/src/content/config.ts b/src/content/config.ts index 11a1241..f76181e 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -1,5 +1,4 @@ import { z, defineCollection } from 'astro:content'; -import { cleanSlug } from '~/utils/permalinks'; const blog = defineCollection({ schema: { @@ -10,7 +9,9 @@ const blog = defineCollection({ canonical: z.string().url().optional(), permalink: z.string().optional(), - publishDate: z.date().optional(), + publishDate: z + .date().or(z.string()) + .optional(), draft: z.boolean().optional(), excerpt: z.string().optional(), @@ -19,7 +20,7 @@ const blog = defineCollection({ author: z.string().optional(), }, slug: ({ defaultSlug, data }) => { - return cleanSlug(data.permalink || defaultSlug); + return data.permalink || defaultSlug; }, }); diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 511e548..8660bfb 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -5,16 +5,18 @@ import MetaTags from '~/components/common/MetaTags.astro'; import BasicScripts from '~/components/common/BasicScripts.astro'; import { MetaSEO } from '~/types'; +import { SITE } from '~/config.mjs'; export interface Props { meta?: MetaSEO; } const { meta = {} } = Astro.props; +const { language = 'en', textDirection = 'ltr' } = SITE; --- - + diff --git a/src/utils/blog.ts b/src/utils/blog.ts index f83c462..0984f62 100644 --- a/src/utils/blog.ts +++ b/src/utils/blog.ts @@ -4,14 +4,14 @@ import type { Post } from '~/types'; import { cleanSlug } from './permalinks'; const getNormalizedPost = async (post: CollectionEntry<'blog'>): Promise => { - const { id, slug, data } = post; + const { id, slug = '', data } = post; const { Content, injectedFrontmatter } = await post.render(); - const { tags = [], category = 'default', author = 'Anonymous', publishDate, ...rest } = data; + const { tags = [], category = 'default', author = 'Anonymous', publishDate = new Date(), ...rest } = data; return { id: id, - slug: slug, + slug: cleanSlug(slug.split('/').pop() ?? ''), publishDate: new Date(publishDate), category: cleanSlug(category), diff --git a/src/utils/permalinks.ts b/src/utils/permalinks.ts index b209e70..98473a6 100644 --- a/src/utils/permalinks.ts +++ b/src/utils/permalinks.ts @@ -1,22 +1,18 @@ import slugify from 'limax'; import { SITE, BLOG } from '~/config.mjs'; - -const trim = (str = '', ch?: string) => { - let start = 0, - end = str.length || 0; - while (start < end && str[start] === ch) ++start; - while (end > start && str[end - 1] === ch) --end; - return start > 0 || end < str.length ? str.substring(start, end) : str; -}; +import { trim } from '~/utils/utils'; const trimSlash = (s: string) => trim(trim(s, '/')); const createPath = (...params: string[]) => { - const paths = params.filter((el) => !!el).join('/'); + const paths = params + .map((el) => trimSlash(el)) + .filter((el) => !!el) + .join('/'); return '/' + paths + (SITE.trailingSlash && paths ? '/' : ''); }; -const basePathname = trimSlash(SITE.basePathname); +const BASE_PATHNAME = SITE.basePathname; export const cleanSlug = (text: string) => trimSlash(text) @@ -34,25 +30,35 @@ export const getCanonical = (path = ''): string | URL => new URL(path, SITE.orig /** */ export const getPermalink = (slug = '', type = 'page'): string => { + let permalink: string; + switch (type) { case 'category': - return createPath(basePathname, CATEGORY_BASE, cleanSlug(slug)); + permalink = createPath(CATEGORY_BASE, cleanSlug(slug)); + break; case 'tag': - return createPath(basePathname, TAG_BASE, cleanSlug(slug)); + permalink = createPath(TAG_BASE, cleanSlug(slug)); + break; case 'post': - return createPath(basePathname, POST_BASE, cleanSlug(slug)); + permalink = createPath(POST_BASE, cleanSlug(slug)); + break; + + case 'page': + default: + permalink = createPath(slug); + break; } - return createPath(basePathname, trimSlash(slug)); + return definitivePermalink(permalink); }; /** */ -export const getHomePermalink = (): string => { - const permalink = getPermalink(); - return !permalink.startsWith('/') ? '/' + permalink : permalink; -}; +export const getHomePermalink = (): string => getPermalink('/'); /** */ export const getBlogPermalink = (): string => getPermalink(BLOG_BASE); + +/** */ +const definitivePermalink = (permalink: string): string => createPath(BASE_PATHNAME, permalink); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 1381618..52043e9 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,9 +1,21 @@ +import { DATE_FORMATTER } from '~/config.mjs'; + +const formatter = + DATE_FORMATTER || + new Intl.DateTimeFormat('en', { + year: 'numeric', + month: 'short', + day: 'numeric', + timeZone: 'UTC' + }); + /* eslint-disable no-mixed-spaces-and-tabs */ -export const getFormattedDate = (date: Date) => - date - ? new Date(date).toLocaleDateString('en-us', { - year: 'numeric', - month: 'short', - day: 'numeric', - }) - : ''; +export const getFormattedDate = (date: Date) => (date ? formatter.format(date) : ''); + +export const trim = (str = '', ch?: string) => { + let start = 0, + end = str.length || 0; + while (start < end && str[start] === ch) ++start; + while (end > start && str[end - 1] === ch) --end; + return start > 0 || end < str.length ? str.substring(start, end) : str; +};