Skip to content

Instantly share code, notes, and snippets.

@AngelMunoz
Created August 15, 2021 03:45
Show Gist options
  • Save AngelMunoz/cea5be5853b2cf7410738edd96ffba63 to your computer and use it in GitHub Desktop.
Save AngelMunoz/cea5be5853b2cf7410738edd96ffba63 to your computer and use it in GitHub Desktop.
Convert Dev.to articles into markdown files with site-fi front matter
#r "nuget: FSharp.SystemTextJson, 0.17.4"
#r "nuget: Ply, 0.3.1"
open System.IO
open System.Text.Json
open System.Text.Json.Serialization
open System
type DevToPost =
{ created_at: DateTime
crossposted_at: DateTime option
edited_at: DateTime option
last_comment_at: DateTime option
published_at: DateTime
canonical_url: string option
feed_source_url: string option
video_closed_caption_track_url: string option
video_source_url: string option
video_thumbnail_url: string option
body_markdown: string
cached_tag_list: string option
cached_user_name: string option
cached_user_username: string option
comments_count: int
description: string option
main_image: string option
main_image_background_hex_color: string
path: string
public_reactions_count: int
processed_html: string
published: bool
published_from_feed: bool
show_comments: bool
slug: string
social_image: string option
title: string
video: string option
video_code: string option }
type PostConfig =
{ title: string
subtitle: string
``abstract``: string option
date: string
categories: string
language: string
markdown: string }
let template (post: PostConfig) : string =
sprintf
"""
---
title: %s
subtitle: %s
categories: %s
abstract: %s
date: %s
language: %s
---
%s
"""
(post.title.Trim())
(post.subtitle.Trim())
(post.categories.Trim())
((post.``abstract`` |> Option.defaultValue "").Trim())
(post.date.Trim())
(post.language.Trim())
(post.markdown.Trim())
let file = File.ReadAllText("./articles.json")
let jsonOpts =
let opts = JsonSerializerOptions()
opts.AllowTrailingCommas <- true
opts.ReadCommentHandling <- JsonCommentHandling.Skip
opts.DefaultIgnoreCondition <- JsonIgnoreCondition.WhenWritingNull
opts.Converters.Add(JsonFSharpConverter())
opts
let getTags (tags: string option) =
match tags with
| Some tags -> tags.Replace(" ", "")
| None -> "uncategorized"
let getDate (date: DateTime) = $"{date.Year}-%02i{date.Month}-%02i{date.Day}"
let posts =
JsonSerializer.Deserialize<DevToPost array>(file, jsonOpts)
posts
|> Array.Parallel.iter
(fun post ->
let value =
{ title = post.title
subtitle = "~"
``abstract`` = post.description
categories = getTags post.cached_tag_list
date = getDate post.published_at
language = "en"
markdown = post.body_markdown }
let fileContent = template value
let path =
Path.Combine("./posts", $"{getDate post.published_at}-{post.slug}.md")
File.WriteAllText(path, fileContent))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment