Skip to content

Instantly share code, notes, and snippets.

@uroybd
Last active April 14, 2026 22:40
Show Gist options
  • Select an option

  • Save uroybd/350b9c7848ca727aaae9e4dcba0498d8 to your computer and use it in GitHub Desktop.

Select an option

Save uroybd/350b9c7848ca727aaae9e4dcba0498d8 to your computer and use it in GitHub Desktop.
KOReader to Obsidian Highlight Import
.callout[data-callout="stylish"] {
--callout-color: var(--color-purple-rgb);
--callout-icon: lucide-brush;
}
--- START: <% Math.random().toString(36).substring(2, 8) %> ---
<% tp.file.cursor() %>
--- END ---
// <%*
// Uncomment the line before this one.
const NOTE_STYLES = {
yellow: {
type: "quote",
title: "Quotable/Concept/General Idea",
},
gray: {
type: "quote",
title: "Quotable/Concept/General Idea",
},
blue: {
type: "important",
title: "Striking/Intense",
},
red: {
type: "danger",
title: "In Discord",
},
green: {
type: "question",
title: "Thought Provoking",
},
olive: {
type: "sceptic",
title: "Sceptic"
},
orange: {
type: "warning",
title: "Unsound"
},
purple: {
type: "stylish",
title: "Stylish"
}
};
const YAMLFrontMatter = /^---\s*[\s\S]*?\s*---/;
async function get_supplements() {
const data = {}
const sFile = await tp.system.suggester(
(item) => item.basename,
tp.app.vault.getMarkdownFiles().filter((item) => item.path.startsWith("Unprocessed")),
false,
"Choose a note supplement, if any."
);
if (sFile == null) {
return data
}
let content = await tp.app.vault.read(sFile);
content = content.replace(YAMLFrontMatter, "").trim()
console.log(content);
content.split('--- END ---').forEach((section) => {
section = section.trim()
if (section.length > 0 && section.startsWith('--- START: ')) {
const [header, body] = section.split("\n", 2);
const id = header.match(/--- START: (\w+) ---/)?.[1];
data[id] = body
}
})
return data
}
function format_koreader_percentages(page, total) {
if (page && total) {
if (typeof page == "string") {
page = parseInt(page)
if (page == NaN) {
return ""
}
}
return `${((page / total) * 100).toFixed(2)}%`;
}
return "";
}
function format_note(text) {
return text.split('\n').map((p) => '> ' + p).join("\n")
}
function format_koreader_json_highlights(content, supplements) {
const data = JSON.parse(content);
console.log(data);
let output = `---\ntitle: "${data.title}"\naliases: ["Notes from ${data.title}"]\nauthor: "${data.author}"\n---\n# ${data.title}\n##### ${data.author}`;
let current_chapter = "";
for (const entry of data.entries) {
if (entry.text) {
if (entry.chapter != current_chapter) {
output += `\n\n## ${entry.chapter}\n`;
current_chapter = entry.chapter;
}
output += `\n### Page: ${entry.page} (${format_koreader_percentages(entry.page, data.number_of_pages)}) @ ${window.moment.unix(entry.time).format("DD MMM YYYY hh:mm:ss A")}\n`;
output += `\n${entry.text}`;
const note_type = NOTE_STYLES[entry.color];
output += `\n\n> [!${note_type.type}] ${note_type.title}`;
if (entry.note) {
let note = entry.note;
if (note.startsWith("#") && note.length == 7) {
const id = note.slice(1);
if (supplements[id]) {
note = supplements[id]
}
}
if (note.length > 50 || note.includes("\n")) {
output += `\n${format_note(note)}`;
} else {
output += `: ${note}`;
}
output += "\n";
}
output += "\n";
}
}
return output;
}
const content = await tp.system.prompt("Paste the JSON content", null, true, true);
let supplements = await get_supplements();
const output = format_koreader_json_highlights(content, supplements);
let file = app.workspace.getActiveFile();
await app.vault.modify(file, output);
// Uncomment the line after this one.
// %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment