adamflott.com

Convert FireFox Bookmarks to Markdown

Description:
Authored: 2021-10-05;
Permalink: https://adamflott.com/programming/rust/firefox-bookmarks/
categories : programming;
tags : rust;


Table of Contents

1. Export Bookmarks

2. Trim JSON Fat

jq '.children[1]' < ~/bookmarks-2021-10-04.json > ~/bookmarks2.json

3. Convert into Markdown

From https://raw.githubusercontent.com/adamflott/firefox-bookmarks-to-markdown/master/src/main.rs

use serde_derive::*;
use serde_json::Result;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Root {
    pub guid: String,
    pub title: String,
    pub index: i64,
    pub date_added: i64,
    pub last_modified: i64,
    pub id: i64,
    pub type_code: i64,
    #[serde(rename = "type")]
    pub type_field: String,
    pub root: Option<String>,
    pub children: Option<Vec<Root>>,
    pub uri: Option<String>,
}

fn main() -> Result<()> {
    let mut args = std::env::args();

    let filename = args.nth(1).unwrap();
    let data = std::fs::read_to_string(&filename).unwrap();

    let r: Root = serde_json::from_str(&data)?;

    let idx = 1;
    if let Some(_) = r.children {
        print_header();
        print_children(idx, &r);
    } else {
        eprintln!("JSON file {} has no children!", filename);
    }

    Ok(())
}

fn print_header() {
    let now_str = chrono::offset::Utc::now()
        .format("%Y-%m-%d")
        .to_string();

    println!(r##"---
title: Bookmarks
description: My Bookmarks
date: {}
tags:
- bookmarks
- links
categories:
- Bookmarks
---
An auto-generated list of my FireFox bookmarks.
"##, now_str);

}

fn print_children(idx: usize, r: &Root) {
    if let Some(c) = &r.children {
        for x in c {
            if x.type_code == 2 {
                let prefix = "#".repeat(idx);
                println!("{} {}", prefix, x.title);
                print_children(idx+1, &x)
            }
            else if x.type_code == 1 {
                let prefix = "*".repeat(1);
                if let Some(u) = &x.uri {
                    println!("{} [{}]({})", prefix, x.title, u);
                }
            }
        }
    }
}