Skip to content

Commit

Permalink
Update generate_markdown_list.py
Browse files Browse the repository at this point in the history
  • Loading branch information
diegovelezg authored Feb 2, 2025
1 parent 216634a commit 4757c3a
Showing 1 changed file with 67 additions and 49 deletions.
116 changes: 67 additions & 49 deletions generate_markdown_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def escape_json_config(config_file):
config = json.loads(clean_control_characters(f.read()))
with open(config_file, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2, ensure_ascii=False)
except (json.JSONDecodeError, Exception) as e:
except Exception as e:
print(f"Error processing {config_file}: {e}")

def process_config_files(root_dir):
Expand All @@ -26,75 +26,97 @@ def process_config_files(root_dir):
def extract_preview(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
match = re.search(r'<!--\s*preview:start\s*-->(.*?)<!--\s*preview:end\s*-->', content, re.DOTALL)
return match.group(1).strip() if match else ""
match = re.search(r'<!--\s*preview:start\s*-->(.*?)<!--\s*preview:end\s*-->', content, re.DOTALL)
return match.group(1).strip() if match else ""

def modify_activity_links(content, lang, track, skill, module):
replacement_base = f"?lang={lang}&track={track or ''}&skill={skill or ''}&module={module or ''}"
return re.sub(r"//PATH_TO_THIS_SCRIPT:\?lang=XX&track=XXX&skill=XXXXXX&module=XXXXXX//", replacement_base, content)

def get_levels(file_path, root_dir):
"""
Extrae los niveles ignorando el nivel "COURSES" y,
en caso de archivos README, utiliza el nombre de la carpeta en lugar del nombre del archivo.
Extrae los niveles de la ruta.
- Si el archivo está en COURSES:
• Se descarta el primer nivel ("COURSES").
• El primer directorio restante se usa como ID del curso (almacenado en "skill").
• El segundo directorio (si existe) se usa como módulo.
• Se devuelve (track, skill, module) donde track = None.
- Si no está en COURSES se usa la lógica original: (track, skill, module).
"""
parts = os.path.relpath(file_path, root_dir).split(os.sep)
# Descartamos el primer nivel si es "COURSES"
if parts and parts[0].upper() == "COURSES":
parts = parts[1:]
# Si el archivo es un README, eliminamos el último elemento (el nombre del archivo)
if parts and parts[-1].upper().startswith("README"):
parts = parts[:-1]
track = parts[0] if len(parts) >= 1 else None
skill = parts[1] if len(parts) >= 2 else None
module = parts[2] if len(parts) >= 3 else None
return (track, skill, module)
if parts[0].upper() == "COURSES":
parts = parts[1:] # descartamos "COURSES"
# Si es un README, usamos el nombre de la carpeta en lugar del nombre del archivo
if parts and parts[-1].upper().startswith("README"):
parts = parts[:-1]
course = parts[0] if len(parts) >= 1 else None
module = parts[1] if len(parts) >= 2 else None
return (None, course, module)
else:
track = parts[0] if len(parts) >= 1 else None
skill = parts[1] if len(parts) >= 2 else None
module = parts[2] if len(parts) >= 3 else None
return (track, skill, module)

def get_file_type(file_path, subdir, file):
"""
Determina el tipo de archivo basándose en la ruta (descartando "COURSES")
y en si se trata de un README.
Regla:
- Si es un README y quedan 1 carpeta → "course"
- Si es un README y quedan 2 carpetas → "module"
- Si no es README y está en una carpeta de "activities" → "activity"
- En otro caso, se usa una lógica de fallback según la profundidad.
Determina el tipo de archivo.
- Si el archivo está en COURSES:
• Se descarta "COURSES" de la ruta.
• Si es un README y, tras quitar el nombre del archivo, queda solo 1 carpeta, se asigna "course".
Si es un README y quedan 2 carpetas, se asigna "module".
Si el archivo está en una carpeta de "activities" y no es README, se asigna "activity".
- Si el archivo no está en COURSES se usa la lógica original:
• El primer directorio es track, el segundo skill, el tercero module.
"""
parts = os.path.relpath(file_path, root_dir).split(os.sep)
if parts and parts[0].upper() == "COURSES":
if parts[0].upper() == "COURSES":
parts = parts[1:]
if file.upper().startswith("README"):
parent_parts = parts[:-1] if parts and parts[-1].upper().startswith("README") else parts
if len(parent_parts) == 1:
if file.upper().startswith("README"):
folder_parts = parts[:-1] if parts and parts[-1].upper().startswith("README") else parts
if len(folder_parts) == 1:
return "course"
elif len(folder_parts) >= 2:
return "module"
else:
return "course"
if "activities" in subdir.lower() and not file.upper().startswith("README"):
return "activity"
depth = len(parts)
if depth == 1:
return "course"
elif len(parent_parts) == 2:
elif depth == 2:
return "module"
else:
return "module"
if "activities" in subdir.lower() and not file.upper().startswith("README"):
return "activity"
depth = len(parts)
if depth == 1:
return "program"
elif depth == 2:
return "course"
elif depth == 3:
return "module"
return "activity"
else:
return "activity"
if "topics" in subdir.lower():
return "topic"
if "activities" in subdir.lower() and not file.upper().startswith("README"):
return "activity"
parts = os.path.relpath(file_path, root_dir).split(os.sep)
depth = len(parts)
if file.upper().startswith("README"):
if depth == 1:
return "program"
elif depth == 2:
return "skill"
else:
return "module"
else:
return "activity"

def get_title(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
match = re.search(r'#\s*(.+)', content)
return {"title": match.group(1).strip(), "lang": "ES" if file_path.endswith("_ES.md") else "PT"} if match else {"title": "Sin título", "lang": "ES" if file_path.endswith("_ES.md") else "PT"}
match = re.search(r'#\s*(.+)', content)
return {"title": match.group(1).strip(), "lang": "ES" if file_path.endswith("_ES.md") else "PT"} if match else {"title": "Sin título", "lang": "ES" if file_path.endswith("_ES.md") else "PT"}

def read_config_data(config_file):
try:
with open(config_file, 'r', encoding='utf-8') as f:
return json.load(f)
except (json.JSONDecodeError, FileNotFoundError):
except Exception:
return {}

def generate_markdown_list(root_dir):
Expand All @@ -105,7 +127,6 @@ def generate_markdown_list(root_dir):
for file in files:
file_path = os.path.join(subdir, file)
if file.endswith(".md"):
# Extraemos niveles ignorando "COURSES"
track, skill, module = get_levels(file_path, root_dir)
file_type = get_file_type(file_path, subdir, file)
lang = "ES" if file.endswith("_ES.md") else "PT" if file.endswith("_PT.md") else None
Expand All @@ -131,14 +152,13 @@ def generate_markdown_list(root_dir):
discord_channel_id, discord_message_id = None, None
slug = f"{track or ''}{'-' + skill if skill else ''}{'-' + module if module else ''}-{os.path.splitext(file)[0]}"
directions = extract_preview(file_path) if file_type in ["program", "course", "module"] else config_data.get("directions", {}).get(lang, "")

markdown_dict = {
"track": track,
"skill": skill,
"module": module,
"title": titles.get("title", "Sin título"),
"type": file_type,
"path": file_path[2:], # Quitar "./" si existe
"path": file_path[2:], # Quita "./" si existe
"lang": lang or titles.get("lang"),
"difficulty": config_data.get("difficulty", ""),
"learning": config_data.get("learning", ""),
Expand All @@ -149,11 +169,9 @@ def generate_markdown_list(root_dir):
"discord_message_id": discord_message_id,
"slug": slug
}

# Lógica antigua para archivos fuera de COURSES
# Para archivos fuera de COURSES se usa la lógica antigua:
parts_orig = os.path.relpath(file_path, root_dir).split(os.sep)
if not parts_orig or parts_orig[0].upper() != "COURSES":
# Actualizamos según la longitud disponible
if parts_orig[0].upper() != "COURSES":
if file_type == "program":
markdown_dict.update({
"track": parts_orig[0] if len(parts_orig) >= 1 else None,
Expand Down

0 comments on commit 4757c3a

Please sign in to comment.