diff options
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/helpers/format.ts | 332 | ||||
| -rw-r--r-- | src/utils/helpers/i18n.ts | 2 | ||||
| -rw-r--r-- | src/utils/helpers/prism.ts | 34 | ||||
| -rw-r--r-- | src/utils/helpers/projects.ts | 86 | ||||
| -rw-r--r-- | src/utils/helpers/sort.ts | 21 | ||||
| -rw-r--r-- | src/utils/hooks/useGithubApi.tsx | 23 | ||||
| -rw-r--r-- | src/utils/hooks/useHeadingsTree.tsx | 104 | ||||
| -rw-r--r-- | src/utils/providers/ackee.tsx | 3 | ||||
| -rw-r--r-- | src/utils/providers/prism-theme.tsx | 2 | 
9 files changed, 5 insertions, 602 deletions
| diff --git a/src/utils/helpers/format.ts b/src/utils/helpers/format.ts deleted file mode 100644 index 47a7b57..0000000 --- a/src/utils/helpers/format.ts +++ /dev/null @@ -1,332 +0,0 @@ -import { ParamsIds, ParamsSlug, Slug } from '@ts/types/app'; -import { -  Article, -  ArticlePreview, -  RawArticle, -  RawArticlePreview, -} from '@ts/types/articles'; -import { Comment, RawComment } from '@ts/types/comments'; -import { -  RawTopic, -  RawTopicPreview, -  RawThematic, -  Topic, -  TopicPreview, -  Thematic, -} from '@ts/types/taxonomies'; -import { settings } from '@utils/config'; - -/** - * Format a post preview from RawArticlePreview to ArticlePreview type. - * @param rawPost - A post preview coming from WP GraphQL. - * @returns A formatted post preview. - */ -export const getFormattedPostPreview = (rawPost: RawArticlePreview) => { -  const { -    acfPosts, -    commentCount, -    contentParts, -    date, -    featuredImage, -    id, -    info, -    modified, -    slug, -    title, -  } = rawPost; - -  const dates = { -    publication: date, -    update: modified, -  }; - -  const topics = acfPosts.postsInTopic ? acfPosts.postsInTopic : []; -  const thematics = acfPosts.postsInThematic ? acfPosts.postsInThematic : []; - -  const formattedPost: ArticlePreview = { -    commentCount, -    dates, -    featuredImage: featuredImage ? featuredImage.node : null, -    id, -    info, -    intro: contentParts.beforeMore, -    slug, -    topics, -    thematics, -    title, -  }; - -  return formattedPost; -}; - -/** - * Format an array of posts list from RawArticlePreview to ArticlePreview type. - * @param rawPosts - A posts list coming from WP GraphQL. - * @returns A formatted posts list. - */ -export const getFormattedPostsList = ( -  rawPosts: RawArticlePreview[] -): ArticlePreview[] => { -  return rawPosts -    .filter((post) => Object.getOwnPropertyNames(post).length > 0) -    .map((post) => { -      return getFormattedPostPreview(post); -    }); -}; - -/** - * Format a topic from RawTopic to Topic type. - * @param rawTopic - A topic coming from WP GraphQL. - * @returns A formatted topic. - */ -export const getFormattedTopic = (rawTopic: RawTopic): Topic => { -  const { -    acfTopics, -    contentParts, -    databaseId, -    date, -    featuredImage, -    id, -    info, -    modified, -    seo, -    title, -  } = rawTopic; - -  const dates = { -    publication: date, -    update: modified, -  }; - -  const posts = getFormattedPostsList(acfTopics.postsInTopic); - -  const formattedTopic: Topic = { -    content: contentParts.afterMore, -    databaseId, -    dates, -    featuredImage: featuredImage ? featuredImage.node : null, -    id, -    info, -    intro: contentParts.beforeMore, -    officialWebsite: acfTopics.officialWebsite, -    posts, -    seo, -    title, -  }; - -  return formattedTopic; -}; - -/** - * Format a thematic from RawThematic to Thematic type. - * @param rawThematic - A thematic coming from wP GraphQL. - * @returns A formatted thematic. - */ -export const getFormattedThematic = (rawThematic: RawThematic): Thematic => { -  const { -    acfThematics, -    contentParts, -    databaseId, -    date, -    id, -    info, -    modified, -    seo, -    title, -  } = rawThematic; - -  const dates = { -    publication: date, -    update: modified, -  }; - -  const posts = getFormattedPostsList(acfThematics.postsInThematic); - -  const formattedThematic: Thematic = { -    content: contentParts.afterMore, -    databaseId, -    dates, -    id, -    info, -    intro: contentParts.beforeMore, -    posts, -    seo, -    title, -  }; - -  return formattedThematic; -}; - -/** - * Format a comments list from RawComment to Comment type. - * @param rawComments - A comments list coming from WP GraphQL. - * @returns A formatted comments list. - */ -export const getFormattedComments = (rawComments: RawComment[]): Comment[] => { -  const formattedComments: Comment[] = rawComments.map((comment) => { -    const formattedComment: Comment = { -      ...comment, -      author: comment.author.node, -      replies: [], -    }; - -    return formattedComment; -  }); - -  return formattedComments; -}; - -/** - * Create a comments tree with replies. - * @param comments - A flatten comments list. - * @returns An array of comments with replies. - */ -export const buildCommentsTree = (comments: Comment[]) => { -  type CommentsHashTable = { -    [key: string]: Comment; -  }; - -  const hashTable: CommentsHashTable = Object.create(null); -  const commentsTree: Comment[] = []; - -  comments.forEach( -    (comment) => (hashTable[comment.databaseId] = { ...comment, replies: [] }) -  ); - -  comments.forEach((comment) => { -    if (!comment.parentDatabaseId) { -      commentsTree.push(hashTable[comment.databaseId]); -    } else { -      hashTable[comment.parentDatabaseId].replies.push( -        hashTable[comment.databaseId] -      ); -    } -  }); - -  return commentsTree; -}; - -export const getFormattedTopicsPreview = ( -  topics: RawTopicPreview[] -): TopicPreview[] => { -  const formattedTopics: TopicPreview[] = topics.map((topic) => { -    return { -      ...topic, -      featuredImage: topic.featuredImage ? topic.featuredImage.node : null, -    }; -  }); - -  return formattedTopics; -}; - -/** - * Format an article from RawArticle to Article type. - * @param rawPost - An article coming from WP GraphQL. - * @returns A formatted article. - */ -export const getFormattedPost = (rawPost: RawArticle): Article => { -  const { -    acfPosts, -    author, -    commentCount, -    contentParts, -    databaseId, -    date, -    featuredImage, -    id, -    info, -    modified, -    seo, -    title, -  } = rawPost; - -  const dates = { -    publication: date, -    update: modified, -  }; - -  const topics = acfPosts.postsInTopic -    ? getFormattedTopicsPreview(acfPosts.postsInTopic) -    : []; - -  const formattedPost: Article = { -    author: author.node, -    commentCount, -    content: contentParts.afterMore, -    databaseId, -    dates, -    featuredImage: featuredImage ? featuredImage.node : null, -    id, -    info, -    intro: contentParts.beforeMore, -    seo, -    topics, -    thematics: acfPosts.postsInThematic ? acfPosts.postsInThematic : [], -    title, -  }; - -  return formattedPost; -}; - -/** - * Converts a date to a string by using the specified locale. - * @param {string} date - The date. - * @param {string} [locale] - A locale. - * @returns {string} The formatted date to locale date string. - */ -export const getFormattedDate = ( -  date: string, -  locale: string = settings.locales.defaultLocale -): string => { -  const dateOptions: Intl.DateTimeFormatOptions = { -    day: 'numeric', -    month: 'long', -    year: 'numeric', -  }; - -  return new Date(date).toLocaleDateString(locale, dateOptions); -}; - -/** - * Converts a date to a time string by using the specified locale. - * @param {string} date - The date. - * @param {string} [locale] - A locale. - * @returns {string} The formatted time to locale date string. - */ -export const getFormattedTime = ( -  date: string, -  locale: string = settings.locales.defaultLocale -): string => { -  const time = new Date(date).toLocaleTimeString(locale, { -    hour: 'numeric', -    minute: 'numeric', -  }); - -  return locale === 'fr' ? time.replace(':', 'h') : time; -}; - -/** - * Convert an array of slugs to an array of params with slug. - * @param {Slug} array - An array of object with slug. - * @returns {ParamsSlug} An array of params with slug. - */ -export const getFormattedPaths = (array: Slug[]): ParamsSlug[] => { -  return array.map((object) => { -    return { params: { slug: object.slug } }; -  }); -}; - -/** - * Convert a number of pages to an array of params with ids. - * @param {number} totalPages - The total pages. - * @returns {ParamsIds} An array of params with ids. - */ -export const getFormattedPageNumbers = (totalPages: number): ParamsIds[] => { -  const paths = []; - -  for (let i = 1; i <= totalPages; i++) { -    paths.push({ params: { id: `${i}` } }); -  } - -  return paths; -}; diff --git a/src/utils/helpers/i18n.ts b/src/utils/helpers/i18n.ts index c4734ad..5d19c8c 100644 --- a/src/utils/helpers/i18n.ts +++ b/src/utils/helpers/i18n.ts @@ -3,7 +3,7 @@ import { settings } from '@utils/config';  import { readFile } from 'fs/promises';  import path from 'path'; -type Messages = { [key: string]: string }; +export type Messages = { [key: string]: string };  export const defaultLocale = settings.locales.defaultLocale; diff --git a/src/utils/helpers/prism.ts b/src/utils/helpers/prism.ts deleted file mode 100644 index a5f5787..0000000 --- a/src/utils/helpers/prism.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Check if the current block has a defined language. - * @param classList - A list of class. - * @returns {boolean} - True if a class starts with "language-". - */ -const isLanguageBlock = (classList: DOMTokenList) => { -  const classes = Array.from(classList); -  return classes.some((className) => /language-.*/.test(className)); -}; - -/** - * Add automatically some classes and attributes for PrismJs. - * - * These classes and attributes are needed by Prism or to customize comments. - */ -export const addPrismClasses = () => { -  const preTags = document.getElementsByTagName('pre'); - -  Array.from(preTags).forEach((preTag) => { -    if (!isLanguageBlock(preTag.classList)) return; - -    preTag.classList.add('match-braces'); - -    if (preTag.classList.contains('filter-output')) { -      preTag.setAttribute('data-filter-output', '#output#'); -    } - -    if (preTag.classList.contains('language-bash')) { -      preTag.classList.add('command-line'); -    } else if (!preTag.classList.contains('language-diff')) { -      preTag.classList.add('line-numbers'); -    } -  }); -}; diff --git a/src/utils/helpers/projects.ts b/src/utils/helpers/projects.ts deleted file mode 100644 index 1612dae..0000000 --- a/src/utils/helpers/projects.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Project, ProjectMeta } from '@ts/types/app'; -import { readdirSync } from 'fs'; -import path from 'path'; - -/** - * Retrieve project's data by id. - * @param {string} id - The filename without extension. - * @returns {Promise<Project>} - The project data. - */ -export const getProjectData = async (id: string): Promise<Project> => { -  try { -    const { -      intro, -      meta, -      seo, -      tagline, -    }: { -      intro: string; -      meta: ProjectMeta & { title: string }; -      seo: { title: string; description: string }; -      tagline?: string; -    } = await import(`../../content/projects/${id}.mdx`); - -    const { title, ...onlyMeta } = meta; - -    return { -      id, -      intro: intro || '', -      meta: onlyMeta || {}, -      slug: id, -      title, -      seo: seo || {}, -      tagline: tagline || '', -    }; -  } catch (err) { -    console.error(err); -    throw err; -  } -}; - -/** - * Retrieve the projects data from filenames. - * @param {string[]} filenames - An array of filenames. - * @returns {Promise<Project[]>} An array of projects with meta. - */ -const getProjectsWithMeta = async (filenames: string[]): Promise<Project[]> => { -  return Promise.all( -    filenames.map(async (filename) => { -      return getProjectData(filename); -    }) -  ); -}; - -/** - * Method to sort an array of projects by publication date. - * @param {Project} a - A single project. - * @param {Project} b - A single project. - * @returns The result used by Array.sort() method: 1 || -1 || 0. - */ -const sortProjectByPublicationDate = (a: Project, b: Project) => { -  if (a.meta.publishedOn < b.meta.publishedOn) return 1; -  if (a.meta.publishedOn > b.meta.publishedOn) return -1; -  return 0; -}; - -/** - * Retrieve all the projects filename. - * @returns {string[]} An array of filenames. - */ -export const getAllProjectsFilename = (): string[] => { -  const projectsDirectory = path.join(process.cwd(), 'src/content/projects'); -  const filenames = readdirSync(projectsDirectory); - -  return filenames.map((filename) => filename.replace(/\.mdx$/, '')); -}; - -/** - * Retrieve all projects in content folder sorted by publication date. - * @returns {Promise<Project[]>} An array of projects. - */ -export const getSortedProjects = async (): Promise<Project[]> => { -  const filenames = getAllProjectsFilename(); -  const projects = await getProjectsWithMeta(filenames); - -  return [...projects].sort(sortProjectByPublicationDate); -}; diff --git a/src/utils/helpers/sort.ts b/src/utils/helpers/sort.ts deleted file mode 100644 index c1ee35d..0000000 --- a/src/utils/helpers/sort.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ArticlePreview } from '@ts/types/articles'; -import { PostsList } from '@ts/types/blog'; - -type YearCollection = { -  [key: string]: ArticlePreview[]; -}; - -export const sortPostsByYear = (data: PostsList[]) => { -  const yearCollection: YearCollection = {}; - -  data.forEach((page) => { -    page.posts.forEach((post) => { -      const postYear = new Date(post.dates.publication) -        .getFullYear() -        .toString(); -      yearCollection[postYear] = [...(yearCollection[postYear] || []), post]; -    }); -  }); - -  return yearCollection; -}; diff --git a/src/utils/hooks/useGithubApi.tsx b/src/utils/hooks/useGithubApi.tsx deleted file mode 100644 index 4b0b3b2..0000000 --- a/src/utils/hooks/useGithubApi.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { RepoData } from '@ts/types/repos'; -import useSWR, { Fetcher } from 'swr'; - -const fetcher: Fetcher<RepoData, string> = (...args) => -  fetch(...args).then((res) => res.json()); - -/** - * Retrieve data from Github API. - * @param repo The repo name. Format: "User/project-slug". - * @returns {object} The data and two booleans to determine if is loading/error. - */ -const useGithubApi = (repo: string) => { -  const apiUrl = repo ? `https://api.github.com/repos/${repo}` : null; -  const { data, error } = useSWR<RepoData>(apiUrl, fetcher); - -  return { -    data, -    isLoading: !error && !data, -    isError: error, -  }; -}; - -export default useGithubApi; diff --git a/src/utils/hooks/useHeadingsTree.tsx b/src/utils/hooks/useHeadingsTree.tsx deleted file mode 100644 index f2be406..0000000 --- a/src/utils/hooks/useHeadingsTree.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { Heading } from '@ts/types/app'; -import { slugify } from '@utils/helpers/slugify'; -import { useRouter } from 'next/router'; -import { useCallback, useEffect, useMemo, useState } from 'react'; - -const useHeadingsTree = (wrapper: string) => { -  const router = useRouter(); -  const depths = useMemo(() => ['h2', 'h3', 'h4', 'h5', 'h6'], []); -  const [allHeadings, setAllHeadings] = -    useState<NodeListOf<HTMLHeadingElement>>(); - -  useEffect(() => { -    const query = depths -      .map((depth) => `${wrapper} > *:not(aside, #comments) ${depth}`) -      .join(', '); -    const result: NodeListOf<HTMLHeadingElement> = -      document.querySelectorAll(query); -    setAllHeadings(result); -  }, [depths, wrapper, router.asPath]); - -  const [headingsTree, setHeadingsTree] = useState<Heading[]>([]); - -  const getElementDepth = useCallback( -    (el: HTMLHeadingElement) => { -      return depths.findIndex((depth) => depth === el.localName); -    }, -    [depths] -  ); - -  const formatHeadings = useCallback( -    (headings: NodeListOf<HTMLHeadingElement>): Heading[] => { -      const formattedHeadings: Heading[] = []; - -      Array.from(headings).forEach((heading) => { -        const title: string = heading.textContent!; -        const id = slugify(title); -        const depth = getElementDepth(heading); -        const children: Heading[] = []; - -        heading.id = id; - -        formattedHeadings.push({ -          depth, -          id, -          children, -          title, -        }); -      }); - -      return formattedHeadings; -    }, -    [getElementDepth] -  ); - -  const buildSubTree = useCallback( -    (parent: Heading, currentHeading: Heading): void => { -      if (parent.depth === currentHeading.depth - 1) { -        parent.children.push(currentHeading); -      } else { -        const lastItem = parent.children[parent.children.length - 1]; -        buildSubTree(lastItem, currentHeading); -      } -    }, -    [] -  ); - -  const buildTree = useCallback( -    (headings: Heading[]): Heading[] => { -      const tree: Heading[] = []; - -      headings.forEach((heading) => { -        if (heading.depth === 0) { -          tree.push(heading); -        } else { -          const lastItem = tree[tree.length - 1]; -          buildSubTree(lastItem, heading); -        } -      }); - -      return tree; -    }, -    [buildSubTree] -  ); - -  const getHeadingsList = useCallback( -    (headings: NodeListOf<HTMLHeadingElement>): Heading[] => { -      const formattedHeadings = formatHeadings(headings); - -      return buildTree(formattedHeadings); -    }, -    [formatHeadings, buildTree] -  ); - -  useEffect(() => { -    if (allHeadings) { -      const headingsList = getHeadingsList(allHeadings); -      setHeadingsTree(headingsList); -    } -  }, [allHeadings, getHeadingsList]); - -  return headingsTree; -}; - -export default useHeadingsTree; diff --git a/src/utils/providers/ackee.tsx b/src/utils/providers/ackee.tsx index c103668..0cb0166 100644 --- a/src/utils/providers/ackee.tsx +++ b/src/utils/providers/ackee.tsx @@ -1,5 +1,5 @@  import { useRouter } from 'next/router'; -import { createContext, FC, useContext, useState } from 'react'; +import { createContext, FC, ReactNode, useContext, useState } from 'react';  import useAckee from 'use-ackee';  export type AckeeProps = { @@ -10,6 +10,7 @@ export type AckeeProps = {  };  export type AckeeProviderProps = { +  children: ReactNode;    domain: string;    siteId: string;    ignoreLocalhost?: boolean; diff --git a/src/utils/providers/prism-theme.tsx b/src/utils/providers/prism-theme.tsx index 2ed8454..62bcf56 100644 --- a/src/utils/providers/prism-theme.tsx +++ b/src/utils/providers/prism-theme.tsx @@ -2,6 +2,7 @@ import { LocalStorage } from '@services/local-storage';  import {    createContext,    FC, +  ReactNode,    useCallback,    useContext,    useEffect, @@ -22,6 +23,7 @@ export type UsePrismThemeProps = {  export type PrismThemeProviderProps = {    attribute?: string; +  children: ReactNode;    storageKey?: string;    themes?: PrismTheme[];  }; | 
