[READ-ONLY] Mirror of https://github.com/plttn/mkd.
0

Configure Feed

Select the types of activity you want to include in your feed.

use 11ty/gray-matter

Jack Platten (May 25, 2026, 4:02 PM -0700) 3a9f68a5 e2e7e740

+32 -81
+1 -1
package.json
··· 43 43 "@sindresorhus/slugify": "^3.0.0", 44 44 "cmd-ts": "^0.15.0", 45 45 "filenamify": "^7.0.1", 46 - "gray-matter": "^4.0.3", 46 + "@11ty/gray-matter": "^2.0.2", 47 47 "pwd-fs": "^3.5.4" 48 48 }, 49 49 "repository": {
+12 -20
pnpm-lock.yaml
··· 261 261 262 262 .: 263 263 dependencies: 264 + '@11ty/gray-matter': 265 + specifier: ^2.0.2 266 + version: 2.0.2 264 267 '@clack/prompts': 265 268 specifier: ^1.4.0 266 269 version: 1.4.0 ··· 273 276 filenamify: 274 277 specifier: ^7.0.1 275 278 version: 7.0.1 276 - gray-matter: 277 - specifier: ^4.0.3 278 - version: 4.0.3 279 279 pwd-fs: 280 280 specifier: ^3.5.4 281 281 version: 3.5.4 ··· 303 303 version: 6.0.3 304 304 305 305 packages: 306 + 307 + '@11ty/gray-matter@2.0.2': 308 + resolution: {integrity: sha512-+sbmr+BPzzi0z4lFvruKiGQ3D/d5zBssavhH9SzXmWkf7rStnB4gfeEMgz6k1Ac8bpN5NAFCH5GyR3xHk1BGPA==} 309 + engines: {node: '>=11'} 306 310 307 311 '@babel/generator@8.0.0-rc.5': 308 312 resolution: {integrity: sha512-nFZPWz3FHIS7y6rMIVoa/WBwjdutfIaRJIBQjzn+t3RnecZoRNlGmGcyR2wb0T/IgSd50Kz/6dG8/LvMCRunjg==} ··· 984 988 graceful-fs@4.2.11: 985 989 resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 986 990 987 - gray-matter@4.0.3: 988 - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} 989 - engines: {node: '>=6.0'} 990 - 991 991 hookable@6.1.1: 992 992 resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} 993 993 ··· 1245 1245 resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} 1246 1246 engines: {node: '>=12'} 1247 1247 1248 - strip-bom-string@1.0.0: 1249 - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} 1250 - engines: {node: '>=0.10.0'} 1251 - 1252 1248 strip-bom@3.0.0: 1253 1249 resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 1254 1250 engines: {node: '>=4'} ··· 1336 1332 hasBin: true 1337 1333 1338 1334 snapshots: 1335 + 1336 + '@11ty/gray-matter@2.0.2': 1337 + dependencies: 1338 + js-yaml: 4.1.1 1339 + section-matter: 1.0.0 1339 1340 1340 1341 '@babel/generator@8.0.0-rc.5': 1341 1342 dependencies: ··· 1978 1979 1979 1980 graceful-fs@4.2.11: {} 1980 1981 1981 - gray-matter@4.0.3: 1982 - dependencies: 1983 - js-yaml: 3.14.2 1984 - kind-of: 6.0.3 1985 - section-matter: 1.0.0 1986 - strip-bom-string: 1.0.0 1987 - 1988 1982 hookable@6.1.1: {} 1989 1983 1990 1984 human-id@4.1.3: {} ··· 2190 2184 strip-ansi@7.2.0: 2191 2185 dependencies: 2192 2186 ansi-regex: 6.2.2 2193 - 2194 - strip-bom-string@1.0.0: {} 2195 2187 2196 2188 strip-bom@3.0.0: {} 2197 2189
+2 -5
src/commands/new.ts
··· 3 3 import slugify from "@sindresorhus/slugify"; 4 4 import { command, restPositionals, string } from "cmd-ts"; 5 5 import filenamify from "filenamify"; 6 - import matter from "gray-matter"; 6 + import matter from "@11ty/gray-matter"; 7 7 import type { Config, Deps } from "../lib/deps"; 8 8 9 9 export function makeNewCommand({ config, pfs }: Deps) { ··· 38 38 }); 39 39 } 40 40 41 - async function generateFrontmatter( 42 - title: string, 43 - config: Config, 44 - ): Promise<string> { 41 + async function generateFrontmatter(title: string, config: Config): Promise<string> { 45 42 const description = await makeDescription(title); 46 43 // const now = new Date(); 47 44
+4 -12
src/commands/publish.ts
··· 1 1 import { autocomplete, intro, isCancel, outro } from "@clack/prompts"; 2 2 import { command } from "cmd-ts"; 3 - import matter from "gray-matter"; 3 + import matter from "@11ty/gray-matter"; 4 4 import { 5 5 type Post, 6 6 parseFrontmatter, ··· 17 17 args: {}, 18 18 handler: async () => { 19 19 const posts = await readPosts(pfs, config); 20 - const drafts = posts.filter( 21 - (post) => parseFrontmatter(post)[config.draftKey] === true, 22 - ); 20 + const drafts = posts.filter((post) => parseFrontmatter(post)[config.draftKey] === true); 23 21 const selected = await getPostsToPublish(drafts, config); 24 22 25 23 for (const draft of selected) { ··· 29 27 }); 30 28 } 31 29 32 - async function getPostsToPublish( 33 - drafts: Post[], 34 - config: Config, 35 - ): Promise<Post[]> { 30 + async function getPostsToPublish(drafts: Post[], config: Config): Promise<Post[]> { 36 31 const options = postsToOptions(drafts, config); 37 32 intro("Publishing posts"); 38 33 ··· 48 43 49 44 outro("Posts undrafted..."); 50 45 51 - return selectedValuesToPosts( 52 - Array.isArray(selected) ? selected : [selected], 53 - drafts, 54 - ); 46 + return selectedValuesToPosts(Array.isArray(selected) ? selected : [selected], drafts); 55 47 } 56 48 57 49 async function updateDraftFrontMatter(draft: Post, deps: Deps) {
+3 -11
src/commands/unpublish.ts
··· 1 1 import { autocomplete, intro, isCancel, outro } from "@clack/prompts"; 2 2 import { command } from "cmd-ts"; 3 - import matter from "gray-matter"; 4 - import { 5 - findPostByFile, 6 - type Post, 7 - postsToOptions, 8 - readPosts, 9 - } from "../lib/commands"; 3 + import matter from "@11ty/gray-matter"; 4 + import { findPostByFile, type Post, postsToOptions, readPosts } from "../lib/commands"; 10 5 import type { Config, Deps } from "../lib/deps"; 11 6 12 7 export function makeUnPublishCommand({ config, pfs }: Deps) { ··· 24 19 }); 25 20 } 26 21 27 - async function getPostToUnpub( 28 - posts: Post[], 29 - config: Config, 30 - ): Promise<Post | null> { 22 + async function getPostToUnpub(posts: Post[], config: Config): Promise<Post | null> { 31 23 const options = postsToOptions(posts, config); 32 24 33 25 intro("Unpublish a post");
+3 -11
src/commands/update.ts
··· 1 1 import { autocomplete, intro, isCancel, outro } from "@clack/prompts"; 2 2 import { command } from "cmd-ts"; 3 - import matter from "gray-matter"; 4 - import { 5 - findPostByFile, 6 - type Post, 7 - postsToOptions, 8 - readPosts, 9 - } from "../lib/commands"; 3 + import matter from "@11ty/gray-matter"; 4 + import { findPostByFile, type Post, postsToOptions, readPosts } from "../lib/commands"; 10 5 import type { Config, Deps } from "../lib/deps"; 11 6 12 7 export function makeUpdateCommand({ config, pfs }: Deps) { ··· 24 19 }); 25 20 } 26 21 27 - async function getPostToUpdate( 28 - posts: Post[], 29 - config: Config, 30 - ): Promise<Post | null> { 22 + async function getPostToUpdate(posts: Post[], config: Config): Promise<Post | null> { 31 23 const options = postsToOptions(posts, config); 32 24 33 25 intro("Update a post");
+4 -13
src/lib/commands.ts
··· 1 - import matter from "gray-matter"; 1 + import matter from "@11ty/gray-matter"; 2 2 import type { Config, Deps } from "./deps"; 3 3 4 4 export type Post = { ··· 9 9 export type Frontmatter = Record<string, unknown>; 10 10 11 11 /** Read all files from the blog directory and return them as Post objects */ 12 - export async function readPosts( 13 - pfs: Deps["pfs"], 14 - config: Config, 15 - ): Promise<Post[]> { 12 + export async function readPosts(pfs: Deps["pfs"], config: Config): Promise<Post[]> { 16 13 const files = (await pfs.readdir(config.blogDir)) as string[]; 17 14 const posts: Post[] = []; 18 15 ··· 45 42 } 46 43 47 44 /** Take the raw selected values returned by the prompt and return matching Post[] */ 48 - export function selectedValuesToPosts( 49 - selected: string[] | symbol, 50 - posts: Post[], 51 - ): Post[] { 45 + export function selectedValuesToPosts(selected: string[] | symbol, posts: Post[]): Post[] { 52 46 if (typeof selected === "symbol") return []; 53 47 return posts.filter((p) => selected.includes(p.file)); 54 48 } 55 49 56 - export function findPostByFile( 57 - posts: Post[], 58 - fileName: string, 59 - ): Post | undefined { 50 + export function findPostByFile(posts: Post[], fileName: string): Post | undefined { 60 51 return posts.find((p) => p.file === fileName); 61 52 }
+3 -8
src/lib/tags.ts
··· 1 - import matter from "gray-matter"; 1 + import matter from "@11ty/gray-matter"; 2 2 import type { Deps } from "./deps"; 3 3 4 4 export type GetAllTagsOptions = { ··· 14 14 * This implementation uses the PoweredFileSystem API (pfs) for all path resolution and IO 15 15 * instead of `path.join` so it respects the pfs instance's `pwd` resolution semantics. 16 16 */ 17 - export async function getAllTags( 18 - deps: Deps, 19 - opts: GetAllTagsOptions = {}, 20 - ): Promise<string[]> { 17 + export async function getAllTags(deps: Deps, opts: GetAllTagsOptions = {}): Promise<string[]> { 21 18 const { pfs, config } = deps; 22 19 const { concurrency = 8, lowerCase = true, sort = true } = opts; 23 20 24 21 const files = (await pfs.readdir(config.blogDir)) as string[]; 25 - const mdFiles = files.filter( 26 - (f) => f.endsWith(".md") || f.endsWith(".markdown"), 27 - ); 22 + const mdFiles = files.filter((f) => f.endsWith(".md") || f.endsWith(".markdown")); 28 23 29 24 // split into batches of size `concurrency` 30 25 const batches: string[][] = [];