Created
September 3, 2021 13:23
-
-
Save kentcdodds/f9a5b9f24f8866e75138ff1629bab071 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Menu: New Post | |
// Description: Create a new blog post | |
// Author: Kent C. Dodds | |
// Shortcut: command option control p | |
// Twitter: @kentcdodds | |
const 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 markdown | |
const 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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment