add astro template for front #13
@ -12,8 +12,8 @@ metadata:
|
|||||||
canonical: https://astrowind.vercel.app/astrowind-template-in-depth
|
canonical: https://astrowind.vercel.app/astrowind-template-in-depth
|
||||||
---
|
---
|
||||||
|
|
||||||
import DListItem from '~/components/ui/DListItem.astro';
|
import DListItem from 'components/ui/DListItem.astro';
|
||||||
import ToggleTheme from '~/components/common/ToggleTheme.astro';
|
import ToggleTheme from 'components/common/ToggleTheme.astro';
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ tags:
|
|||||||
- Astro
|
- Astro
|
||||||
---
|
---
|
||||||
|
|
||||||
import Logo from '~/components/Logo.astro';
|
import Logo from 'components/Logo.astro';
|
||||||
import { YouTube, Tweet, Vimeo } from 'astro-embed';
|
import { YouTube, Tweet, Vimeo } from 'astro-embed';
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
---
|
---
|
||||||
import Layout from 'layouts/Layout.astro';
|
import Layout from 'layouts/PageLayout.astro';
|
||||||
import 'leaflet/dist/leaflet.css'
|
import 'leaflet/dist/leaflet.css'
|
||||||
|
|
||||||
|
const metadata = {
|
||||||
|
title: 'Maps',
|
||||||
|
ignoreTitleTemplate: true,
|
||||||
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="maps test">
|
<Layout metadata={metadata}>
|
||||||
|
|
||||||
<div class="w-52 h-52" id="map" />
|
<div class="w-52 h-52" id="map" />
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { getRssString } from '@astrojs/rss';
|
import { getRssString } from '@astrojs/rss';
|
||||||
|
|
||||||
import { SITE, METADATA, APP_BLOG } from 'astrowind:config';
|
import { SITE, METADATA, APP_BLOG } from 'astrowind:config';
|
||||||
import { fetchPosts } from '~/utils/blog';
|
import { fetchPosts } from 'utils/blog';
|
||||||
import { getPermalink } from '~/utils/permalinks';
|
import { getPermalink } from 'utils/permalinks';
|
||||||
|
|
||||||
export const GET = async () => {
|
export const GET = async () => {
|
||||||
if (!APP_BLOG.isEnabled) {
|
if (!APP_BLOG.isEnabled) {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import type { PaginateFunction } from 'astro';
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
||||||
import { getCollection } from 'astro:content';
|
/* eslint-disable id-length */
|
||||||
import type { CollectionEntry } from 'astro:content';
|
import type { PaginateFunction } from 'astro'
|
||||||
import type { Post } from '~/types';
|
import { getCollection } from 'astro:content'
|
||||||
import { APP_BLOG } from 'astrowind:config';
|
import type { CollectionEntry } from 'astro:content'
|
||||||
import { cleanSlug, trimSlash, BLOG_BASE, POST_PERMALINK_PATTERN, CATEGORY_BASE, TAG_BASE } from './permalinks';
|
import type { Post } from 'types'
|
||||||
|
import { APP_BLOG } from 'astrowind:config'
|
||||||
|
import { cleanSlug, trimSlash, BLOG_BASE, POST_PERMALINK_PATTERN, CATEGORY_BASE, TAG_BASE } from './permalinks'
|
||||||
|
|
||||||
const generatePermalink = async ({
|
const generatePermalink = async ({
|
||||||
id,
|
id,
|
||||||
@ -11,17 +13,17 @@ const generatePermalink = async ({
|
|||||||
publishDate,
|
publishDate,
|
||||||
category,
|
category,
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string
|
||||||
slug: string;
|
slug: string
|
||||||
publishDate: Date;
|
publishDate: Date
|
||||||
category: string | undefined;
|
category: string | undefined
|
||||||
}) => {
|
}) => {
|
||||||
const year = String(publishDate.getFullYear()).padStart(4, '0');
|
const year = String(publishDate.getFullYear()).padStart(4, '0')
|
||||||
const month = String(publishDate.getMonth() + 1).padStart(2, '0');
|
const month = String(publishDate.getMonth() + 1).padStart(2, '0')
|
||||||
const day = String(publishDate.getDate()).padStart(2, '0');
|
const day = String(publishDate.getDate()).padStart(2, '0')
|
||||||
const hour = String(publishDate.getHours()).padStart(2, '0');
|
const hour = String(publishDate.getHours()).padStart(2, '0')
|
||||||
const minute = String(publishDate.getMinutes()).padStart(2, '0');
|
const minute = String(publishDate.getMinutes()).padStart(2, '0')
|
||||||
const second = String(publishDate.getSeconds()).padStart(2, '0');
|
const second = String(publishDate.getSeconds()).padStart(2, '0')
|
||||||
|
|
||||||
const permalink = POST_PERMALINK_PATTERN.replace('%slug%', slug)
|
const permalink = POST_PERMALINK_PATTERN.replace('%slug%', slug)
|
||||||
.replace('%id%', id)
|
.replace('%id%', id)
|
||||||
@ -31,18 +33,18 @@ const generatePermalink = async ({
|
|||||||
.replace('%day%', day)
|
.replace('%day%', day)
|
||||||
.replace('%hour%', hour)
|
.replace('%hour%', hour)
|
||||||
.replace('%minute%', minute)
|
.replace('%minute%', minute)
|
||||||
.replace('%second%', second);
|
.replace('%second%', second)
|
||||||
|
|
||||||
return permalink
|
return permalink
|
||||||
.split('/')
|
.split('/')
|
||||||
.map((el) => trimSlash(el))
|
.map((el) => trimSlash(el))
|
||||||
.filter((el) => !!el)
|
.filter((el) => !!el)
|
||||||
.join('/');
|
.join('/')
|
||||||
};
|
}
|
||||||
|
|
||||||
const getNormalizedPost = async (post: CollectionEntry<'post'>): Promise<Post> => {
|
const getNormalizedPost = async (post: CollectionEntry<'post'>): Promise<Post> => {
|
||||||
const { id, slug: rawSlug = '', data } = post;
|
const { id, slug: rawSlug = '', data } = post
|
||||||
const { Content, remarkPluginFrontmatter } = await post.render();
|
const { Content, remarkPluginFrontmatter } = await post.render()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
publishDate: rawPublishDate = new Date(),
|
publishDate: rawPublishDate = new Date(),
|
||||||
@ -55,23 +57,23 @@ const getNormalizedPost = async (post: CollectionEntry<'post'>): Promise<Post> =
|
|||||||
author,
|
author,
|
||||||
draft = false,
|
draft = false,
|
||||||
metadata = {},
|
metadata = {},
|
||||||
} = data;
|
} = data
|
||||||
|
|
||||||
const slug = cleanSlug(rawSlug); // cleanSlug(rawSlug.split('/').pop());
|
const slug = cleanSlug(rawSlug) // cleanSlug(rawSlug.split('/').pop())
|
||||||
const publishDate = new Date(rawPublishDate);
|
const publishDate = new Date(rawPublishDate)
|
||||||
const updateDate = rawUpdateDate ? new Date(rawUpdateDate) : undefined;
|
const updateDate = rawUpdateDate ? new Date(rawUpdateDate) : undefined
|
||||||
|
|
||||||
const category = rawCategory
|
const category = rawCategory
|
||||||
? {
|
? {
|
||||||
slug: cleanSlug(rawCategory),
|
slug: cleanSlug(rawCategory),
|
||||||
title: rawCategory,
|
title: rawCategory,
|
||||||
}
|
}
|
||||||
: undefined;
|
: undefined
|
||||||
|
|
||||||
const tags = rawTags.map((tag: string) => ({
|
const tags = rawTags.map((tag: string) => ({
|
||||||
slug: cleanSlug(tag),
|
slug: cleanSlug(tag),
|
||||||
title: tag,
|
title: tag,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
@ -97,111 +99,112 @@ const getNormalizedPost = async (post: CollectionEntry<'post'>): Promise<Post> =
|
|||||||
// or 'content' in case you consume from API
|
// or 'content' in case you consume from API
|
||||||
|
|
||||||
readingTime: remarkPluginFrontmatter?.readingTime,
|
readingTime: remarkPluginFrontmatter?.readingTime,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const load = async function (): Promise<Array<Post>> {
|
const load = async function(): Promise<Array<Post>> {
|
||||||
const posts = await getCollection('post');
|
const posts = await getCollection('post')
|
||||||
const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post));
|
const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post))
|
||||||
|
|
||||||
const results = (await Promise.all(normalizedPosts))
|
const results = (await Promise.all(normalizedPosts))
|
||||||
.sort((a, b) => b.publishDate.valueOf() - a.publishDate.valueOf())
|
.sort((a, b) => b.publishDate.valueOf() - a.publishDate.valueOf())
|
||||||
.filter((post) => !post.draft);
|
.filter((post) => !post.draft)
|
||||||
|
|
||||||
return results;
|
return results
|
||||||
};
|
}
|
||||||
|
|
||||||
let _posts: Array<Post>;
|
let _posts: Array<Post>
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const isBlogEnabled = APP_BLOG.isEnabled;
|
export const isBlogEnabled = APP_BLOG.isEnabled
|
||||||
export const isRelatedPostsEnabled = APP_BLOG.isRelatedPostsEnabled;
|
export const isRelatedPostsEnabled = APP_BLOG.isRelatedPostsEnabled
|
||||||
export const isBlogListRouteEnabled = APP_BLOG.list.isEnabled;
|
export const isBlogListRouteEnabled = APP_BLOG.list.isEnabled
|
||||||
export const isBlogPostRouteEnabled = APP_BLOG.post.isEnabled;
|
export const isBlogPostRouteEnabled = APP_BLOG.post.isEnabled
|
||||||
export const isBlogCategoryRouteEnabled = APP_BLOG.category.isEnabled;
|
export const isBlogCategoryRouteEnabled = APP_BLOG.category.isEnabled
|
||||||
export const isBlogTagRouteEnabled = APP_BLOG.tag.isEnabled;
|
export const isBlogTagRouteEnabled = APP_BLOG.tag.isEnabled
|
||||||
|
|
||||||
export const blogListRobots = APP_BLOG.list.robots;
|
export const blogListRobots = APP_BLOG.list.robots
|
||||||
export const blogPostRobots = APP_BLOG.post.robots;
|
export const blogPostRobots = APP_BLOG.post.robots
|
||||||
export const blogCategoryRobots = APP_BLOG.category.robots;
|
export const blogCategoryRobots = APP_BLOG.category.robots
|
||||||
export const blogTagRobots = APP_BLOG.tag.robots;
|
export const blogTagRobots = APP_BLOG.tag.robots
|
||||||
|
|
||||||
export const blogPostsPerPage = APP_BLOG?.postsPerPage;
|
export const blogPostsPerPage = APP_BLOG?.postsPerPage
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const fetchPosts = async (): Promise<Array<Post>> => {
|
export const fetchPosts = async (): Promise<Array<Post>> => {
|
||||||
if (!_posts) {
|
if (!_posts) {
|
||||||
_posts = await load();
|
// eslint-disable-next-line require-atomic-updates
|
||||||
|
_posts = await load()
|
||||||
}
|
}
|
||||||
|
|
||||||
return _posts;
|
return _posts
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const findPostsBySlugs = async (slugs: Array<string>): Promise<Array<Post>> => {
|
export const findPostsBySlugs = async (slugs: Array<string>): Promise<Array<Post>> => {
|
||||||
if (!Array.isArray(slugs)) return [];
|
if (!Array.isArray(slugs)) {return []}
|
||||||
|
|
||||||
const posts = await fetchPosts();
|
const posts = await fetchPosts()
|
||||||
|
|
||||||
return slugs.reduce(function (r: Array<Post>, slug: string) {
|
return slugs.reduce(function(r: Array<Post>, slug: string) {
|
||||||
posts.some(function (post: Post) {
|
posts.some(function(post: Post) {
|
||||||
return slug === post.slug && r.push(post);
|
return slug === post.slug && r.push(post)
|
||||||
});
|
})
|
||||||
return r;
|
return r
|
||||||
}, []);
|
}, [])
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const findPostsByIds = async (ids: Array<string>): Promise<Array<Post>> => {
|
export const findPostsByIds = async (ids: Array<string>): Promise<Array<Post>> => {
|
||||||
if (!Array.isArray(ids)) return [];
|
if (!Array.isArray(ids)) {return []}
|
||||||
|
|
||||||
const posts = await fetchPosts();
|
const posts = await fetchPosts()
|
||||||
|
|
||||||
return ids.reduce(function (r: Array<Post>, id: string) {
|
return ids.reduce(function(r: Array<Post>, id: string) {
|
||||||
posts.some(function (post: Post) {
|
posts.some(function(post: Post) {
|
||||||
return id === post.id && r.push(post);
|
return id === post.id && r.push(post)
|
||||||
});
|
})
|
||||||
return r;
|
return r
|
||||||
}, []);
|
}, [])
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const findLatestPosts = async ({ count }: { count?: number }): Promise<Array<Post>> => {
|
export const findLatestPosts = async ({ count }: { count?: number }): Promise<Array<Post>> => {
|
||||||
const _count = count || 4;
|
const _count = count || 4
|
||||||
const posts = await fetchPosts();
|
const posts = await fetchPosts()
|
||||||
|
|
||||||
return posts ? posts.slice(0, _count) : [];
|
return posts ? posts.slice(0, _count) : []
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getStaticPathsBlogList = async ({ paginate }: { paginate: PaginateFunction }) => {
|
export const getStaticPathsBlogList = async ({ paginate }: { paginate: PaginateFunction }) => {
|
||||||
if (!isBlogEnabled || !isBlogListRouteEnabled) return [];
|
if (!isBlogEnabled || !isBlogListRouteEnabled) {return []}
|
||||||
return paginate(await fetchPosts(), {
|
return paginate(await fetchPosts(), {
|
||||||
params: { blog: BLOG_BASE || undefined },
|
params: { blog: BLOG_BASE || undefined },
|
||||||
pageSize: blogPostsPerPage,
|
pageSize: blogPostsPerPage,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getStaticPathsBlogPost = async () => {
|
export const getStaticPathsBlogPost = async () => {
|
||||||
if (!isBlogEnabled || !isBlogPostRouteEnabled) return [];
|
if (!isBlogEnabled || !isBlogPostRouteEnabled) {return []}
|
||||||
return (await fetchPosts()).flatMap((post) => ({
|
return (await fetchPosts()).flatMap((post) => ({
|
||||||
params: {
|
params: {
|
||||||
blog: post.permalink,
|
blog: post.permalink,
|
||||||
},
|
},
|
||||||
props: { post },
|
props: { post },
|
||||||
}));
|
}))
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getStaticPathsBlogCategory = async ({ paginate }: { paginate: PaginateFunction }) => {
|
export const getStaticPathsBlogCategory = async ({ paginate }: { paginate: PaginateFunction }) => {
|
||||||
if (!isBlogEnabled || !isBlogCategoryRouteEnabled) return [];
|
if (!isBlogEnabled || !isBlogCategoryRouteEnabled) {return []}
|
||||||
|
|
||||||
const posts = await fetchPosts();
|
const posts = await fetchPosts()
|
||||||
const categories = {};
|
const categories = {}
|
||||||
posts.map((post) => {
|
posts.map((post) => {
|
||||||
post.category?.slug && (categories[post.category?.slug] = post.category);
|
post.category?.slug && (categories[post.category?.slug] = post.category)
|
||||||
});
|
})
|
||||||
|
|
||||||
return Array.from(Object.keys(categories)).flatMap((categorySlug) =>
|
return Array.from(Object.keys(categories)).flatMap((categorySlug) =>
|
||||||
paginate(
|
paginate(
|
||||||
@ -212,21 +215,21 @@ export const getStaticPathsBlogCategory = async ({ paginate }: { paginate: Pagin
|
|||||||
props: { category: categories[categorySlug] },
|
props: { category: categories[categorySlug] },
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getStaticPathsBlogTag = async ({ paginate }: { paginate: PaginateFunction }) => {
|
export const getStaticPathsBlogTag = async ({ paginate }: { paginate: PaginateFunction }) => {
|
||||||
if (!isBlogEnabled || !isBlogTagRouteEnabled) return [];
|
if (!isBlogEnabled || !isBlogTagRouteEnabled) {return []}
|
||||||
|
|
||||||
const posts = await fetchPosts();
|
const posts = await fetchPosts()
|
||||||
const tags = {};
|
const tags = {}
|
||||||
posts.map((post) => {
|
posts.map((post) => {
|
||||||
Array.isArray(post.tags) &&
|
Array.isArray(post.tags) &&
|
||||||
post.tags.map((tag) => {
|
post.tags.map((tag) => {
|
||||||
tags[tag?.slug] = tag;
|
tags[tag?.slug] = tag
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
return Array.from(Object.keys(tags)).flatMap((tagSlug) =>
|
return Array.from(Object.keys(tags)).flatMap((tagSlug) =>
|
||||||
paginate(
|
paginate(
|
||||||
@ -237,42 +240,42 @@ export const getStaticPathsBlogTag = async ({ paginate }: { paginate: PaginateFu
|
|||||||
props: { tag: tags[tagSlug] },
|
props: { tag: tags[tagSlug] },
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export async function getRelatedPosts(originalPost: Post, maxResults: number = 4): Promise<Post[]> {
|
export async function getRelatedPosts(originalPost: Post, maxResults = 4): Promise<Array<Post>> {
|
||||||
const allPosts = await fetchPosts();
|
const allPosts = await fetchPosts()
|
||||||
const originalTagsSet = new Set(originalPost.tags ? originalPost.tags.map((tag) => tag.slug) : []);
|
const originalTagsSet = new Set(originalPost.tags ? originalPost.tags.map((tag) => tag.slug) : [])
|
||||||
|
|
||||||
const postsWithScores = allPosts.reduce((acc: { post: Post; score: number }[], iteratedPost: Post) => {
|
const postsWithScores = allPosts.reduce((acc: Array<{ post: Post, score: number }>, iteratedPost: Post) => {
|
||||||
if (iteratedPost.slug === originalPost.slug) return acc;
|
if (iteratedPost.slug === originalPost.slug) {return acc}
|
||||||
|
|
||||||
let score = 0;
|
let score = 0
|
||||||
if (iteratedPost.category && originalPost.category && iteratedPost.category.slug === originalPost.category.slug) {
|
if (iteratedPost.category && originalPost.category && iteratedPost.category.slug === originalPost.category.slug) {
|
||||||
score += 5;
|
score += 5
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iteratedPost.tags) {
|
if (iteratedPost.tags) {
|
||||||
iteratedPost.tags.forEach((tag) => {
|
iteratedPost.tags.forEach((tag) => {
|
||||||
if (originalTagsSet.has(tag.slug)) {
|
if (originalTagsSet.has(tag.slug)) {
|
||||||
score += 1;
|
score += 1
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
acc.push({ post: iteratedPost, score });
|
acc.push({ post: iteratedPost, score })
|
||||||
return acc;
|
return acc
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
postsWithScores.sort((a, b) => b.score - a.score);
|
postsWithScores.sort((a, b) => b.score - a.score)
|
||||||
|
|
||||||
const selectedPosts: Post[] = [];
|
const selectedPosts: Array<Post> = []
|
||||||
let i = 0;
|
let i = 0
|
||||||
while (selectedPosts.length < maxResults && i < postsWithScores.length) {
|
while (selectedPosts.length < maxResults && i < postsWithScores.length) {
|
||||||
selectedPosts.push(postsWithScores[i].post);
|
selectedPosts.push(postsWithScores[i].post)
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedPosts;
|
return selectedPosts
|
||||||
}
|
}
|
||||||
|
@ -1,46 +1,47 @@
|
|||||||
import slugify from 'limax';
|
/* eslint-disable max-depth */
|
||||||
|
/* eslint-disable complexity */
|
||||||
|
import slugify from 'limax'
|
||||||
|
|
||||||
import { SITE, APP_BLOG } from 'astrowind:config';
|
import { SITE, APP_BLOG } from 'astrowind:config'
|
||||||
|
|
||||||
import { trim } from '~/utils/utils';
|
import { trim } from 'utils/utils'
|
||||||
|
|
||||||
export const trimSlash = (s: string) => trim(trim(s, '/'));
|
export const trimSlash = (s: string) => trim(trim(s, '/'))
|
||||||
const createPath = (...params: string[]) => {
|
const createPath = (...params: Array<string>) => {
|
||||||
const paths = params
|
const paths = params
|
||||||
.map((el) => trimSlash(el))
|
.map((el) => trimSlash(el))
|
||||||
.filter((el) => !!el)
|
.filter((el) => !!el)
|
||||||
.join('/');
|
.join('/')
|
||||||
return '/' + paths + (SITE.trailingSlash && paths ? '/' : '');
|
return '/' + paths + (SITE.trailingSlash && paths ? '/' : '')
|
||||||
};
|
}
|
||||||
|
|
||||||
const BASE_PATHNAME = SITE.base || '/';
|
const BASE_PATHNAME = SITE.base || '/'
|
||||||
|
|
||||||
export const cleanSlug = (text = '') =>
|
export const cleanSlug = (text = '') =>
|
||||||
trimSlash(text)
|
trimSlash(text)
|
||||||
.split('/')
|
.split('/')
|
||||||
.map((slug) => slugify(slug))
|
.map((slug) => slugify(slug))
|
||||||
.join('/');
|
.join('/')
|
||||||
|
|
||||||
export const BLOG_BASE = cleanSlug(APP_BLOG?.list?.pathname);
|
export const BLOG_BASE = cleanSlug(APP_BLOG?.list?.pathname)
|
||||||
export const CATEGORY_BASE = cleanSlug(APP_BLOG?.category?.pathname);
|
export const CATEGORY_BASE = cleanSlug(APP_BLOG?.category?.pathname)
|
||||||
export const TAG_BASE = cleanSlug(APP_BLOG?.tag?.pathname) || 'tag';
|
export const TAG_BASE = cleanSlug(APP_BLOG?.tag?.pathname) || 'tag'
|
||||||
|
|
||||||
export const POST_PERMALINK_PATTERN = trimSlash(APP_BLOG?.post?.permalink || `${BLOG_BASE}/%slug%`);
|
export const POST_PERMALINK_PATTERN = trimSlash(APP_BLOG?.post?.permalink || `${BLOG_BASE}/%slug%`)
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getCanonical = (path = ''): string | URL => {
|
export const getCanonical = (path = ''): string | URL => {
|
||||||
const url = String(new URL(path, SITE.site));
|
const url = String(new URL(path, SITE.site))
|
||||||
if (SITE.trailingSlash == false && path && url.endsWith('/')) {
|
if (SITE.trailingSlash === false && path && url.endsWith('/')) {
|
||||||
return url.slice(0, -1);
|
return url.slice(0, -1)
|
||||||
} else if (SITE.trailingSlash == true && path && !url.endsWith('/')) {
|
} else if (SITE.trailingSlash == true && path && !url.endsWith('/')) {
|
||||||
return url + '/';
|
return url + '/'
|
||||||
}
|
}
|
||||||
return url;
|
return url
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
export const getPermalink = (slug = '', type = 'page'): string => {
|
export const getPermalink = (slug = '', type = 'page'): string => {
|
||||||
let permalink: string;
|
let permalink: string
|
||||||
|
|
||||||
if (
|
if (
|
||||||
slug.startsWith('https://') ||
|
slug.startsWith('https://') ||
|
||||||
@ -49,48 +50,48 @@ export const getPermalink = (slug = '', type = 'page'): string => {
|
|||||||
slug.startsWith('#') ||
|
slug.startsWith('#') ||
|
||||||
slug.startsWith('javascript:')
|
slug.startsWith('javascript:')
|
||||||
) {
|
) {
|
||||||
return slug;
|
return slug
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'home':
|
case 'home':
|
||||||
permalink = getHomePermalink();
|
permalink = getHomePermalink()
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'blog':
|
case 'blog':
|
||||||
permalink = getBlogPermalink();
|
permalink = getBlogPermalink()
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'asset':
|
case 'asset':
|
||||||
permalink = getAsset(slug);
|
permalink = getAsset(slug)
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'category':
|
case 'category':
|
||||||
permalink = createPath(CATEGORY_BASE, trimSlash(slug));
|
permalink = createPath(CATEGORY_BASE, trimSlash(slug))
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'tag':
|
case 'tag':
|
||||||
permalink = createPath(TAG_BASE, trimSlash(slug));
|
permalink = createPath(TAG_BASE, trimSlash(slug))
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'post':
|
case 'post':
|
||||||
permalink = createPath(trimSlash(slug));
|
permalink = createPath(trimSlash(slug))
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'page':
|
case 'page':
|
||||||
default:
|
default:
|
||||||
permalink = createPath(slug);
|
permalink = createPath(slug)
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return definitivePermalink(permalink);
|
return definitivePermalink(permalink)
|
||||||
};
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getHomePermalink = (): string => getPermalink('/');
|
export const getHomePermalink = (): string => getPermalink('/')
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getBlogPermalink = (): string => getPermalink(BLOG_BASE);
|
export const getBlogPermalink = (): string => getPermalink(BLOG_BASE)
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const getAsset = (path: string): string =>
|
export const getAsset = (path: string): string =>
|
||||||
@ -98,37 +99,37 @@ export const getAsset = (path: string): string =>
|
|||||||
[BASE_PATHNAME, path]
|
[BASE_PATHNAME, path]
|
||||||
.map((el) => trimSlash(el))
|
.map((el) => trimSlash(el))
|
||||||
.filter((el) => !!el)
|
.filter((el) => !!el)
|
||||||
.join('/');
|
.join('/')
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
const definitivePermalink = (permalink: string): string => createPath(BASE_PATHNAME, permalink);
|
const definitivePermalink = (permalink: string): string => createPath(BASE_PATHNAME, permalink)
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const applyGetPermalinks = (menu: object = {}) => {
|
export const applyGetPermalinks = (menu: object = {}) => {
|
||||||
if (Array.isArray(menu)) {
|
if (Array.isArray(menu)) {
|
||||||
return menu.map((item) => applyGetPermalinks(item));
|
return menu.map((item) => applyGetPermalinks(item))
|
||||||
} else if (typeof menu === 'object' && menu !== null) {
|
} else if (typeof menu === 'object' && menu !== null) {
|
||||||
const obj = {};
|
const obj = {}
|
||||||
for (const key in menu) {
|
for (const key in menu) {
|
||||||
if (key === 'href') {
|
if (key === 'href') {
|
||||||
if (typeof menu[key] === 'string') {
|
if (typeof menu[key] === 'string') {
|
||||||
obj[key] = getPermalink(menu[key]);
|
obj[key] = getPermalink(menu[key])
|
||||||
} else if (typeof menu[key] === 'object') {
|
} else if (typeof menu[key] === 'object') {
|
||||||
if (menu[key].type === 'home') {
|
if (menu[key].type === 'home') {
|
||||||
obj[key] = getHomePermalink();
|
obj[key] = getHomePermalink()
|
||||||
} else if (menu[key].type === 'blog') {
|
} else if (menu[key].type === 'blog') {
|
||||||
obj[key] = getBlogPermalink();
|
obj[key] = getBlogPermalink()
|
||||||
} else if (menu[key].type === 'asset') {
|
} else if (menu[key].type === 'asset') {
|
||||||
obj[key] = getAsset(menu[key].url);
|
obj[key] = getAsset(menu[key].url)
|
||||||
} else if (menu[key].url) {
|
} else if (menu[key].url) {
|
||||||
obj[key] = getPermalink(menu[key].url, menu[key].type);
|
obj[key] = getPermalink(menu[key].url, menu[key].type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
obj[key] = applyGetPermalinks(menu[key]);
|
obj[key] = applyGetPermalinks(menu[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj;
|
return obj
|
||||||
}
|
}
|
||||||
return menu;
|
return menu
|
||||||
};
|
}
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
// hide an issue with typescript
|
// hide an issue with typescript
|
||||||
"noUnusedLocals": false
|
"noUnusedLocals": false,
|
||||||
|
"noImplicitAny": false,
|
||||||
},
|
},
|
||||||
"ts-node": {
|
"ts-node": {
|
||||||
"esm": true
|
"esm": true
|
||||||
|
153
front/vendor/integration/utils/configBuilder.ts
vendored
153
front/vendor/integration/utils/configBuilder.ts
vendored
@ -1,86 +1,87 @@
|
|||||||
import merge from 'lodash.merge';
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
||||||
|
import merge from 'lodash.merge'
|
||||||
|
|
||||||
import type { MetaData } from '~/types';
|
import type { MetaData } from 'types'
|
||||||
|
|
||||||
type Config = {
|
interface Config {
|
||||||
site?: SiteConfig;
|
site?: SiteConfig
|
||||||
metadata?: MetaDataConfig;
|
metadata?: MetaDataConfig
|
||||||
i18n?: I18NConfig;
|
i18n?: I18NConfig
|
||||||
apps?: {
|
apps?: {
|
||||||
blog?: AppBlogConfig;
|
blog?: AppBlogConfig
|
||||||
};
|
}
|
||||||
ui?: unknown;
|
ui?: unknown
|
||||||
analytics?: unknown;
|
analytics?: unknown
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface SiteConfig {
|
export interface SiteConfig {
|
||||||
name: string;
|
name: string
|
||||||
site?: string;
|
site?: string
|
||||||
base?: string;
|
base?: string
|
||||||
trailingSlash?: boolean;
|
trailingSlash?: boolean
|
||||||
googleSiteVerificationId?: string;
|
googleSiteVerificationId?: string
|
||||||
}
|
}
|
||||||
export interface MetaDataConfig extends Omit<MetaData, 'title'> {
|
export interface MetaDataConfig extends Omit<MetaData, 'title'> {
|
||||||
title?: {
|
title?: {
|
||||||
default: string;
|
default: string
|
||||||
template: string;
|
template: string
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
export interface I18NConfig {
|
export interface I18NConfig {
|
||||||
language: string;
|
language: string
|
||||||
textDirection: string;
|
textDirection: string
|
||||||
dateFormatter?: Intl.DateTimeFormat;
|
dateFormatter?: Intl.DateTimeFormat
|
||||||
}
|
}
|
||||||
export interface AppBlogConfig {
|
export interface AppBlogConfig {
|
||||||
isEnabled: boolean;
|
isEnabled: boolean
|
||||||
postsPerPage: number;
|
postsPerPage: number
|
||||||
isRelatedPostsEnabled: boolean;
|
isRelatedPostsEnabled: boolean
|
||||||
relatedPostsCount: number;
|
relatedPostsCount: number
|
||||||
post: {
|
post: {
|
||||||
isEnabled: boolean;
|
isEnabled: boolean
|
||||||
permalink: string;
|
permalink: string
|
||||||
robots: {
|
robots: {
|
||||||
index: boolean;
|
index: boolean
|
||||||
follow: boolean;
|
follow: boolean
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
list: {
|
list: {
|
||||||
isEnabled: boolean;
|
isEnabled: boolean
|
||||||
pathname: string;
|
pathname: string
|
||||||
robots: {
|
robots: {
|
||||||
index: boolean;
|
index: boolean
|
||||||
follow: boolean;
|
follow: boolean
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
category: {
|
category: {
|
||||||
isEnabled: boolean;
|
isEnabled: boolean
|
||||||
pathname: string;
|
pathname: string
|
||||||
robots: {
|
robots: {
|
||||||
index: boolean;
|
index: boolean
|
||||||
follow: boolean;
|
follow: boolean
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
tag: {
|
tag: {
|
||||||
isEnabled: boolean;
|
isEnabled: boolean
|
||||||
pathname: string;
|
pathname: string
|
||||||
robots: {
|
robots: {
|
||||||
index: boolean;
|
index: boolean
|
||||||
follow: boolean;
|
follow: boolean
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
export interface AnalyticsConfig {
|
export interface AnalyticsConfig {
|
||||||
vendors: {
|
vendors: {
|
||||||
googleAnalytics: {
|
googleAnalytics: {
|
||||||
id?: string;
|
id?: string
|
||||||
partytown?: boolean;
|
partytown?: boolean
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UIConfig {}
|
export interface UIConfig {}
|
||||||
|
|
||||||
const DEFAULT_SITE_NAME = 'Website';
|
const DEFAULT_SITE_NAME = 'Website'
|
||||||
|
|
||||||
const getSite = (config: Config) => {
|
const getSite = (config: Config) => {
|
||||||
const _default = {
|
const _default = {
|
||||||
@ -90,13 +91,13 @@ const getSite = (config: Config) => {
|
|||||||
trailingSlash: false,
|
trailingSlash: false,
|
||||||
|
|
||||||
googleSiteVerificationId: '',
|
googleSiteVerificationId: '',
|
||||||
};
|
}
|
||||||
|
|
||||||
return merge({}, _default, config?.site ?? {}) as SiteConfig;
|
return merge({}, _default, config?.site ?? {}) as SiteConfig
|
||||||
};
|
}
|
||||||
|
|
||||||
const getMetadata = (config: Config) => {
|
const getMetadata = (config: Config) => {
|
||||||
const siteConfig = getSite(config);
|
const siteConfig = getSite(config)
|
||||||
|
|
||||||
const _default = {
|
const _default = {
|
||||||
title: {
|
title: {
|
||||||
@ -111,21 +112,21 @@ const getMetadata = (config: Config) => {
|
|||||||
openGraph: {
|
openGraph: {
|
||||||
type: 'website',
|
type: 'website',
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
return merge({}, _default, config?.metadata ?? {}) as MetaDataConfig;
|
return merge({}, _default, config?.metadata ?? {}) as MetaDataConfig
|
||||||
};
|
}
|
||||||
|
|
||||||
const getI18N = (config: Config) => {
|
const getI18N = (config: Config) => {
|
||||||
const _default = {
|
const _default = {
|
||||||
language: 'en',
|
language: 'en',
|
||||||
textDirection: 'ltr',
|
textDirection: 'ltr',
|
||||||
};
|
}
|
||||||
|
|
||||||
const value = merge({}, _default, config?.i18n ?? {});
|
const value = merge({}, _default, config?.i18n ?? {})
|
||||||
|
|
||||||
return value as I18NConfig;
|
return value as I18NConfig
|
||||||
};
|
}
|
||||||
|
|
||||||
const getAppBlog = (config: Config) => {
|
const getAppBlog = (config: Config) => {
|
||||||
const _default = {
|
const _default = {
|
||||||
@ -165,18 +166,18 @@ const getAppBlog = (config: Config) => {
|
|||||||
follow: true,
|
follow: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
return merge({}, _default, config?.apps?.blog ?? {}) as AppBlogConfig;
|
return merge({}, _default, config?.apps?.blog ?? {}) as AppBlogConfig
|
||||||
};
|
}
|
||||||
|
|
||||||
const getUI = (config: Config) => {
|
const getUI = (config: Config) => {
|
||||||
const _default = {
|
const _default = {
|
||||||
theme: 'system',
|
theme: 'system',
|
||||||
};
|
}
|
||||||
|
|
||||||
return merge({}, _default, config?.ui ?? {});
|
return merge({}, _default, config?.ui ?? {})
|
||||||
};
|
}
|
||||||
|
|
||||||
const getAnalytics = (config: Config) => {
|
const getAnalytics = (config: Config) => {
|
||||||
const _default = {
|
const _default = {
|
||||||
@ -186,10 +187,10 @@ const getAnalytics = (config: Config) => {
|
|||||||
partytown: true,
|
partytown: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
return merge({}, _default, config?.analytics ?? {}) as AnalyticsConfig;
|
return merge({}, _default, config?.analytics ?? {}) as AnalyticsConfig
|
||||||
};
|
}
|
||||||
|
|
||||||
export default (config: Config) => ({
|
export default (config: Config) => ({
|
||||||
SITE: getSite(config),
|
SITE: getSite(config),
|
||||||
@ -198,4 +199,4 @@ export default (config: Config) => ({
|
|||||||
APP_BLOG: getAppBlog(config),
|
APP_BLOG: getAppBlog(config),
|
||||||
UI: getUI(config),
|
UI: getUI(config),
|
||||||
ANALYTICS: getAnalytics(config),
|
ANALYTICS: getAnalytics(config),
|
||||||
});
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user