Skip to content

Instantly share code, notes, and snippets.

@apeyroux
Created September 30, 2024 09:48
Show Gist options
  • Save apeyroux/a78c306b545e6745d031c1886a44c43f to your computer and use it in GitHub Desktop.
Save apeyroux/a78c306b545e6745d031c1886a44c43f to your computer and use it in GitHub Desktop.
obs2org.py
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