create-new-blog-post
by Kent C. Dodds
Create a new blog post
// Menu: New Post// Description: Create a new blog post// Author: Kent C. Dodds// Shortcut: command option control p// Twitter: @kentcdoddsconst dateFns = await npm('date-fns')const prettier = await npm('prettier')const YAML = await npm('yaml')const slugify = await npm('@sindresorhus/slugify')const {format: formatDate} = await npm('date-fns')const makeMetascraper = await npm('metascraper')const {$filter, toRule} = await npm('@metascraper/helpers')const unsplashTitleToAlt = toRule(str => str.replace(/ photo – .*$/, ''))const unsplashOGTitleToAuthor = toRule(str =>str.replace(/Photo by (.*?) on Unsplash/, '$1'),)const unsplashImageToPhotoId = toRule(str =>new URL(str).pathname.replace('/', ''),)const metascraper = makeMetascraper([{unsplashPhotoId: [unsplashImageToPhotoId($ =>$('meta[property="og:image"]').attr('content'),),],},{author: [unsplashOGTitleToAuthor($ =>$('meta[property="og:title"]').attr('content'),),],},{alt: [unsplashTitleToAlt($ => $('title').text())]},])async function getMetadata(url) {const html = await fetch(url).then(res => res.text())return metascraper({html, url})}const blogDir = await env('KCD_BLOG_CONTENT_DIR',`What's the path to the blog content directory on this machine?`,)const title = await arg({placeholder: `What's the title of this post?`,hint: 'Title',ignoreBlur: true,})const description = await arg({placeholder: `What's the description of this post?`,hint: 'Description',input: 'TODO: add a description',ignoreBlur: true,})const categories = (await arg({placeholder: `What are the categories of this post?`,hint: 'Categories (comma separated)',ignoreBlur: true,})).split(',').map(c => c.trim())const keywords = (await arg({placeholder: `What are the keywords of this post?`,hint: 'Keywords (comma separated)',ignoreBlur: true,})).split(',').map(c => c.trim())const unsplashPhotoInput = await arg({placeholder: `What's the unsplash photo?`,hint: 'Unsplash Photo',ignoreBlur: true,})const unsplashPhotoUrl = unsplashPhotoInput.startsWith('http')? unsplashPhotoInput: `https://unsplash.com/photos/${unsplashPhotoInput}`const metadata = await getMetadata(unsplashPhotoUrl)const frontmatter = YAML.stringify({title,date: dateFns.format(new Date(), 'yyyy-MM-dd'),description,categories,meta: {keywords},bannerCloudinaryId: `unsplash/${metadata.unsplashPhotoId}`,bannerAlt: metadata.alt,bannerCredit: `Photo by [${metadata.author}](${unsplashPhotoUrl})`,})const md = `---${frontmatter}---Be excellent to each other.`// prettify the markdownconst prettyMd = await prettier.format(md, {parser: 'markdown',arrowParens: 'avoid',bracketSpacing: false,embeddedLanguageFormatting: 'auto',htmlWhitespaceSensitivity: 'css',insertPragma: false,jsxBracketSameLine: false,jsxSingleQuote: false,printWidth: 80,proseWrap: 'always',quoteProps: 'as-needed',requirePragma: false,semi: false,singleQuote: true,tabWidth: 2,trailingComma: 'all',useTabs: false,vueIndentScriptAndStyle: false,})const filename = slugify(title, {decamelize: false})const newFile = path.join(blogDir, `${filename}.mdx`)await writeFile(newFile, prettyMd)await edit(newFile)