Acerca de la página
La página esta compuesta de archivos html estáticos generados por org-publish a partir de notas de org-mode en texto plano. Elementos de la wiki y bibliografía de cada página fue manejada mediante org-roam antes de ser exportados de la misma manera. Está inspirada en páginas como esta. Está albergada en un VPS barato, y corre en Debian GNU/Linux. Esta guía cubre este tema de manera muy sencilla. A continuación comparto mi configuración de GNU Emacs y el script de python para generar el gráfico de redes de la wiki:
Org publish (plantillas)
(setq org-publish-project-alist '(("wiki" :base-directory "~/emaacs/org-roam" :base-extension "org" :publishing-directory "~/emaacs/output/pagina/public/wiki/" :recursive t :with-author nil :with-email nil :with-date nil :with-creator t :with-timestamps nil :publishing-function org-html-publish-to-html :headline-levels 4 :section-numbers nil :html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"../css/wiki_style.css\" />" :html-head-include-default-style nil :html-head-include-scripts nil :auto-sitemap t :sitemap-filename "index.org" :sitemap-title "Wiki" :html-preamble "<nav class=\"navbar\"> <div class=\"nav-container\"> <a href=\"/\" class=\"nav-logo\">bananacore.xyz</a> <ul class=\"nav-menu\"> <li><a href=\"/\">Acerca de</a></li> <li><a href=\"/links.html\">Notas</a></li> <li><a href=\"/wiki/index_with_graph.html\" style=\"background-color: #e0f0ff; color: #003366\">Wiki</a></li> </ul> </div> </nav>" ) ("pagina" :base-directory "~/emaacs/templ_pages_ban/" :base-extension "org" :publishing-directory "~/emaacs/output/pagina/public/" :recursive t :with-author nil :with-email nil :with-date nil :with-creator t :with-timestamps nil :publishing-function org-html-publish-to-html :headline-levels 4 :section-numbers nil :html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"../css/style.css\" />" :html-head-include-default-style nil :html-head-include-scripts nil :html-preamble "<nav class=\"navbar\"> <div class=\"nav-container\"> <a href=\"/\" class=\"nav-logo\">bananacore.xyz</a> <ul class=\"nav-menu\"> <li><a href=\"/\">Acerca de</a></li> <li><a href=\"/links.html\">Notas</a></li> <li><a href=\"/wiki/index_with_graph.html\">Wiki</a></li> </ul> </div> </nav>" ) )) (setq org-export-time-stamp-file nil)
Org-roam
(setq org-roam-directory (file-truename "~/emaacs/org-roam")) (org-roam-db-autosync-mode)
Script para gráfico
Paquetes necesarios: bs4, networkx, numpy, pyvis
import os, re from bs4 import BeautifulSoup import networkx as nx import numpy as np from pyvis.network import Network HTML_DIR = "/home/usuario/emaacs/output/pagina/public/wiki" INDEX_FILE = os.path.join(HTML_DIR, "index.html") OUTPUT_FILE = os.path.join(HTML_DIR, "index_with_graph.html") # --- Build directed graph --- G = nx.DiGraph() def is_valid_note_link(href): if href.startswith("#") or href.startswith(("http", "mailto:")): return False if not href.endswith(".html") and ".html#" not in href: return False if "index.html" in href or "index_with_graph.html" in href: return False return True # --- Parse all notes and collect links --- for filename in os.listdir(HTML_DIR): if not filename.endswith(".html"): continue if filename in ("index.html", "index_with_graph.html"): continue filepath = os.path.join(HTML_DIR, filename) with open(filepath, "r", encoding="utf-8") as f: soup = BeautifulSoup(f, "html.parser") for a in soup.find_all("a", href=True): href = a["href"] if not is_valid_note_link(href): continue target = href.split("#")[0] if os.path.exists(os.path.join(HTML_DIR, target)): G.add_edge(filename, target) # --- Node size by degree --- for node in G.nodes: G.nodes[node]["size"] = np.log(G.degree(node) + 1) * 5 # --- Build Pyvis network --- net = Network(height="300px", width="100%", directed=True, bgcolor="#0E0E0E", font_color="#fffff") net.from_nx(G) def clean_label(filename): name = os.path.basename(filename) name = re.sub(r'^\d{14}-', '', name) return name.replace(".html", "") for node in net.nodes: node_id = node["id"] label = clean_label(node_id) node["label"] = label node["title"] = label node["size"] = G.nodes[node_id]["size"] node["url"] = node_id # --- Generate temporary full HTML --- tmpfile = os.path.join(HTML_DIR, "graph_fragment.html") net.write_html(tmpfile, notebook=False) # --- Extract only the necessary fragment --- with open(tmpfile, encoding="utf-8") as f: soup = BeautifulSoup(f, "html.parser") # gather includes (CSS+JS) includes = "\n".join( str(tag) for tag in soup.find_all(["link", "script"]) if "vis-network" in str(tag) ) # gather styles style = soup.find("style") # gather graph div div = soup.find("div", id="mynetwork") # gather JS scripts (edges, nodes, drawGraph) scripts = "\n".join( str(tag) for tag in soup.find_all("script") if any(key in str(tag) for key in ("var edges", "var nodes", "drawGraph")) ) # add interactivity click_js = """ <script type="text/javascript"> network.on("click", function (params) { if (params.nodes.length === 1) { var node_id = params.nodes[0]; var node = nodes.get(node_id); if (node.url) { window.location.href = node.url; } } }); </script> """ fragment_html = ( includes + (str(style) if style else "") + str(div) + scripts + click_js ) # --- Merge into index.html cleanly --- with open(INDEX_FILE, encoding="utf-8") as f: index_html = f.read() insert_point = index_html.find("</h1>") if insert_point == -1: insert_point = index_html.find("</body>") if insert_point == -1: insert_point = len(index_html) new_html = ( index_html[:insert_point] + "<br><br>" + "\n\n<div id='graph-container'>\n" + fragment_html + "\n</div>\n" + "<br><br><br>" + index_html[insert_point:] ) # --- Write output --- with open(OUTPUT_FILE, "w", encoding="utf-8") as f: f.write(new_html) os.remove(tmpfile)
Acerca de mí
Mi nombre es Rodrigo. Esta página es una manera conveniente de organizar y mantener mis apuntes. También planeo escribir proximamente sobre temas que me interesan. Gracias por tu visita.
Intereses
- Novelas del siglo XX. Autores favoritos: A. Malraux, M.
HouleqeqHoullebeqHolleqbecHouellebecq, E. Hemingway, L.Ferdinand Céline, V. Nabokov, J. Kerouac, R. Arlt, J. Donoso, JM. Arguedas, Edgard Norabuena Figueroa. - Música (música fea como breakcore, hardcore, speedcore, gabber, chiptune, eurobeat, italo-disco; dream pop y géneros relacionados; música doujin de touhou, denpa, j-pop; punk, metal, grindcore).
- Historia económica (la gran divergencia, política industrial, planificación económica).
- Neurociencia (neurofisiología, metodos electrofisiológicos, comportamiento).
Contacto
Mi correo principal es rodrigo.caceres1@unmsm.edu.pe. Esta es mi clave PGP pública para comunicación encriptada:
-----BEGIN PGP PUBLIC KEY BLOCK----- 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 d+uRpdq/iPgaXXk44buyetsRShxpkBDwHXpz8wEdtGFj9t4HsU+KySyTRZAPWenf yW1FiwtWa/gkjVX3FtzlZKGtw1P1Z72yDbUj/Uc2676DTL0jaTJGeq4Q2/iMot8K 4Z7auPsCuImEKm9iAjYz54QLzPkT2NObGUCHDg4KTDR+xPzl6sbO4bzpPfD4e6Ml hdmIEHovP6k5F/Dq/tSNab7YbLdGM4y4e0GpY56HWUkr7LyAeWb6JN+FOcE1iQ0R vaW+SeiIOV3vC4vOePJzEXiKPlx5drQvhY+xMKEPt4UyVwslVYHh1NUYx4nBTuUd BqIZpAbFmE6T+s3Q1Q9JPud96+qQ/ipxDQz6ijL/+1LlYV7c8LxaZIdh923wrKao aJmkFpjtj8WsPxgqu2MWYZTvl8IDVO15+2DUgksPDNIrhGuo8SPbABEBAAG0Im1h cmlvX2phcmEgPG1hcmlvX2phcmFAb21hZXJhLm9yZz6JAk4EEwEIADgWIQS9jdic Iv66n9LecsHGoZ+UK+v7FQUCaRNThgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIX gAAKCRDGoZ+UK+v7FX/uEACWji50yAVbwSCzDaHShPJtW6N4vijGOGtsajShYo9j FKbX1tiRyP2SjJrqiJXfuA+38xPJTJb7/SuSgoJ4YnZ7TRZplaVft6czmK+c+QvK tKyJC+5YVWAuf6cNUNsGw1GlJHt0v+B31/x4IByEP1XhI3TrfhZyxo4vgwK2dUx2 KJ5L19Il9NzhqA8f4k+RSRlqPvl+3P+E+5dESobz2lHNzTic3POKWjx/2iZmaCRm CNuLYOvEOdXOx6Cee4QqR3jKi6tseCTRft3MGWkA3NbNOAxYj4FSNVT5XV288kAA w7fEtTa875dkbw2JQF8V2dZWPX8zzvsemRsU0boLndJKv9U2AscEHgjeI3+qxXtE 99FR8l6jFwCUU+hYcpB/2ngouEnqEQDBdbA7kqtdFBNDKWGFrhljIzPJSoEWqMve AriQVMbybAmfqdeWZAffap5vfFhBA/gQ16Nc76jVOOSbndAFAeFOrXcgY6cx14k5 S7KrmnwelropSY+j7zw8XRaboGDAxolt4oBqOyEtiQ9WqNNVcFlrL6ldvCuN6SpC Jk7x0rf9tC3d2DYypVixPttOupMjUvYzZPmpO9R2RabL9KLao2dmMR2IZwl1VDmm R9UXZ4AmcM2pJRm8ZEHdiWS81Oh49lS2+SzZ5Eh0tl7rLgcgalJfLP2cLN+sVXIk OrkCDQRpE1OGARAAnjbs73W0zyV9BFzaPBbGYT12460/lI5+KZuNAYDBFIL15rTi ZK6e9D3KArnwVs56qrxgVA0MlsKVREdlvnfuPtTsFdgsMpaMMGVY66SwzWVXIpn4 o41U8NQlIklK411R/ApcUZrUC9FtKT8FSiQE3nK/QXQqmip+6XuNeUvX2QMIpC7+ eXiJ47i6Sp2zqzwI3zoh+ujoqyd1cSht/0otjyCeH21QPLc4x9iiNea8PHbXcymY oWj1ec+NoGHcaTsd7XRK45y1jY9DEDsGA1XYhLiaYGetINP94c4n1jobkCx0erYx mqUobPk4dfKdYj5RMk0a9coyXLlI5OXeVyhnRn2ozAu+bYJ1VWt9X7tGV2i4sRWI w6fuGeSYf8h5OBr+v4kamV1WyrHFWwZ/1WvV458b2SMDXWaL33CZ/tCtuianf8qF 1Lm2ACQUopLj6XyiXPwwIJPZfdWev2ZPGAR8bv8kwXhig+ZAUyBmbhdweZ4dmtMX N9yXR8RmYhM31b/TWauIrBBEpFVuM7NUfWRZojC7zx5SXbD9Ygkrs9CBQhHiRKPF MlasJbeVmGTY6oF82fnzmWgZmukoSouwwFtyxe0pBXVpEX2gzBzxR1q2NMizcDLv zsXn8vqotiS2q9ozxc3G5zk/WCMhRE9vRrWOKNhIDx82XvsVDcyQfN+3NGEAEQEA AYkCNgQYAQgAIBYhBL2N2Jwi/rqf0t5ywcahn5Qr6/sVBQJpE1OGAhsMAAoJEMah n5Qr6/sVPeEQAIJ65lsT9pxojwvh04ZsD6jXrlJPrjWMcv9zf7CQrKTLNknM9pno t2qR5uPClVLToUGQTl3fR47VOPxLnFj67g9zJ8Mmf+xfNvVF1A7BPcORS40FSLcq lqXzsbqBeSX0i8KVh4i2OpozX9OX16NthEc1MG76VY0RfgmXrY2F9midWGBAVVk3 mE2qYVfzsRllAR6MGVLHvzGd3I3eiYsyE7afew9Xgt9UHh+FDS8kG2LRoWbds8PO MDymEPatv5duMOoHOSEUicZfnSEgMPlECnD60AKBxuk/RnHpvO9/HoxYINfnBWvK ONFNaH8buGF4SIT7HQJUKZ48UtYC26Q/RYaAj15ZlzXFVC1AAwxpevNGBAD/zYpO hWNN5dKHzyBU9aoK2GVHBRhvfPAiMGUHJsyj5At5L7E3A0VDsr9+7qt9gWchlnZg Pek29lynj2RZsgkGdlJDQlNVGQTN+Y3sqHkydM98y21Q1RNZ8Rig7PCqOclK6S64 DS6z/3gRoN4GWy1nz2QpZfsu1bbBTaEcPmqhXc/B+mUw0L76pAcALIjMTomGRDE+ ympOPUjic1Z2Z9v+pC1HNCWSs8TLhvHA9u7uNQeuviE3SHoykZxqyRJSXXp5tCQ+ 7EYuu4Rca5vuuBPDCxepwiqHfA0/cOjiljDAE8sVv9oLGP2P1aDZ5Y2Y =ZLuZ -----END PGP PUBLIC KEY BLOCK-----