1
0
Fork 0
Actualización de [libre-maker](https://git.librebits.info/lab/libre-marker)
Go to file
MrPokeYT 2cec2cef40 Eliminar CLAUDE.md 2026-02-01 14:49:49 +00:00
Screenshots 3,2,1... adelante, demiurgos del teclado XD 2025-12-04 23:47:04 +01:00
README.md 3,2,1... adelante, demiurgos del teclado XD 2025-12-04 23:47:04 +01:00
visor.html 3,2,1... adelante, demiurgos del teclado XD 2025-12-04 23:47:04 +01:00

README.md

Libre-marker Project

con Nginx + JavaScript. Podemos configurar Nginx para que, cuando alguien pida un .md, Nginx le sirva una pequeña plantilla HTML "invisible" que contenga la librería Marked y renderice el texto al instante.

FASE1 - Libre-marke viewer

Aquí tienes cómo montar tu propio "Markdown Viewer" estático en 2 pasos:

Paso 1: Crear el "Visor Mágico" (visor.html)

Crea un archivo llamado visor.html en la raíz de tu sitio web (junto a tus archivos .md). Copia este código exacto.

Este código usa la librería Marked (la que mostraste en la imagen) para convertir el texto a HTML en el navegador del visitante.

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Visor Markdown</title>
    <style>
        body { font-family: sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; line-height: 1.6; }
        img { max-width: 100%; }
        pre { background: #f4f4f4; padding: 10px; border-radius: 5px; overflow-x: auto; }
        /* Puedes añadir aquí CSS para que se vea como GitHub o tu estilo preferido */
    </style>
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
</head>
<body>
    <div id="content">Cargando documento...</div>

    <script>
        // 1. Detectar qué archivo .md se pidió (viene en la URL)
        const urlParams = new URLSearchParams(window.location.search);
        const file = urlParams.get('file');

        if (file) {
            // 2. Descargar el archivo .md
            fetch(file)
                .then(response => {
                    if (!response.ok) throw new Error("No se encontró el archivo.");
                    return response.text();
                })
                .then(text => {
                    // 3. Convertir Markdown a HTML y mostrarlo
                    document.getElementById('content').innerHTML = marked.parse(text);
                })
                .catch(err => {
                    document.getElementById('content').innerHTML = "Error: " + err.message;
                });
        } else {
            document.getElementById('content').innerHTML = "No se ha especificado ningún archivo.";
        }
    </script>
</body>
</html>

Paso 2: El Truco de Nginx (La Redirección)

Ahora configuramos Nginx para que intercepte la petición. Cuando el usuario escriba misitio.com/manual.md, Nginx reescribirá internamente la petición para cargar el visor, pasándole el nombre del archivo.

Edita tu configuración del sitio (/etc/nginx/sites-enabled/tustio):

server {
    # ... tu configuración actual ...
    root /var/www/tusitio;
    index index.html;

    # REGLA MÁGICA PARA MARKDOWN
    location ~ \.md$ {
        # Si el archivo existe, redirige al visor
        try_files $uri @markdown_viewer;
    }

    location @markdown_viewer {
        # Reescribe la URL para usar el visor.html
        # Ejemplo: manual.md -> /visor.html?file=manual.md
        rewrite ^/(.*\.md)$ /visor.html?file=$1 last;
    }
    
    # ... resto de la config ...
}

Paso 3: Reiniciar y Probar

  1. Reinicia Nginx:
service nginx restart
  1. Borra caché del navegador (Ctrl + Shift + R).

    Entra a librebits.info/tu-archivo.md.

  2. ¿Qué ocurrirá?

    La URL en el navegador seguirá diciendo tu-archivo.md (elegante).

    Pero lo que verás en pantalla será el HTML generado, con títulos, negritas y enlaces, tal cual querías.

¿Te animas a probar este enfoque? Es muy ligero y no requiere instalar PHP ni bases de datos.

FASE 2 - Live Editor + Preview

Editor Markdown en tiempo real con split view, inspirado en la demo oficial de Marked.js (ver Screenshots/markedJS-demo.png).

Arquitectura

100% cliente-side. Nginx solo sirve el HTML estático, toda la lógica ocurre en el navegador usando JavaScript vanilla + Marked.js.

Componentes UI

┌─────────────────────────────────────────────────────────────┐
│ Barra superior: [Dropdown Views] [Clear] [Version] [Theme] │
├──────────────────────────┬──────────────────────────────────┤
│                          │                                  │
│   PANEL IZQUIERDO        │    PANEL DERECHO                 │
│   (Editor)               │    (Preview)                     │
│                          │                                  │
│   <textarea>             │    <div id="preview">            │
│   Markdown crudo         │    HTML renderizado              │
│   con sintaxis           │    en tiempo real                │
│                          │                                  │
└──────────────────────────┴──────────────────────────────────┘

Funcionamiento

  1. Textarea con evento oninput:

    textarea.addEventListener('input', (e) => {
        const markdown = e.target.value;
        renderPreview(markdown);
    });
    
  2. Renderizado instantáneo:

    function renderPreview(text) {
        const view = currentView; // Preview, HTML Source, Lexer Data
    
        switch(view) {
            case 'preview':
                preview.innerHTML = marked.parse(text);
                break;
            case 'html':
                preview.textContent = marked.parse(text);
                break;
            case 'lexer':
                preview.textContent = JSON.stringify(marked.lexer(text), null, 2);
                break;
        }
    }
    
  3. Layout CSS Grid/Flexbox:

    • Split 50/50 horizontal
    • Responsive: stack vertical en móviles
    • Dark mode toggle

Características a Implementar

  • Split view editor/preview
  • Actualización en tiempo real (oninput)
  • Dropdown con vistas: Preview, HTML Source, Lexer Data, Quick Reference
  • Botón "Clear" para limpiar editor
  • Dark mode
  • Cargar archivo .md existente para editar
  • Botón "Download" para guardar cambios localmente
  • LocalStorage para persistencia temporal

Sin Backend Necesario

Todo funciona en el cliente con:

  • HTML + CSS + JavaScript vanilla (ES6+)
  • Marked.js (CDN: https://cdn.jsdelivr.net/npm/marked/marked.min.js)
  • Nginx sirviendo archivos estáticos

FASE 3 - Control de Versiones con Git

Añadir capacidad de commit directo desde el navegador para versionar cambios en archivos Markdown.

Visión General

Botón "💾 Commit" en la interfaz que guarda el estado actual del archivo con mensaje de commit, creando un historial versionado.

Desafío: Seguridad del Navegador

JavaScript en el navegador NO puede ejecutar comandos git directamente por restricciones de seguridad. Necesitamos un puente mínimo servidor-cliente.

Opciones de Implementación (Out-of-the-box thinking)

Opción A: GitHub API (Sin Backend Custom)

Pros: Sin código servidor, usa API REST de GitHub Contras: Requiere repo público/privado en GitHub, token de autenticación

// Commit directo vía GitHub API
async function commitToGitHub(filename, content, message) {
    const response = await fetch(`https://api.github.com/repos/user/repo/contents/${filename}`, {
        method: 'PUT',
        headers: {
            'Authorization': `token ${GITHUB_TOKEN}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            message: message,
            content: btoa(content), // Base64
            sha: currentFileSHA // Obtenido previamente
        })
    });
    return response.json();
}

Flujo:

  1. Usuario edita markdown
  2. Click en "Commit" → prompt para mensaje
  3. JavaScript hace PUT a GitHub API
  4. Archivo actualizado en el repo remoto
  5. Historial visible en GitHub

Opción B: Endpoint Mínimo PHP/Python + Git Local

Pros: Control total, commits locales, no depende de GitHub Contras: Requiere script servidor (rompe filosofía "sin backend")

// save.php (ejecutado vía Nginx FastCGI)
<?php
$file = $_POST['file'];
$content = $_POST['content'];
$message = $_POST['message'];

// Guardar archivo
file_put_contents("/var/www/docs/{$file}", $content);

// Git commit
exec("cd /var/www/docs && git add {$file}");
exec("git commit -m " . escapeshellarg($message));

echo json_encode(['status' => 'ok']);
?>

Configuración Nginx:

location /api/save {
    fastcgi_pass unix:/var/run/php/php-fpm.sock;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /var/www/scripts/save.php;
}

Opción C: LocalStorage + Historial JSON (Sin Git Real)

Pros: 100% cliente, sin servidor, funciona offline Contras: No es git real, historial solo en navegador local

// Pseudo-versionado con LocalStorage
function saveVersion(filename, content, message) {
    const history = JSON.parse(localStorage.getItem('mdHistory') || '[]');

    history.push({
        file: filename,
        content: content,
        message: message,
        timestamp: new Date().toISOString(),
        sha: simpleHash(content) // Hash simple como "commit ID"
    });

    localStorage.setItem('mdHistory', JSON.stringify(history));
}

// Exportar historial como .json
function exportHistory() {
    const data = localStorage.getItem('mdHistory');
    downloadFile('history.json', data);
}

Opción D: Git via WebAssembly (Experimental)

Pros: Git real en el navegador, sin backend Contras: Tecnología emergente, compleja, tamaño de bundle grande

Usar isomorphic-git compilado a WASM para ejecutar operaciones git directamente en el navegador.

Recomendación por Fases

  1. FASE 3.1 (Más simple): Opción C - LocalStorage + exportar historial
  2. FASE 3.2 (Híbrido): Opción B - Endpoint PHP mínimo para git local
  3. FASE 3.3 (Cloud): Opción A - GitHub API para equipos colaborativos
  4. FASE 3.X (Futuro): Opción D - Git WASM cuando madure la tecnología

UI Propuesta

┌──────────────────────────────────────────────────────────┐
│ [💾 Commit] [📜 History] [⬇️ Export]     [Theme] [Help] │
├─────────────────────────┬────────────────────────────────┤
│  Editor                 │  Preview                       │
│                         │                                │
└─────────────────────────┴────────────────────────────────┘

Al click en "💾 Commit":
┌─────────────────────────────────────┐
│  Commit Message:                    │
│  ┌───────────────────────────────┐  │
│  │ Updated documentation         │  │
│  └───────────────────────────────┘  │
│                                     │
│      [Cancel]    [💾 Save]          │
└─────────────────────────────────────┘

Reference: Marked - Markdown Parser

========================

Marked lets you convert Markdown into HTML. Markdown is a simple text format whose goal is to be very easy to read and write, even when not converted to HTML. This demo page will let you type anything you like and see how it gets converted. Live. No more waiting around.

How To Use The Demo

  1. Type in stuff on the left.
  2. See the live updates on the right.

That's it. Pretty simple. There's also a drop-down option above to switch between various views:

  • Preview: A live display of the generated HTML as it would render in a browser.
  • HTML Source: The generated HTML before your browser makes it pretty.
  • Lexer Data: What marked uses internally, in case you like gory stuff like this.
  • Quick Reference: A brief run-down of how to format things using markdown.

Why Markdown?

It's easy. It's not overly bloated, unlike HTML. Also, as the creator of markdown says,

The overriding design goal for Markdown's formatting syntax is to make it as readable as possible. The idea is that a Markdown-formatted document should be publishable as-is, as plain text, without looking like it's been marked up with tags or formatting instructions.

Ready to start writing? Either start changing stuff on the left or clear everything with a simple click.