Spaces:
Sleeping
Sleeping
import streamlit as st | |
from streamlit.components.v1 import html | |
from pathlib import Path | |
import json | |
import time | |
from datetime import datetime | |
import re | |
import pandas as pd | |
import yaml | |
from io import StringIO, BytesIO | |
import openpyxl | |
import csv | |
import base64 | |
import glob | |
import os | |
import zipfile | |
FILE_TYPES = { | |
"md": "π Markdown", | |
"txt": "π Text", | |
"json": "π§ JSON", | |
"csv": "π CSV", | |
"xlsx": "π Excel", | |
"yaml": "βοΈ YAML", | |
"xml": "π XML", | |
"mp4": "π¬ MP4", | |
"webm": "π¬ WEBM", | |
"ogg": "π¬ OGG" | |
} | |
for key in [ | |
'file_data', 'file_types', 'md_outline', 'rendered_content', 'file_history', | |
'md_versions', 'md_files_history', 'combined_markdown', 'current_file', | |
'file_content' | |
]: | |
if key not in st.session_state: | |
if key in ['file_data', 'file_types', 'md_outline', 'rendered_content', 'md_versions']: | |
st.session_state[key] = {} | |
elif key in ['file_history', 'md_files_history']: | |
st.session_state[key] = [] | |
else: | |
st.session_state[key] = "" | |
def create_zip_of_files(files): | |
zip_buffer = BytesIO() | |
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file: | |
for file in files: | |
with open(file, 'r', encoding='utf-8') as f: | |
zip_file.writestr(file, f.read()) | |
return zip_buffer.getvalue() | |
def get_download_link(file_path): | |
if isinstance(file_path, bytes): | |
b64 = base64.b64encode(file_path).decode() | |
href = f'data:application/zip;base64,{b64}' | |
filename = 'all_files.zip' | |
else: | |
with open(file_path, 'r', encoding='utf-8') as f: | |
content = f.read() | |
b64 = base64.b64encode(content.encode()).decode() | |
href = f'data:text/markdown;base64,{b64}' | |
filename = os.path.basename(file_path) | |
return f'<a href="{href}" download="{filename}">{filename}</a>' | |
def load_file(filepath): | |
with open(filepath, 'r', encoding='utf-8') as f: | |
return f.read() | |
def encode_content(content): | |
return base64.b64encode(content.encode()).decode() | |
def decode_content(encoded_content): | |
return base64.b64decode(encoded_content.encode()).decode() | |
def parse_markdown_outline(content): | |
return [ | |
{ | |
'level': len(line.split()[0]), | |
'title': line.strip('#').strip(), | |
'indent': ' ' * (len(line.split()[0]) - 1) | |
} | |
for line in content.split('\n') if line.strip().startswith('#') | |
] | |
def combine_markdown_files(): | |
all_files = glob.glob("*.md") | |
combined = [] | |
for filepath in sorted(all_files): | |
with open(filepath, 'r', encoding='utf-8') as f: | |
content = f.read() | |
combined.append(f"# {filepath}\n\n{content}\n\n---\n\n") | |
return "".join(combined) | |
def combine_video_files(): | |
video_files = [f for f in glob.glob("*") if f.split(".")[-1].lower() in ["mp4", "webm", "ogg"]] | |
video_html = [] | |
for vf in video_files: | |
with open(vf, "rb") as f: | |
b64_video = base64.b64encode(f.read()).decode("utf-8") | |
ext = vf.split(".")[-1].lower() | |
mime_type = "video/mp4" if ext == "mp4" else f"video/{ext}" | |
video_html.append(f""" | |
<video width="640" height="480" controls autoplay muted loop> | |
<source src="data:{mime_type};base64,{b64_video}" type="{mime_type}"> | |
</video> | |
<br><hr> | |
""") | |
return "".join(video_html) | |
def display_file_manager(): | |
st.sidebar.title("π File Management") | |
all_files = glob.glob("*.md") | |
all_files.sort(reverse=True) | |
col1, col2 = st.sidebar.columns(2) | |
with col1: | |
if st.button("π Delete All", key="delete_all_files_button"): | |
for file in all_files: | |
if file != "README.md": | |
os.remove(file) | |
st.rerun() | |
with col2: | |
if st.button("β¬οΈ Download All", key="download_all_files_button"): | |
zip_file = create_zip_of_files(all_files) | |
st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True) | |
st.sidebar.markdown("---") | |
for idx, file in enumerate(all_files): | |
file_stat = os.stat(file) | |
unique_id = f"{idx}_{file_stat.st_size}_{file_stat.st_mtime}" | |
col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1]) | |
with col1: | |
if st.button("π", key=f"view_{unique_id}"): | |
st.session_state.current_file = file | |
st.session_state.file_content = load_file(file) | |
with col2: | |
st.markdown(get_download_link(file), unsafe_allow_html=True) | |
with col3: | |
if st.button("π", key=f"edit_{unique_id}"): | |
st.session_state.current_file = file | |
st.session_state.file_content = load_file(file) | |
with col4: | |
if st.button("π", key=f"delete_{unique_id}"): | |
os.remove(file) | |
st.rerun() | |
def create_markdown_tabs(content, filename): | |
tab1, tab2 = st.tabs(["π Editor", "π Preview"]) | |
with tab1: | |
edited_content = st.text_area("Edit your markdown", content, height=300, key=f"edit_{filename}") | |
if edited_content != content: | |
st.session_state.file_data[filename] = edited_content | |
content = edited_content | |
if st.button("πΎ Save"): | |
with open(filename, 'w', encoding='utf-8') as f: | |
f.write(edited_content) | |
st.success("β¨ Saved successfully!") | |
with tab2: | |
st.markdown(content, unsafe_allow_html=True) | |
return content | |
def read_file_content(uploaded_file): | |
file_type = uploaded_file.name.split('.')[-1].lower() | |
try: | |
if file_type == 'md': | |
content = uploaded_file.getvalue().decode() | |
with open(uploaded_file.name, 'w', encoding='utf-8') as f: | |
f.write(content) | |
return content, "md" | |
elif file_type in ['csv', 'xlsx']: | |
if file_type == 'csv': | |
df = pd.read_csv(uploaded_file) | |
else: | |
df = pd.read_excel(uploaded_file) | |
return df.to_string(), file_type | |
elif file_type == 'json': | |
return json.dumps(json.load(uploaded_file), indent=2), "json" | |
elif file_type == 'yaml': | |
return yaml.dump(yaml.safe_load(uploaded_file)), "yaml" | |
elif file_type in ['mp4', 'webm', 'ogg']: | |
with open(uploaded_file.name, 'wb') as f: | |
f.write(uploaded_file.getvalue()) | |
return None, file_type | |
else: | |
content = uploaded_file.getvalue().decode() | |
return content, "txt" | |
except Exception as e: | |
st.error(f"π¨ Error reading {uploaded_file.name}: {str(e)}") | |
return None, None | |
def main(): | |
st.set_page_config(page_title="Markdown Handler", layout="wide") | |
display_file_manager() | |
st.title("πβ¨ Super Smart File Handler with Markdown Magic! β¨π") | |
upload_tab, book_tab = st.tabs(["π€ File Upload", "π Book View"]) | |
with upload_tab: | |
col1, col2 = st.columns(2) | |
with col1: | |
single_uploaded_file = st.file_uploader( | |
"π€ Upload single file", | |
type=list(FILE_TYPES.keys()), | |
help="Supports: " + ", ".join([f"{v} (.{k})" for k, v in FILE_TYPES.items()]), | |
key="single_uploader" | |
) | |
with col2: | |
multiple_uploaded_files = st.file_uploader( | |
"π Upload multiple files", | |
type=list(FILE_TYPES.keys()), | |
accept_multiple_files=True, | |
help="Upload multiple files to view as a book or video playlist", | |
key="multiple_uploader" | |
) | |
if single_uploaded_file: | |
content, file_type = read_file_content(single_uploaded_file) | |
if content is not None and file_type != "txt": | |
st.success(f"π Loaded {FILE_TYPES.get(file_type, 'π')} file: {single_uploaded_file.name}") | |
elif content is not None: | |
st.success(f"π Loaded file: {single_uploaded_file.name}") | |
if multiple_uploaded_files: | |
for uploaded_file in multiple_uploaded_files: | |
content, file_type = read_file_content(uploaded_file) | |
if content is not None or file_type in ['mp4','webm','ogg']: | |
st.success(f"π Loaded {uploaded_file.name}") | |
st.rerun() | |
if st.session_state.current_file and st.session_state.file_content: | |
st.markdown("---") | |
create_markdown_tabs(st.session_state.file_content, st.session_state.current_file) | |
with book_tab: | |
st.markdown("## π Book View") | |
combined_content = combine_markdown_files() | |
if combined_content: | |
st.markdown(combined_content, unsafe_allow_html=True) | |
else: | |
st.info("Upload some markdown files to see them combined here!") | |
st.markdown("## π Video Gallery") | |
video_playlist = combine_video_files() | |
if video_playlist: | |
st.markdown(video_playlist, unsafe_allow_html=True) | |
else: | |
st.info("No videos found. Upload MP4, WEBM, or OGG files to see them here!") | |
if __name__ == "__main__": | |
main() | |