Created
September 30, 2024 09:48
-
-
Save apeyroux/a78c306b545e6745d031c1886a44c43f to your computer and use it in GitHub Desktop.
obs2org.py
This file contains hidden or 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
import os | |
import re | |
import argparse | |
def parse_metadata(lines): | |
"""Extraire les métadonnées Markdown du début du fichier.""" | |
metadata = {} | |
if len(lines) == 0: # Vérifier si le fichier est vide | |
return metadata | |
if lines[0].strip() == "---": | |
lines.pop(0) # Enlever le premier '---' | |
while lines: | |
line = lines.pop(0).strip() | |
if line == "---": # Fin des métadonnées | |
break | |
if ": " in line: | |
key, value = line.split(": ", 1) | |
metadata[key.lower()] = value.strip() | |
return metadata | |
def convert_markdown_to_org(input_file, output_file): | |
with open(input_file, 'r', encoding='utf-8') as file: | |
lines = file.readlines() | |
converted_lines = [] | |
inside_code_block = False | |
inside_quote_block = False | |
# Utiliser le nom du fichier comme titre | |
file_name = os.path.splitext(os.path.basename(input_file))[0] | |
converted_lines.append(f"#+TITLE: {file_name}") | |
# Analyse et conversion des métadonnées | |
metadata = parse_metadata(lines) | |
# Conversion des métadonnées standards et personnalisées | |
for key, value in metadata.items(): | |
if key == 'author': | |
converted_lines.append(f"#+AUTHOR: {value}") | |
elif key == 'date': | |
converted_lines.append(f"#+DATE: {value}") | |
else: | |
# Conversion des métadonnées personnalisées en variables Org-mode | |
converted_lines.append(f"#+{key.upper()}: {value}") | |
for line in lines: | |
stripped_line = line.strip() | |
# Gestion des blocs de code | |
if stripped_line.startswith("```"): | |
if inside_code_block: | |
converted_lines.append("#+END_SRC") | |
inside_code_block = False | |
else: | |
lang = stripped_line[3:].strip() # Langage optionnel après ``` | |
converted_lines.append(f"#+BEGIN_SRC {lang}") | |
inside_code_block = True | |
continue | |
# Gestion des citations | |
if stripped_line.startswith(">"): | |
if not inside_quote_block: | |
converted_lines.append("#+BEGIN_QUOTE") | |
inside_quote_block = True | |
converted_lines.append(stripped_line[1:].strip()) | |
continue | |
elif inside_quote_block: | |
converted_lines.append("#+END_QUOTE") | |
inside_quote_block = False | |
# Conversion des titres Markdown (# en *, ## en **, etc.) | |
if stripped_line.startswith("#"): | |
header_level = len(stripped_line) - len(stripped_line.lstrip('#')) | |
header_content = stripped_line.lstrip('#').strip() | |
converted_lines.append(f"{'*' * header_level} {header_content}") | |
continue | |
# Conversion des tâches Markdown | |
# - [x] devient * DONE, et - [ ] devient * TODO | |
if stripped_line.startswith("- [x]"): | |
task_content = stripped_line[5:].strip() | |
converted_lines.append(f"* DONE {task_content}") | |
continue | |
elif stripped_line.startswith("- [ ]"): | |
task_content = stripped_line[5:].strip() | |
converted_lines.append(f"* TODO {task_content}") | |
continue | |
# Fonction de remplacement pour les liens avec ou sans alias | |
def replace_link_with_alias(match): | |
link_text = match.group(1) | |
alias = match.group(2) if match.group(2) else link_text | |
return f"[[file:{link_text}.org][{alias}]]" | |
def replace_link_without_alias(match): | |
link_text = match.group(1) | |
return f"[[file:{link_text}.org][{link_text}]]" | |
# Gérer les liens avec alias | |
line = re.sub(r'\[\[([^\|\]]+)\|([^\]]+)\]\]', replace_link_with_alias, line) # Liens avec alias | |
# Gérer les liens sans alias | |
line = re.sub(r'\[\[([^\]]+)\]\]', replace_link_without_alias, line) # Liens sans alias | |
# Gestion des pièces jointes Obsidian ![[fichier]] | |
# Pas de transformation, simplement mettre dans [[file:]] | |
line = re.sub(r'!\[\[([^\]]+)\]\]', r'[[file:\1]]', line) | |
# Ajout des lignes converties | |
converted_lines.append(line.rstrip()) | |
# Si le fichier se termine par une citation ouverte, la fermer | |
if inside_quote_block: | |
converted_lines.append("#+END_QUOTE") | |
# Écriture du fichier Org converti | |
with open(output_file, 'w', encoding='utf-8') as file: | |
file.write("\n".join(converted_lines)) | |
def process_directory(source_dir, destination_dir): | |
"""Convertir tous les fichiers .md du répertoire source en fichiers .org dans le répertoire destination.""" | |
if not os.path.exists(destination_dir): | |
os.makedirs(destination_dir) | |
for root, _, files in os.walk(source_dir): | |
for file in files: | |
if file.endswith(".md"): | |
input_file = os.path.join(root, file) | |
output_file = os.path.join(destination_dir, file.replace(".md", ".org")) | |
print(f"Conversion de {input_file} vers {output_file}") | |
convert_markdown_to_org(input_file, output_file) | |
def main(): | |
parser = argparse.ArgumentParser(description="Convertir les fichiers Markdown Obsidian en fichiers Org-mode.") | |
parser.add_argument("source", help="Répertoire source contenant les fichiers Obsidian (.md)") | |
parser.add_argument("destination", help="Répertoire destination pour les fichiers Org-mode (.org)") | |
args = parser.parse_args() | |
# Traitement du répertoire source et destination | |
process_directory(args.source, args.destination) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment