Created
July 22, 2020 20:31
-
-
Save lelesrc/54fb5a1d7b22668543ace2764173992a 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
// foam-obsidian-importer.js | |
// Import from obsidian to foam | |
// | |
// • Copy all files recursively from SRC_DIR to DST_DIR. | |
// • For each .md file: | |
// - rename to kebab-case.md | |
// - add header "# filename /n/n" | |
// - fix internal links and attachments links | |
// • Copy any other (non .md) file. | |
// | |
// Obsidian attachments will be imported from ATTACHMENTS_DIR | |
// | |
// Usage: | |
// 1. npm install fs-extra slugify prepend-file | |
// 2. edit SRC_DIR, DST_DIR, ATTACHMENTS_DIR | |
// 3. node foam-obsidian-importer.js | |
// SRC_DIR (obsdian); DST_DIR (foam) | |
const SRC_DIR = "/projects/obsidian"; | |
const DST_DIR = "/projects/foam/imported"; | |
// folder where obsidian attachments are stored, relative to SRC_DIR | |
const ATTACHMENTS_DIR = "attachments/" | |
const path = require("path"); | |
const fs = require("fs-extra"); | |
const slugify = require("slugify"); | |
const prependFile = require("prepend-file"); | |
// get files in dir | |
async function getFiles(dir) { | |
const dirents = await fs.promises.readdir(dir, { | |
withFileTypes: true, | |
}); | |
const files = await Promise.all( | |
dirents.map((dirent) => { | |
const res = path.resolve(dir, dirent.name); | |
return dirent.isDirectory() ? getFiles(res) : res; | |
}) | |
); | |
return Array.prototype.concat(...files); | |
} | |
// fix internal links for file and write to dst_path | |
function fix_internal_links(file, dst_path) { | |
// read file | |
var data = fs.readFileSync(file, "utf-8"); | |
// fix internal links | |
var re_internal_links = /\[\[(.*)\]\]/gm | |
data = data.replace(re_internal_links, | |
(match, p1) => { | |
return '[[' + slugify(p1.toLowerCase()) + ']]' | |
} | |
) | |
// fix file links | |
var re_file_links = /\[\[((.*)\.(png|jpg|gif|svg))\]\]/gm | |
data = data.replace(re_file_links, | |
(match, p1, p2, p3) => { | |
let rlt_path = path.relative(SRC_DIR, path.parse(file).dir); | |
let rlt_depth = (rlt_path.match(/\//g) || []).length + 1 | |
return '[' + p2 + '](' + '../'.repeat(rlt_depth) + ATTACHMENTS_DIR + slugify(p1.toLowerCase()) + ')' | |
} | |
) | |
// save file | |
fs.writeFileSync(dst_path, data, "utf-8"); | |
} | |
// do the magic | |
function process(file) { | |
let current_file = path.parse(file); | |
let file_slug = slugify(current_file.name.toLowerCase()); | |
let rlt_path = path.relative(SRC_DIR, current_file.dir); | |
var dst_path = path.resolve(DST_DIR, rlt_path, file_slug + current_file.ext); | |
let dst_file = path.parse( | |
path.resolve(DST_DIR, rlt_path, file_slug + current_file.ext) | |
); | |
// create dst dir if not exists | |
fs.ensureDirSync(dst_file.dir); | |
// if markdown | |
if (current_file.ext == ".md") { | |
// prepend header "# <Filename> \n\n" | |
prependFile( | |
dst_path, | |
"# " + | |
current_file.name.charAt(0).toUpperCase() + | |
current_file.name.slice(1) + | |
"\n\n", | |
(err) => { | |
if (err) { | |
console.log(err); | |
} | |
} | |
); | |
// fix relative links | |
fix_internal_links(file, dst_path) | |
// if any other file extension | |
} else { | |
// copy file to dst dir | |
fs.copySync(file, dst_path); | |
} | |
} | |
function main() { | |
getFiles(SRC_DIR) | |
.then((files) => | |
files.forEach((src_file) => { | |
process(src_file); | |
}) | |
) | |
.catch((e) => console.error(e)); | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey thanks for this, super neat! I'm just starting to think to modify this to work with nb style linking, which requires the relative path to the notebook root. This probably requires:
Sadly, my JS skills are beyond rusty. Ah well - a holiday project.
Thanks again for the cool work!