Convert Supernote .note files to markdown
Project description
Supernote to Markdown converter (sn2md)
A CLI tool to convert Supernote .note, PDFs, and images to markdown using any LLM supported by the LLM library.
Sample output: 20240712_151149.md
The default LLM prompt with gpt-4o-mini supports:
- Supports markdown in .note files (#tags,
## Headers,[[Links]], etc) - Supports basic formatting (lists, tables, etc)
- Converts of images of diagrams to mermaid.
- Handles math equations using
$and$$latex math blocks.
Installation
pip install sn2md
Setup your OPENAI_API_KEY environment variable.
Usage
To import a single Supernote .note file, use the file command:
# import one .note file (or PDF, image):
sn2md file <path_to_note_file>
# import a directory of .note files (or PDFs, images):
sn2md directory <path_to_directory>
Notes:
- A cache file is also generated, so repeated runs don't recreate the same data.
You can force a refresh by running with the
--forceflag.
Configuration
A configuration file can be used to override the program defaults. The
default location is platform specific (eg, ~/Library/Application Support/sn2md.toml on OSX, ~/.config/sn2md.toml on Linux, etc).
Values that you can configure:
template: The output template to generate markdown.prompt: The prompt sent to the LLM. Requires a{context}placeholder to help the AI understand the context of the previous page.title_prompt: The prompt sent to the OpenAI API to decode any titles (H1-H4 supernote highlights).model: The model to use (default:gpt-4o-mini). Supports OpenAI out of the box, but additional providers can be configured (see below).api_key: Your Service provider's API key (defaults to the environmental variable required by the model you've provided. For instance, for OpenAI models$OPENAI_API_KEY).
Example instructing the AI to convert text to pirate speak:
model = "gemini-1.5-pro-latest"
prompt = """###
Context (what the last couple lines of the previous page were converted to markdown):
{context}
###
Convert the following image to markdown:
- Don't convert diagrams or images. Just output "<IMAGE>" on a newline.
- Paraphrase all the text in pirate speak.
"""
template = """
# Pirate Speak
{{markdown}}
"""
Prompt
The default prompt sent to the LLM is:
###
Context (the last few lines of markdown from the previous page):
{context}
###
Convert the image to markdown:
- If there is a simple diagram that the mermaid syntax can achieve, create a mermaid codeblock of it.
- When it is unclear what an image is, don't output anything for it.
- Use $$, $ latex math blocks for math equations.
- Support Obsidian syntaxes and dataview "field:: value" syntax.
- Do not wrap text in codeblocks.
This can be overridden in the configuration file. For example, to have underlined text converted to an Obsidian internal link you could append - Convert any underlined words to internal wiki links (double brackets)..
Output Template
You can provide your own jinja template, if you prefer to customize the markdown output. The default template is:
---
created: {{year_month_day}}
tags: supernote
---
{{markdown}}
# Images
{% for image in images %}
- 
{%- endfor %}
{% if keywords %}
# Keywords
{% for keyword in keywords %}
- Page {{ keyword.page_number }}: {{ keyword.content }}
{%- endfor %}
{%- endif %}
{% if links %}
# Links
{% for link in links %}
- Page {{ link.page_number }}: {{ link.type }} {{ link.inout }} [[{{ link.name | replace('.note', '')}}]]
{%- endfor %}
{%- endif %}
{% if titles %}
# Titles
{% for title in titles %}
- Page {{ title.page_number }}: Level {{ title.level }} "{{ title.content }}"
{%- endfor %}
{%- endif %}
Variables supplied to the template:
year_month_day: The date the note was created (eg, 2024-05-12).markdown: The markdown content of the note.images: an array of image objects with the following properties:name: The name of the image file.rel_path: The relative path to the image file to where the file was run from.abs_path: The absolute path to the image file.
links: an array of links in or out of a .note file with the following properties:page_number: The page number the link is on.type: The link type (page, file, web)name: The basename of the link (url, page, web)device_path: The full path of the linkinout: The direction of the link (in, out)
keywords: an array of keywords in a .note file with the following properties:page_number: The page number the keyword is on.content: The content of the keyword.
titles: an array of titles in a .note file with the following properties:page_number: The page number the title is on.level: The level of the title (1-4).content: The content of the title. If the area of the title appears to be text, the text, otherwise a description of it.
Note: links, keywords, and titles are only available for .note files (and is an empty list otherwise).
Other LLM Models
This tool uses llm, which supports many services. You can use any of these models by specifying the model, as long is it a multi-modal model that supports visual inputs (such as gpt-4o-mini, llama3.2-vision, etc).
Here are a couple examples of using this tool with other models.
Gemini
To use Gemini:
- Get a Gemini API key. Set this as the
api_keyin the configuration file, or as theLLM_GEMINI_KEYenvironmental variable. - Install the gemini llm API.
- Specify the model in the configuration file as
model, or use the--modelCLI flag.
export LLM_GEMINI_KEY=yourkey
llm install llm-gemini
sn2md -m gemini-1.5-pro-latest file <path_to_note_file>
Notes: The default prompt appears to work well with Gemini. Your mileage may vary!
Ollama
You can run your own local LLM modals using Ollama (or other supported local methods), using an LLM that supports visual inputs:
- Install Ollama, and install a model that supports visual inputs.
- Install the ollama llm plugin.
- Specify the model in the configuration file as
model, or use the--modelCLI flag.
# Run ollama in one terminal:
ollama serve
# In another terminal, install a model, and plugin support:
ollama pull llama3.2-vision:11b
llm install llm-ollama
sn2md -m llama3.2-vision:11b file <path_to_note_file>
Notes: The default prompt does NOT work well with llama3.2-vision:11b. You will need to provide a custom prompt in the configuration file. Basic testing showed this configuration provided basic OCR capabilities (probably not mermaid, ore other markdown features!):
model = "llama3.2-vision:11b"
prompt = """###
Context (the last few lines of markdown from the previous page):
{context}
###
You are an OCR program. Extract text from the image and format as paragraphs of plain markdown text.
"""
Please let me know if you find better prompts!
Contributing
Contributions are welcome. Please open an issue or submit a pull request.
Development
```sh
git clone https://github.com/yourusername/supernote-importer.git
- [supernote-tool library](https://github.com/jya-dev/supernote-tool) for .note file parsing.
cd supernote-importer
poetry install
pytest
License
This project is licensed under the AGPL License. See the LICENSE file for details.
Acknowledgements
- Supernote for their amazing note-taking devices.
- supernote-tool library for .note file parsing.
- llm for LLM access.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sn2md-2.1.0.tar.gz.
File metadata
- Download URL: sn2md-2.1.0.tar.gz
- Upload date:
- Size: 23.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.5 CPython/3.13.1 Darwin/23.4.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc4b42d3eb378b7290b58e1a422588e0259733a08e8a54230d69114dfe299355
|
|
| MD5 |
9a3fbd12c87b24bcc6ac59505dae67d0
|
|
| BLAKE2b-256 |
5e4797b5808f6b23eb315beddb36dfc4ef71501e2dec2f69438a5a74ec04def7
|
File details
Details for the file sn2md-2.1.0-py3-none-any.whl.
File metadata
- Download URL: sn2md-2.1.0-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.5 CPython/3.13.1 Darwin/23.4.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05390d1746a6b087af6b49f1ba7a2932a7f15c56b6ab3b07dfe6b9fde04c24f4
|
|
| MD5 |
aa70c7839cf2ce2da211ea1c8051e0bf
|
|
| BLAKE2b-256 |
1219e9356e58a7d8f63d71ebf8f9b9eee51c912724cb5f30037f3955af422680
|