poststore

3.0.1 • Public • Published

PostStore

PostStoreNEXT.JS 와 함께 블로그를 위시한 마크다운 기반의 문서 페이지를 보다 쉽게 제작하기 위한 도구입니다.

장점

  1. 디렉터리 구조에 기반한 카테고리 기능을 제공하여 굳이 마크다운 파일 내에 카테고리를 명시할 필요가 없습니다. ./Javascript/Snippets 폴더에 위치한 게시물들은 모두 Javascript -> Snippets 라는 중첩된 카테고리를 가지게 됩니다.
  2. 마크다운 문서가 저장된 특정 디렉터리를 분석하여, NEXT.JSgetStaticPathsgetStaticProps를 위한 pathsprops를 자동으로 생성합니다.
  3. 마크다운 문서에 첨부된 이미지들은 굳이 public 디렉터리에 옮기지 않아도, 개발 모드와 프로덕션 빌드 단계에서 자동으로 빌드 결과물에 삽입됩니다. 즉, 상대경로 절대경로를 포함한 그 어떤 경로도 자유롭게 이미지 삽입을 위해 사용할 수 있습니다.
  4. 마크다운에 첨부된 이미지 파일들은 모두 동일한 퀄리티로 최적화 되며, 특정 너비를 초과하는 이미지들은 리사이징 됩니다. (최대 너비 기본값은 600으로 설정되어 있습니다.)
  5. 180자 길이의 Excerpt가 마크다운 해석 과정 중 자동으로 생성되며, 마크다운 문서 편집 만으로 특정 이미지를 Thumbnail로 지정하거나 Youtube 영상을 첨부하는 것이 가능합니다.
  6. 마크다운을 통해 파싱된 html 결과물은 검증된 rehype-sanitize 플러그인의 기본 옵션을 사용하여 XSS 공격을 예방 하였습니다.
  7. 타입 선언을 패키지 내에 자체적으로 내장하고 있어서, 타입스크립트와 함께 사용하기 용이합니다.

단점

  1. 블로그 데이터에 대한 자유로운 커스터마이징이 필요하다면 이 라이브러리 사용을 재고해 보셔야 합니다.

설치

npm i poststore

사용법

PostStore 는 각 페이지의 목적에 맞는 PageHandler를 각각 제공합니다.

모든 PageHandlerNEXT.JSgetStaticPathsgetStaticProps에 사용하기 위한 PathsProps를 제공합니다.

생성되는 Props와 Paths의 형태

PageHandler 분류

별도의 Paths 생성이 필요한 페이지와 불필요한 페이지 두 가지 핸들러로 분류가 됩니다.

별도의 Paths 생성이 필요한 페이지

  • getPageHandler : /page/[pageNum] 에 대한 각각의 PathsProps를 생성하는데 사용됩니다.
  • getPostPageHandler : /posts/[PostSlug] 에 대한 각각의 PathsProps를 생성하는데 사용됩니다.
  • getCategoryPageHandler : /categories/[...categories] 에 대한 각각의 PathsProps를 생성하는데 사용됩니다.
  • getTagPageHandler : /tags/[..tags] 에 대한 각각의 PathsProps를 생성하는데 사용됩니다.

상기의 핸들러들은 모두 동일한 API 를 사용합니다.

import React from 'react';
import { getPostPageHandler, PostPageProp } from 'poststore';

const PostView: React.FC<PostPageProp> = (/* 생략 */) => {
  //... 컴포넌트 코드 생략
};

const { getPathsBySlug, getPropsBySlug } = getPostPageHandler({
  useConfig: true,
});

export async function getStaticPaths() {
  const paths = await getPathsBySlug();

  return {
    paths,
    fallback: false,
  };
}
export async function getStaticProps({ params: { post } }) {
  const props = await getPropsBySlug(post);

  return {
    props,
  };
}

별도의 Paths 생성이 불필요한 페이지

  • getMainPageHandler : 메인 페이지를 위한 핸들러이며, /page/1 과 동일한 Props를 생성합니다.
import { getMainPageHandler, ListPageProp } from 'poststore';
import PostList from 'components/molecules/PostList';

const Post = ({ main: { postList } }: ListPageProp) => {
  return (
    <>
      <PostList postList={postList} href='/blog/[post]' as='/blog/' />
    </>
  );
};

export default Post;

const { getMainProps } = getMainPageHandler({
  useConfig: true,
});

export async function getStaticProps() {
  const props = await getMainProps();

  return {
    props,
  };
}

사용 예시

getPostPageHandler

개개의 마크다운 문서들을 위한 PathsProps를 제공합니다.

import Link from 'next/link';
import { getPostPageHandler, PostPageProp } from 'poststore';

const Post = ({
  param,
  main: {
    postData: { title, html, date, prevPost, excerpt, thumbnail, nextPost },
  },
}: PostPageProp) => {
  return (
    <>
      <h1>
        {title} - {param}
      </h1>
      <h2>{new Date(date).toLocaleString()}</h2>
      {excerpt && <h2>요약 : {excerpt}</h2>}
      {thumbnail && <h2>썸네일 : {thumbnail}</h2>}
      <div className='article' dangerouslySetInnerHTML={{ __html: html }}></div>
      {prevPost && (
        <Link href='/blog/[post]' as={`/blog/${prevPost.slug}`}>
          <a>이전 포스트 : {prevPost.title}</a>
        </Link>
      )}
      {nextPost && (
        <Link href='/blog/[post]' as={`/blog/${nextPost.slug}`}>
          <a>다음 포스트 : {nextPost.title}</a>
        </Link>
      )}
    </>
  );
};

export default Post;

const { getPathsBySlug, getPropsBySlug } = getPostPageHandler({
  useConfig: true,
});

export async function getStaticPaths() {
  const paths = await getPathsBySlug();

  return {
    paths,
    fallback: false,
  };
}
export async function getStaticProps({ params: { post } }) {
  const props = await getPropsBySlug(post);

  return {
    props,
  };
}

테스트

jest 단위 테스트

npm test

jest 테스트

스냅샷 테스트

npm run snapshot update

스냅샷 업데이트

npm run snapshot test

스냅샷 테스트

npm run snapshot all

스냅샷 일괄진행

주요 기록

2020-07-07

  • Watch mode 구현 완료
    • 기존 포스트 수정시 Store 재생성 없이 해당 PostData 객체만 업데이트.
    • 다중 Store 의 경우 별개의 watcher가 지원됨.
  • 마크다운 관련 편의기능 추가
    • 마크다운을 통해 Youtube 영상을 첨부할 수 있는 기능 추가.
      • Youtube 링크를 삽입하면서 url 뒤에 !!를 붙일 경우 링크가 아닌 iframe 요소로 삽입됨.
    • 상대 경로로 이미지 삽입이 가능하도록 수정.
      • 마크다운 파싱 과정에서 해당 마크다운에 사용된 이미지 asset들을 수집.
      • store 생성시 public/assets 폴더로 일괄 전송

2020-07-03

  • 게시물 이름이 중복되는 경우에 대한 핸들링 추가.
    • 중복될 경우 hash를 붙이되, hash는 우선 경로 단위, 동일 경로에도 중복이 발생될 경우 salt를 늘려가며 재귀적 변경.
    • 관련 코드 링크
    • 스냅샷 링크
  • Multiple Store 기능 추가
    • 서로 다른 경로를 갖는 다수의 store 를 생성함으로써, 하나의 프로젝트에서 다수의 서브 페이지를 생성할 수 있게됨.
    • 하나의 프로젝트에서 블로그 관련, 기술 문서 관련 store를 별개로 생성해 관리 가능.
    • perPageOption 추가. 리스트 페이지 별로 페이지 당 게시물 출력 수를 각각 지정 가능.

현재 기준 구현된 Configuration

interface PostStoreConfig {
  storeOption: {
    [key: string]: {
      path: string;
      shouldUpdate: boolean;
      incremental: boolean;
      perPage: {
        category: number;
        tag: number;
        page: number;
      };
      pageParam: {
        post: string;
        category: string;
        tag: string;
        page: string;
      };
    };
  };
}

2020-07-02

2020-07-01

PostStore 를 별도의 모듈로 분리하였습니다.

2020-06-30

  • postStore 구조 정립 및 하기 내용 구현완료
    • store.pathList
      • store.pathList.post -> getStaticPaths에 사용될 게시물 path list
      • store.pathList.category -> getStaticPaths에 사용될 category의 path list
      • store.pathList.tag -> getStaticPaths에 사용될 tag path list
      • store.pathList.page -> getStaticPaths에 사용될 page path list
    • store.propList
      • store.propList.category -> getStaticProps에 사용될 category의 prop list
      • store.propList.tag -> getStaticProps에 사용될 tag prop list
      • store.propList.page -> getStaticProps에 사용될 page prop list
      • store.propList.post -> getStaticProps에 사용될 post prop list
    • store.propList.global -> 각종 전역 데이터
      • store.propList.global.postCount -> 전체 게시물 갯수
      • store.propList.global.categoryCount -> 전체 category 갯수
      • store.propList.global.tagCount -> 전체 tag 갯수

2020-06-29

  • 트리 탐색을 위한 헬퍼 함수들 작성함.
    • visit.tsx
      • visit 함수
      • findNode 함수
      • findeNodeAll 함수
  • postStore 초안 구현완료
    • getCategoriesPath 함수
      • next.js에서 category 관련 path를 생성하기 위한 목적.
    • getPostsByCategories 함수
      • 카테고리 배열로부터 해당 카테고리에 속한 포스트들을 가져오기 위한 목적.

2020-06-25

  • rehype용 prism.js 플러그인 제작함
    • prism.js로 하이라이트된 코드를 정적 생성하기 위한 플러그인임.
  • postParser 초기 구현 완료
  • 간단한 형태의 slugify 모듈 제작함.
  • lib/getNodeTree.tsx 구현 완료

Package Sidebar

Install

npm i poststore

Weekly Downloads

5

Version

3.0.1

License

MIT

Unpacked Size

145 kB

Total Files

69

Last publish

Collaborators

  • bityoungjae