Skip to content

Commit

Permalink
refactor(markdown): add remarkMinutes
Browse files Browse the repository at this point in the history
  • Loading branch information
angrybacon committed May 18, 2024
1 parent f837a21 commit 7bba79c
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 34 deletions.
4 changes: 2 additions & 2 deletions src/pages/articles/[year]/[month]/[day]/[article].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Markdown } from '@/components/Markdown/Markdown';
import { getDecklists } from '@/tools/decklists/getDecklists';
import { type Decklists } from '@/tools/decklists/types';
import { getArticleCards } from '@/tools/markdown/getArticleCards';
import { getArticle, getPartial } from '@/tools/markdown/getMarkdown';
import { getArticle, getMarkdown } from '@/tools/markdown/getMarkdown';
import { getMenu } from '@/tools/markdown/getMenu';
import {
type Article,
Expand Down Expand Up @@ -75,7 +75,7 @@ export const getStaticProps: GetStaticProps<Props, Query> = async ({
props: {
article: await getArticle(year, month, day, article),
decklists: getDecklists(),
footer: await getPartial('article-footer'),
footer: await getMarkdown('partials', 'article-footer.md'),
menu: getMenu(),
},
};
Expand Down
4 changes: 2 additions & 2 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Markdown } from '@/components/Markdown/Markdown';
import { getDecklists } from '@/tools/decklists/getDecklists';
import { type Decklists } from '@/tools/decklists/types';
import { getArticleCards } from '@/tools/markdown/getArticleCards';
import { getPartial } from '@/tools/markdown/getMarkdown';
import { getMarkdown } from '@/tools/markdown/getMarkdown';
import { getMenu } from '@/tools/markdown/getMenu';
import {
type ArticleCard as ArticleCardModel,
Expand Down Expand Up @@ -86,7 +86,7 @@ export const getStaticProps: GetStaticProps<Props> = async () => ({
articles: await getArticleCards(),
decklists: getDecklists(),
menu: getMenu(),
welcome: await getPartial('welcome'),
welcome: await getMarkdown('partials', 'welcome.md'),
},
});

Expand Down
4 changes: 2 additions & 2 deletions src/pages/license.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Layout } from '@/components/Layout/Layout';
import { Markdown } from '@/components/Markdown/Markdown';
import { getDecklists } from '@/tools/decklists/getDecklists';
import { type Decklists } from '@/tools/decklists/types';
import { getPartial } from '@/tools/markdown/getMarkdown';
import { getMarkdown } from '@/tools/markdown/getMarkdown';
import { getMenu } from '@/tools/markdown/getMenu';
import { type MenuEntry, type Partial } from '@/tools/markdown/types';

Expand All @@ -31,7 +31,7 @@ const LicensePage: NextPage<Props> = ({ decklists, license, menu }) => (
export const getStaticProps: GetStaticProps<Props> = async () => ({
props: {
decklists: getDecklists(),
license: await getPartial('license'),
license: await getMarkdown('partials', 'license.md'),
menu: getMenu(),
},
});
Expand Down
4 changes: 2 additions & 2 deletions src/pages/sandbox/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Layout } from '@/components/Layout/Layout';
import { Markdown } from '@/components/Markdown/Markdown';
import { getDecklists } from '@/tools/decklists/getDecklists';
import { type Decklists } from '@/tools/decklists/types';
import { getPartial } from '@/tools/markdown/getMarkdown';
import { getMarkdown } from '@/tools/markdown/getMarkdown';
import { getMenu } from '@/tools/markdown/getMenu';
import { type MenuEntry, type Partial } from '@/tools/markdown/types';

Expand All @@ -28,7 +28,7 @@ const Page: NextPage<Props> = ({ decklists, markdown, menu }) => (
export const getStaticProps: GetStaticProps<Props> = async () => ({
props: {
decklists: getDecklists(),
markdown: await getPartial('sandbox'),
markdown: await getMarkdown('partials', 'sandbox.md'),
menu: getMenu(),
},
});
Expand Down
12 changes: 5 additions & 7 deletions src/tools/markdown/constants/Files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import { join } from 'node:path';
/** File extension to consider for Markdown content. */
export const MARKDOWN_EXTENSION = '.md';

/** Base URL for Markdown content. */
const BASE_MARKDOWN_URL = join(process.cwd(), 'markdown');
/** Base file URL for Markdown content. */
export const BASE_URL = join(process.cwd(), 'markdown');

/** Base URLs for Markdown content. */
/** Base file URLs for Markdown content categories. */
export const BASE_URLS = {
/** Base URL for articles. */
ARTICLE: join(BASE_MARKDOWN_URL, 'articles'),
ARTICLES: join(BASE_URL, 'articles'),
/** Base URL for chapters. */
CHAPTER: join(BASE_MARKDOWN_URL, 'chapters'),
/** Base URL for partials. */
PARTIAL: join(BASE_MARKDOWN_URL, 'partials'),
CHAPTERS: join(BASE_URL, 'chapters'),
} as const;
4 changes: 2 additions & 2 deletions src/tools/markdown/getArticleCards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type ArticleCardPending = Omit<ArticleCard, 'banner'> &
/** Read file system and return a list of all articles. */
export const getArticleCards = async (): Promise<ArticleCard[]> => {
const extension = MARKDOWN_EXTENSION;
const files = walk(BASE_URLS.ARTICLE, { extension });
const files = walk(BASE_URLS.ARTICLES, { extension });
/** Warmup array for banner promises. */
const banners: Promise<Banner>[] = [];
// NOTE Reduce rightwards to sort descending
Expand All @@ -33,7 +33,7 @@ export const getArticleCards = async (): Promise<ArticleCard[]> => {
const path = join(...crumbs) + extension;
let matter: ArticleMatter;
try {
matter = readArticleMatter(read(BASE_URLS.ARTICLE, path).matter);
matter = readArticleMatter(read(BASE_URLS.ARTICLES, path).matter);
} catch (error) {
const message = error instanceof Error ? error.message : `${error}`;
throw new Error(`${message} in "${path}"`);
Expand Down
4 changes: 2 additions & 2 deletions src/tools/markdown/getChapterCards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import { assertCategory, assertDepth } from '@/tools/markdown/utilities';
/** Read file system and return a list of all chapters. */
export const getChapterCards = (): ChapterCard[] => {
const extension = MARKDOWN_EXTENSION;
const files = walk(BASE_URLS.CHAPTER, { extension });
const files = walk(BASE_URLS.CHAPTERS, { extension });
const cards = files.reduce<ChapterCard[]>((accumulator, crumbs) => {
assertDepth(crumbs, 2);
const [category, slug] = crumbs;
assertCategory(category);
const path = join(...crumbs) + extension;
let matter: ChapterMatter;
try {
matter = readChapterMatter(read(BASE_URLS.CHAPTER, path).matter);
matter = readChapterMatter(read(BASE_URLS.CHAPTERS, path).matter);
} catch (error) {
const message = error instanceof Error ? error.message : `${error}`;
throw new Error(`${message} in "${path}"`);
Expand Down
27 changes: 15 additions & 12 deletions src/tools/markdown/getMarkdown.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import readingTime from 'reading-time';
import remarkDirective from 'remark-directive';
import remarkFrontmatter from 'remark-frontmatter';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
import { unified } from 'unified';

import { BASE_URLS } from '@/tools/markdown/constants/Files';
import { BASE_URL } from '@/tools/markdown/constants/Files';
import { getBanner } from '@/tools/markdown/getBanner';
import {
readArticleMatter,
Expand All @@ -19,24 +18,33 @@ import {
type Partial,
} from '@/tools/markdown/types';
import { remarkMana } from '@/tools/remark/remarkMana.server';
import { remarkMinutes } from '@/tools/remark/remarkMinutes.server';
import { remarkScries } from '@/tools/remark/remarkScries.server';
import { type Scries } from '@/tools/scryfall/types';
import { remarkMatter } from '../remark/remarkFrontmatter.server';

const getMarkdown = async (path: string): Promise<Partial> => {
const buffer = readFileSync(path + '.md');
/**
* Read the Markdown content found at the provided path crumbs.
* This does not handle the file extension and it has to be provided in the last
* crumb. The path is relative to the root of the project.
*/
export const getMarkdown = async (...crumbs: string[]): Promise<Partial> => {
const path = join(...crumbs);
const buffer = readFileSync(join(BASE_URL, path));
try {
const { data, value } = await unified()
.use(remarkDirective)
.use(remarkFrontmatter)
.use(remarkMana)
.use(remarkMatter)
.use(remarkMinutes)
.use(remarkParse)
.use(remarkScries)
.use(remarkStringify)
.process(buffer);
return {
matter: data.matter as Record<string, unknown>,
minutes: data.minutes as number,
scries: data.scries as Scries,
text: String(value),
};
Expand All @@ -50,13 +58,12 @@ const getMarkdown = async (path: string): Promise<Partial> => {
export const getArticle = async (
...crumbs: [year: string, month: string, day: string, article: string]
): Promise<Article> => {
const path = join(BASE_URLS.ARTICLE, ...crumbs);
const path = join('articles', ...crumbs) + '.md';
const markdown = await getMarkdown(path);
try {
const matter = readArticleMatter(markdown.matter);
const banner = await getBanner(matter.banner);
const minutes = readingTime(markdown.text).minutes;
return { ...markdown, banner, matter, minutes };
return { ...markdown, banner, matter };
} catch (error) {
const message = error instanceof Error ? error.message : `${error}`;
throw new Error(`${message} in "${path}"`);
Expand All @@ -67,7 +74,7 @@ export const getArticle = async (
export const getChapter = async (
...crumbs: [category: string, chapter: string]
): Promise<Chapter> => {
const path = join(BASE_URLS.CHAPTER, ...crumbs);
const path = join('chapters', ...crumbs) + '.md';
const markdown = await getMarkdown(path);
try {
const matter = readChapterMatter(markdown.matter);
Expand All @@ -78,7 +85,3 @@ export const getChapter = async (
throw new Error(`${message} in "${path}"`);
}
};

/** Convenience helper to read a partial. See `getMarkdown`. */
export const getPartial = (path: string): Promise<Partial> =>
getMarkdown(join(BASE_URLS.PARTIAL, path));
2 changes: 1 addition & 1 deletion src/tools/markdown/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ export type ChapterCard = Card<ChapterMatter> & {

export type Partial = {
matter: Record<string, unknown>;
minutes: number;
scries: Scries;
text: string;
};

export type Article = Omit<Partial, 'matter'> & {
banner: Banner;
matter: ArticleMatter;
minutes: number;
};

export type Chapter = Omit<Partial, 'matter'> & {
Expand Down
3 changes: 1 addition & 2 deletions src/tools/remark/remarkMana.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { type Plugin } from 'unified';

import { MANA_RE } from '@/tools/mana/constants';

export const remarkMana: Plugin = () => async (tree) => {
export const remarkMana: Plugin = () => async (tree) =>
findAndReplace(tree as Nodes, [
MANA_RE,
(_match, value) =>
Expand All @@ -16,4 +16,3 @@ export const remarkMana: Plugin = () => async (tree) => {
type: 'textDirective',
}) satisfies TextDirective,
]);
};
14 changes: 14 additions & 0 deletions src/tools/remark/remarkMinutes.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import readingTime from 'reading-time';
import { type Plugin } from 'unified';
import { type Literal } from 'unist';
import { visit } from 'unist-util-visit';

export const remarkMinutes: Plugin = () => async (tree, file) => {
let text = '';
visit(tree, 'text', (node) => {
text += (node as Literal).value;
});
const { minutes } = readingTime(text);
console.log(minutes);
file.data.minutes = Math.ceil(minutes);
};

0 comments on commit 7bba79c

Please sign in to comment.