diff --git a/.env.template b/.env.template
index 4003ba7..016240b 100644
--- a/.env.template
+++ b/.env.template
@@ -2,5 +2,6 @@ SECRET_KEY=
USERNAME=
PASS_HASH=
#PASSWORD=only for testing
-FABRIQUEDOC_ENDPOINT=
+FABRIQUEDOC_ENDPOINT= # Use http://backend:8080 for Docker Compose, or http://127.0.0.1:8080 for local development
+FABRIQUEDOC_PUBLIC_ENDPOINT= # Use http://127.0.0.1:8080 for local development, or your public IP/domain for deployment
ALGORITHM=HS256
diff --git a/backend/.DS_Store b/backend/.DS_Store
new file mode 100644
index 0000000..810ea86
Binary files /dev/null and b/backend/.DS_Store differ
diff --git a/backend/routers/images.py b/backend/routers/images.py
index bbc79f5..dee6e26 100644
--- a/backend/routers/images.py
+++ b/backend/routers/images.py
@@ -10,7 +10,7 @@ from models import User
router = APIRouter()
@router.get("/")
-async def get_images(current_user: Annotated[User, Depends(get_current_active_user)]):
+async def get_images():
# list all files in resources/images
files = [f for f in os.listdir(f"{os.getcwd()}/resources/images") if os.path.isfile(os.path.join(f"{os.getcwd()}/resources/images", f))]
# sort the files
@@ -18,7 +18,7 @@ async def get_images(current_user: Annotated[User, Depends(get_current_active_us
return {"images": files}
@router.get("/{nom_image}")
-async def get_image(nom_image: str, current_user: Annotated[User, Depends(get_current_active_user)]):
+async def get_image(nom_image: str):
return FileResponse(f"{os.getcwd()}/resources/images/{nom_image}")
@router.post("/")
diff --git a/backend/styles/autohebergement/instagram-fullscreen/atelier1-fullscreen-autohebergement-1080-1350-jaune.png b/backend/styles/autohebergement/instagram-fullscreen/atelier1-fullscreen-autohebergement-1080-1350-jaune.png
new file mode 100644
index 0000000..567c819
Binary files /dev/null and b/backend/styles/autohebergement/instagram-fullscreen/atelier1-fullscreen-autohebergement-1080-1350-jaune.png differ
diff --git a/backend/styles/autohebergement/instagram-fullscreen/atelier1-fullscreen-autohebergement-1080-1350-jaune.svg b/backend/styles/autohebergement/instagram-fullscreen/atelier1-fullscreen-autohebergement-1080-1350-jaune.svg
new file mode 100644
index 0000000..cb872b0
--- /dev/null
+++ b/backend/styles/autohebergement/instagram-fullscreen/atelier1-fullscreen-autohebergement-1080-1350-jaune.svg
@@ -0,0 +1,156 @@
+
+
+
+
diff --git a/backend/styles/autohebergement/linkedin/banniere-autohebergement-1920-jaune.png b/backend/styles/autohebergement/linkedin/banniere-autohebergement-1920-jaune.png
new file mode 100644
index 0000000..3fe89ca
Binary files /dev/null and b/backend/styles/autohebergement/linkedin/banniere-autohebergement-1920-jaune.png differ
diff --git a/backend/styles/autohebergement/linkedin/banniere-autohebergement-1920-jaune.svg b/backend/styles/autohebergement/linkedin/banniere-autohebergement-1920-jaune.svg
new file mode 100644
index 0000000..c9a81cc
--- /dev/null
+++ b/backend/styles/autohebergement/linkedin/banniere-autohebergement-1920-jaune.svg
@@ -0,0 +1,136 @@
+
+
+
+
diff --git a/backend/styles/rituels-numeriques/slide169/slides-rituels-numeriques-1920-1080-jaune-top.png b/backend/styles/rituels-numeriques/slide169/slides-rituels-numeriques-1920-1080-jaune-top.png
new file mode 100644
index 0000000..1ec1f79
Binary files /dev/null and b/backend/styles/rituels-numeriques/slide169/slides-rituels-numeriques-1920-1080-jaune-top.png differ
diff --git a/backend/styles/rituels-numeriques/slide169/slides-rituels-numeriques-1920-1080-jaune-top.svg b/backend/styles/rituels-numeriques/slide169/slides-rituels-numeriques-1920-1080-jaune-top.svg
new file mode 100644
index 0000000..5cba18e
--- /dev/null
+++ b/backend/styles/rituels-numeriques/slide169/slides-rituels-numeriques-1920-1080-jaune-top.svg
@@ -0,0 +1,152 @@
+
+
+
+
diff --git a/frontend/app_tab1.py b/frontend/app_tab1.py
index 250cf47..8b49450 100644
--- a/frontend/app_tab1.py
+++ b/frontend/app_tab1.py
@@ -1,6 +1,8 @@
# Importation des bibliothèques nécessaires
import mdformat # Pour formater le texte Markdown
import streamlit as st # Pour créer l'interface utilisateur web
+import requests # Pour effectuer des requêtes HTTP
+import re # Pour les expressions régulières
# Importation du texte de démonstration depuis un autre fichier
from demo_text import demo_text
@@ -9,22 +11,76 @@ from demo_text import demo_text
def app_tab1():
# Fonction de rappel pour le bouton de formatage
def button1_callback():
+ # Récupère le texte Markdown actuel
+ markdown_text = st.session_state['markdown']
+
+ # Vérifie si l'utilisateur veut ajouter des nouvelles pages
+ if st.session_state.get('add_newpage_checkbox', False):
+ header_level = st.session_state['header_level_select']
+
+ # 1. Insérer \newpage avant le niveau d'en-tête spécifié
+ lines = markdown_text.split('\n')
+ new_lines = []
+ for line in lines:
+ if line.startswith('#' * header_level + ' '):
+ new_lines.append('\\newpage')
+ new_lines.append(line)
+ markdown_text = '\n'.join(new_lines)
+
+ # 2. Supprimer les \newpage trop proches, sauf s'il y a une image
+ final_lines = []
+ i = 0
+ while i < len(new_lines):
+ if new_lines[i] == '\\newpage':
+ # Vérifier si la prochaine \newpage est trop proche
+ next_newpage_index = -1
+ for j in range(i + 1, min(i + 11, len(new_lines))): # Vérifier jusqu'à 10 lignes plus loin
+ if new_lines[j] == '\\newpage':
+ next_newpage_index = j
+ break
+
+ if next_newpage_index != -1:
+ # Vérifier s'il y a une image entre les deux \newpage
+ image_found = False
+ for k in range(i + 1, next_newpage_index):
+ if '!' in new_lines[k] and '[' in new_lines[k] and ']' in new_lines[k] and '(' in new_lines[k] and ')' in new_lines[k]:
+ image_found = True
+ break
+
+ if not image_found:
+ # Supprimer la \newpage actuelle si la prochaine est trop proche et pas d'image
+ i += 1 # Passer la \newpage actuelle
+ continue # Ne pas l'ajouter à final_lines
+
+ final_lines.append(new_lines[i])
+ i += 1
+
+ markdown_text = '\n'.join(final_lines)
+
# Formate le texte Markdown stocké dans la session et active la numérotation
- st.session_state['markdown'] = mdformat.text(st.session_state['markdown'],
+ st.session_state['markdown'] = mdformat.text(markdown_text,
options={"number": True})
# Création d'une zone de texte pour entrer le contenu Markdown
- st.session_state['content'] = st.text_area(
+ st.text_area(
# Texte d'instruction pour l'utilisateur
"Entre ton texte ici. Les images sont dans ./images/",
# Texte par défaut (démonstration)
- demo_text,
+ st.session_state.get('markdown', demo_text),
# Hauteur de la zone de texte en pixels
height=450,
# Clé unique pour identifier cet élément dans la session
key='markdown'
)
+ # Menu déroulant pour choisir le niveau d'en-tête
+ st.selectbox(
+ "Insérer une nouvelle page avant les en-têtes de niveau :",
+ options=[1, 2, 3, 4, 5, 6],
+ index=1, # Par défaut, niveau 2
+ key='header_level_select'
+ )
+
# Création d'un bouton pour formater le texte
st.button(
# Texte affiché sur le bouton
diff --git a/frontend/app_tab2.py b/frontend/app_tab2.py
index 365fbba..07c8d44 100644
--- a/frontend/app_tab2.py
+++ b/frontend/app_tab2.py
@@ -1,6 +1,8 @@
# Importation de la bibliothèque Streamlit
# Streamlit est utilisé pour créer des applications web interactives en Python
import streamlit as st
+import re # Pour les expressions régulières
+import requests # Pour effectuer des requêtes HTTP
# Définition de la fonction principale pour l'onglet 2 de l'application
def app_tab2():
@@ -12,4 +14,29 @@ def app_tab2():
# st.markdown() est utilisé pour rendre du texte formaté en Markdown
# st.session_state est un dictionnaire qui conserve les données entre les rechargements de page
# ['content'] fait référence à la clé où le contenu Markdown est stocké
- st.markdown(st.session_state['content'])
\ No newline at end of file
+
+ markdown_content = st.session_state['markdown']
+ fabriquedoc_public_endpoint = st.session_state['fabriquedoc_public_endpoint']
+ bearer_token = st.session_state['bearer_token']
+
+ # Regex pour trouver les images Markdown: 
+ # Capture le chemin complet de l'image (y compris les répertoires si présents)
+ image_pattern = re.compile(r'!\[.*?\]\((.*?)\)')
+
+ def replace_image_path(match):
+ image_path = match.group(1)
+ # Si le chemin est déjà une URL complète, ne rien faire
+ if image_path.startswith('http://') or image_path.startswith('https://'):
+ return match.group(0)
+
+ # Construire l'URL complète de l'image
+ # On suppose que le chemin dans le markdown est juste le nom du fichier ou un chemin relatif simple
+ # et que le backend sert les images via /images/{nom_fichier}
+ image_name = image_path.split('/')[-1] # Prend juste le nom du fichier
+ full_image_url = f"{fabriquedoc_public_endpoint}/images/{image_name}"
+ return f"[0][2:]}]({full_image_url})"
+
+ # Remplacer tous les chemins d'images relatifs par des URLs complètes
+ processed_markdown_content = image_pattern.sub(replace_image_path, markdown_content)
+
+ st.markdown(processed_markdown_content)
\ No newline at end of file
diff --git a/frontend/demo_text.py b/frontend/demo_text.py
index 66c66cf..4f992fd 100644
--- a/frontend/demo_text.py
+++ b/frontend/demo_text.py
@@ -48,8 +48,8 @@ Ceci est centré
## Images
-- 
-- [](url-de-l-image-complete.jpg)
+- 
+- [](https://jevalide.ca)
## Citations
diff --git a/frontend/main.py b/frontend/main.py
index 2324b5c..446a9e7 100644
--- a/frontend/main.py
+++ b/frontend/main.py
@@ -32,7 +32,11 @@ def init_session_state():
if 'fabriquedoc_endpoint' not in st.session_state:
load_dotenv() # Charge les variables d'environnement depuis un fichier .env
# Définit l'URL du backend, avec une valeur par défaut si non spécifiée
- st.session_state['fabriquedoc_endpoint'] = os.environ.get("FABRIQUEDOC_ENDPOINT", "http://127.0.0.1:8080")
+ # Définit l'URL du backend. Utilise 'http://backend:8080' pour Docker Compose,
+ # ou 'http://127.0.0.1:8080' pour un développement local sans Docker Compose.
+ st.session_state['fabriquedoc_endpoint'] = os.environ.get("FABRIQUEDOC_ENDPOINT", "http://backend:8080")
+
+ st.session_state['fabriquedoc_public_endpoint'] = os.environ.get("FABRIQUEDOC_PUBLIC_ENDPOINT", "http://127.0.0.1:8080")
# Initialise d'autres variables de session avec des valeurs par défaut
for key, default_value in [('options', ""), ('bearer_token', ""), ('logged_in', False)]: