206 views
# #REPORT2_ES ## Una metáfora de publicación A continuación se narra no un sistema o un flujo de publicación, sino de un paradigma de programación que, entre varias posibilidades, permite publicar en el sentido tradicional o como _crossmedia_ o _transmedia_. Este paradigma se conoce como programación literaria ==TODO== y con ella se implementará una metáfora de publicación. Un sistema de publicación es un flujo de producción que puede permitir amplias modificaciones, aunque por lo general están planteadas para tener un flujo específico. Un sistema de publicación te permite modificar objetos o flujos, pero siempre hay una distancia entre la entidad productora y la entidad producida. Pero en un contexto digital esa distancia ha sido puesta en el diseño de un flujo que se constituye como «sistema de publicación». El «sistema» para hablar de publicación digital es también una metáfora computacional. Daniel Ingalls, que junto con Alan Kay son los pioneros en los dos paradigmas más comunes en la computación (leguajes orientados a objetos e interfaces gráficas), nos dice en «[Principios de diseño de Smalltalk](https://studylib.es/doc/8280398/principios-de-dise%C3%B1o-de-smalltalk)» (1981): > **Objetos**: Un lenguaje de computación debe soportar el concepto de «objeto» y proveer una manera uniforme de referirse a los objetos de universo. Más adelante: > **Metáfora uniforme**: Un lenguaje debería ser diseñado alrededor de una metáfora poderosa que pueda ser aplicada uniformemente en todas las áre as. Es decir, Ingalls nos advierte que los «objetos» computacionales son metáforas que nos permiten inteligir lo que una computadora hace pero que no necesariamente está haciendo en la materialidad de sus circuitos interaccionando con una corriente eléctrica. Incluso los «ceros» y los «unos» que se consideran el lenguaje más bajo para comunicarse con las computadoras es una metáfora, ya que estas operan con una presencia o ausencia de electrones, una danza electromagnética. Cfr. «[_Metáforas de la vida cotidiana_](https://gitlab.com/NikaZhenya/bibliografia/-/blob/master/todo/lakoff2009a.pdf?expanded=true&viewer=rich)» (George Lakoff y Mark Johnson, 2009) y «[_No hay ningún_ software](https://gitlab.com/NikaZhenya/bibliografia/-/blob/master/todo/kittler2018b.pdf)» (Friedrich Kittler, 2018) Para publicar los textos de esta investigación se necesita de alguna metáfora que nos permita intelegir su funcionamiento mediante la lectura, pero también la capacidad de escribir este funcionamiento mediante su programación. ## La cocción De manera convencional se dice que una receta está «cruda» cuando RuWEB no ha sido empleado en este _input_ y «cocida» cuando ya se produjeros los _outputs_. En esta receta es específico, y como se explicará más adelante, puedes saber que está cruda si ==TODO==. Si no ==TODO== es porque RuWEB ya procesó esta receta cuyas indicaciones señalas más adelante cocina también este texto. Para evitar mayores confusiones, puedes leer esta receta en sus dos momentos: * [receta cruda](https://pad.programando.li/s/Hcd3dwQyN) * [receta cocida](https://nikazhenya.gitlab.io/maestria-investigacion/misc/reporte2.html) :::success ¿Sabías que la «receta» para que lo «crudo» por medio de «eventos» sea lo «cocido» es una «metáfora uniforme» de la edición y publicación inspirada en [v#SAX](http://alturl.com/73aep), una [v#API](http://alturl.com/9bht7) para [v#XML](https://es.wikipedia.org/wiki/Extensible_Markup_Language) basada en eventos, la crítica de Derrida a Lévi-Strauss en «[La estructura, el signo y el juego en el discurso de las ciencias humanas](https://mercaba.org/SANLUIS/Filosofia/autores/Contempor%C3%A1nea/Derrida/La%20estructura.pdf)» y el «[Recetario para humanidades desocupadas](https://ranchoelectronico.org/miau-en-flisol2021-recetario-para-humanidades-desocupadas/)»? ::: :::success Pero ¿también sabías que al ser esto la constitución de una metáfora, podrías retomar el código y reescribirlo todo hasta el punto de tener otras metáforas, programas, documentación o publicaciones? ::: **Ahora sí, ¡a cocinar!** ## La definición de metadatos en Ruby ==TODO== Toda la descripción del código va a ser más expresiva, por el momento está en sus significantes mínimos. ==TODO== Lo primero que se explica son los tipos de datos más comunes en Ruby a partir de la definición de metadatos. Los primeros metadatos: ```ruby=+ META = { lang: 'es', title: 'El creador y lo creado', subtitle: 'Maestría en Filosofía', description: 'La propiedad intelectual como supuesto en la producción cultural y filosófica', tags: 'investigación, maestría, tesis, nika, zhenya, epub, ebook, publishing, libros, markdown, html, xhtml, mobi, perro, tuerto, propiedad, intelectual, bienes, comunes', site: 'https://maestria.perrotuerto.blog', contact: { email: 'hi@perrotuerto.blog', blog: 'https://perrotuerto.blog' }, authors: [{ name: 'Ramiro', lastname: 'Santa Ana Anguiano', affiliation: 'UNAM-FFyL' }], publishers: ['Perro Tuerto'], license: { name: 'Licencia Editorial Abierta y Libre', acronym: 'LEAL', url: 'https://gitlab.com/programando-libreros/juridico/licencia-editorial-abierta-y-libre' } } ``` Manifiesto de la red de pads de este proyecto: ```ruby=+ META[:pad_server] = 'https://pad.programando.li/' META[:pads] = { acknowledgements: 'jlCAkyqDST-5HG8tQVPpQA', acronyms: 'Fvf4kt6zSDiygthmIN-xSA', intro: 'yic1NgzXRfqdEPnjtSHQFw', chap1: '6Me0yOV0TluiGX-xuYnX-g', chap2: 'vG2T2khBTW60tAOErUtQMw', chap3: 'wMhXyjhBTyW__RVD5oWncA', conclusion: 'WnIO3M_nSYODaLiGGyd-Vw', glossary: 'RuYyNvjeQ0WidMee7unIVQ', todo_list: 'jQwG6o40Sm20EGsncIS23w', bib: '6LiuDuMbRiyvLYu2Ix5w3A', report1_es: 'XE1d-Mb1RiK5hfwOWrnKkQ', report1_en: 'bHS6ZMrCSti9hEttm-28wA', report2_es: '_CrMDL2FS6Ouu3umzgDOkQ', report2_en: 'KAdEIUXpT-q6gsIl1HxogQ', essay_es: 'G_0bDEq-Sh-Xhzs2BrVqIA', essay_en: 'jcRrTwa4S_2cuOl7uQ8yuw', index: 'NEfYglcaTLOFF0xdg9D4LA' } ``` Orden de lectura de la publicación: ```ruby=+ META[:spine] = [ 'acknowledgements', 'acronyms', 'intro', 'chap1', 'chap2', 'chap3', 'conclusion', 'glossary', 'todo_list' ] ``` Declaración de títulos ```ruby=+ META[:titles] = { acknowledgements: 'Agradecimientos', acronyms: 'Lista de siglas y acrónimos', intro: 'Introducción. Un tema filosófico desatendido', chap1: 'Teorías de la propiedad intelectual', chap2: 'Críticas de los bienes comunes', chap3: 'Puntos de encuentro', conclusion: 'Conclusión. YYY', glossary: 'Glosario', todo_list: 'Tareas pendientes', bib: 'Bibliografía', report1_es: 'Cómo está hecha: tesis de Maestría', report1_en: 'How It Is Made: Master Research Thesis', report2_es: 'Cómo está rehecha: tesis de Maestría', report2_en: 'How It Is Remade: Master Research Thesis', essay_es: 'Metafísicas y tecnologías de la creación', essay_en: 'Metaphysics and technologies of creation' } ``` Declaración de enlaces relevantes: ```ruby=+ META[:research] = { html: 'research/creador_creado.html', icml: 'research/creador_creado.xml', pdf: 'research/creador_creado.pdf', epub: 'research/creador_creado.epub', docx: 'research/creador_creado.docx', mobi: 'research/creador_creado.mobi' } META[:bib] = { db: 'bib/bibliografia.bib', query: 'bib/bibliografia.html', download: 'https://gitlab.com/NikaZhenya/bibliografia/-/tree/master' } META[:repo] = { oxacab: 'https://0xacab.org/NikaZhenya/maestria-investigacion', gitlab: 'https://gitlab.com/NikaZhenya/maestria-investigacion' } META[:dl] = { zip: 'https://gitlab.com/NikaZhenya/maestria-investigacion/-/archive/ed2/maestria-investigacion-master.zip', tar: 'https://gitlab.com/NikaZhenya/maestria-investigacion/-/archive/ed2/maestria-investigacion-master.tar', gz: 'https://gitlab.com/NikaZhenya/maestria-investigacion/-/archive/ed2/maestria-investigacion-master.tar.gz', bz2: 'https://gitlab.com/NikaZhenya/maestria-investigacion/-/archive/ed2/maestria-investigacion-master.tar.bz2' } META[:misc] = { essay_es: 'misc/ensayo.html', essay_en: 'misc/essay.html', report1_es: 'misc/reporte1.html', report1_en: 'misc/report1.html', report2_es: 'misc/reporte2.html', report2_en: 'misc/report2.html' } ``` ## Los primeros métodos en Ruby ==TODO== De la descripción de datos se pasa a la explicación de la implementación de método en Ruby. Método para obtener una marca temporal en segundos ```ruby=+ def puts_timestamp Time.now.to_i.to_s end ``` Método para obtener la fecha ```ruby=+ def puts_date t = Time.now m = ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'] "#{t.day} de #{m[t.mon - 1]} del #{t.year}" end ``` Método para eliminar los metadatos de escritura de los pads: ```ruby=+ def remove_yaml_from(pad) pad.sub(/^---\n+(.|\n)+?---(\n+|$)/, '') end ``` La eliminación de metadatos de escritura es para permitir asignar valores distintos para su publicación. Sin embargo, la eliminación no es necesaria. ## La obtención del contenido de los pads Método para extraer el contenido de un pad ```ruby=+ require 'open-uri' def obtain_content_from(pad_id) url = "#{META[:pad_server]}#{pad_id}/download" URI.parse(url).open.read.strip end ``` De los id de los pads a su contenido por medio de una iteración. Los crudos se guardan para archivo ```ruby=+ raw_data = {} data = {} META[:pads].each do |pad_name, pad_id| raw_data[pad_name] = obtain_content_from(pad_id) data[pad_name] = remove_yaml_from(raw_data[pad_name]) end ``` ## El contenido para la publicación Para las publicaciones se tienen que unir los pads declarados en el orden de lectura y eliminar los contenidos sueltos ```ruby=+ publication_in_md = '' META[:spine].each do |pad_name| pad_name = pad_name.to_sym publication_in_md += "\n\n#{data[pad_name]}" data.delete(pad_name) end data[:creador_creado] = publication_in_md.strip ``` ## Unas pruebas de marcado Con los contenidos listos para su procesamiento, se realizan algunas pruebas al respecto. Asignación del símbolo que servirá de separador, a modo de punto entre la cadena de caracteres arbitrarios que conforman un texto. ```ruby=+ E = "#" ``` Podría ser cualquier símbolo, se escoge `#` por su amplio uso como [#etiquetador](https://es.wikipedia.org/wiki/Hashtag). La diferencia en su uso como separador es que se empleará para determinar un «evento»: el posicionamiento en una parte de la cadena que permite procesar caracteres a la izquierda y a la derecha. Para ello se requiere un método que nos permita capturar caracteres a petición de un lado y del otro que, de coincidir, permita una [retrollamada](https://es.wikipedia.org/wiki/Callback) para cambiar lo que sea y como sea del texto capturado. ```ruby=+ def cut(pad, a:, b:, callback:) regex = /(?<prefix>.{0,1})(?<a>#{a})#{E}(?<b>#{b})/ pad.gsub(regex).each_with_index do |string, index| if string[0].ord != 96 els = string.match(regex) mod = send(callback.to_sym, els[:a], els[:b], index) "#{els[:prefix]}#{mod}" else string end end end ``` El texto como cadena de caracteres se simboliza como $a$. El separador hace un corte que da lugar a $a \land b$. La separación solo es posible si $a$ y $b$ coinciden con la regla de captura determinada por el usuario. Esto es un «evento» que desata una retrollamada para procesar la captura de $a \land b$ como argumentos independientes. Además, esta retrollamada cuenta con un tercer argumento `i`, la cual indica el número de índice de cada coincidencia de la condición $a \land b$. Esto es útil para establecer relaciones entre coincidencias que no están presentes en el texto crudo. Una prueba que convierte cualquier marca `v#Versalita` en versalita como `<span class="smallcaps" style="text-transform:lowercase">Versalita</span>` ```ruby=+ def to_smallcaps(a, b, i) "<span class=\"smallcaps\" style=\"text-transform:lowercase\">#{b}</span>" end ``` Como la retrollamada solo se activa si acontece $a \land b$, las retrollamadas siempre cuentan con tres argumentos para $a$, $b$ y el índice: `a, b, i`. Para el caso de las versalitas, las regla de corte de `a` siempre coincidirá con `v`, mientras que la condición de `b` siempre coincidirá con cualquier letra, número, tipo de guion o un símbolo de evento. Entonces, $a$ nos permite tener un significado y, con ello, una conversión a versalitas. Cada que haya coincidencia, con `v` se puede determinar que su modificación será una versalita. Ojo que $a = v$ es arbitrario, bien pudo haer sido $a = sc$ para `sc#Versalita` o $a = blablablá$ para `blablablá#Versalita` y así obtener una versalita. Otra prueba de marcado será con cualquier `#frances` que vaya de `Una línea #frances` a `<p class="french">Una línea</p>` ```ruby=+ def to_french_paragraph(a, b, i) a = a.strip b = b.gsub('frances', '') "<p class=\"french\">#{a}</p>#{b}" end ``` En las reglas de corte se indicará que del lado izquierdo se capturará cualquier caracter hasta el inicio de una línea y del lado derecho, además de `frances`, se capturará cualquier espacio o tabulador antes del fin de la línea. En este siguiente prueba se usará el argumento `i` para añadir numeración a las figuras a partir de la marca `#fig`. ```ruby=+ def numerate_figure(a, b, i) figure = "Figura #{i + 1}. " "#{a}#{figure}" end ``` La condición de $a$ será $a = ![$, que es la sintaxis para una imagen en Markdown, mientras que la regla de corte $b$ será $b = fig$. El lado $b$ le da significado al corte, pero en el procesamiento se utiliza $a$, presente en el texto, e $i$, generada por esta receta. Como última prueba, se declara una retrollamada para la numeración de los tres capítulos donde a `#CHAP` más cualquier dígito se le añadirá una numeración alfabética de la forma `A, B, C`. ```ruby=+ def numerate_chapter(a, b, i) abc = ['A', 'B', 'C'] number = b.gsub(/\D/, '').to_i - 1 letter = "#{abc[number]}. " "#{a}#{letter}#{E}#{b}" end ``` La regla de corte $a$ será $a = inicio\ de\ línea + definición\ de\ encabezado 1$. La condición $b$ será $b = CHAP + dígitos$. Con $b$ se obtiene un número de índice para un conjunto `A, B, C`, que permite sustituir el índice por uno de estos caracteres. Ahora es momento de implementar los métodos, se hará según su orden de definición que en ciertas circunstancias puede ser relevante: ```ruby=+ data.each do |pad_name, pad_content| data[pad_name] = cut(data[pad_name], a: 'v', b: /[#{E}:alpha:-_]+/, callback: 'to_smallcaps') data[pad_name] = cut(data[pad_name], a: /^.+/, b: /frances[\s]*$/, callback: 'to_french_paragraph') data[pad_name] = cut(data[pad_name], a: /^\!\[/, b: /fig/, callback: 'numerate_figure') data[pad_name] = cut(data[pad_name], a: /^\#\s+/, b: /CHAP\d+/, callback: 'numerate_chapter') end ``` Esta gestión de marcado permite usar otros métodos como argumentos y no solo cadena de caracteres o [expresiones regulares](https://es.wikipedia.org/wiki/Expresi%C3%B3n_regular). Cabe la posibilidad de hacer retrollamadas constantes hasta que cierta condición se cumpla, por lo que es posible la modificación de $a \land b$ como [gramática libre de contexto](https://pad.programando.li/jG4j2oXsQdWyt0qIiHsSAg). ## Unas pruebas con constantes Según [Jesus Castellos](https://www.rubyguides.com/2017/07/ruby-constants/), las constantes en Ruby son: > A constant is a type of variable which always starts with a capital letter. They can only be defined outside of methods, unless you use metaprogramming. > Constants are used for values that aren’t supposed to change, but Ruby doesn’t prevent you from changing them. Las constantes nos permiten tener una lógica de datos distinta a la lógica de categorización en un texto, ya que nos permite establecer equivalencias. Nuestras primeras constantes establecen equivalencias con los metadatos definidos en esta receta: ```ruby=+ ACKNOWLEDGEMENTS = META[:titles][:acknowledgements] ACRONYMS = META[:titles][:acronyms] BIB = META[:titles][:bib] BIB_DB = META[:bib][:db] BIB_DOWNLOAD = META[:bib][:download] BIB_QUERY = META[:bib][:query] BLOG = META[:contact][:blog] BZ2 = META[:dl][:bz2] CHAP1 = META[:titles][:chap1] CHAP2 = META[:titles][:chap2] CHAP3 = META[:titles][:chap3] CONCLUSION = META[:titles][:conclusion] DESCRIPTION = META[:description] DOCX = META[:research][:docx] EMAIL = META[:contact][:email] EPUB = META[:research][:epub] ESSAY_EN = META[:titles][:essay_en] ESSAY_EN_URL = META[:misc][:essay_en] ESSAY_ES = META[:titles][:essay_es] ESSAY_ES_URL = META[:misc][:essay_es] GITLAB = META[:repo][:gitlab] GLOSSARY = META[:titles][:glossary] GZ = META[:dl][:gz] INTRO = META[:titles][:intro] LANG = META[:lang] LICENSE = META[:license][:acronym] LICENSE_NAME = META[:license][:name] LICENSE_URL = META[:license][:url] MOBI = META[:research][:mobi] OXACAB = META[:repo][:oxacab] PDF = META[:research][:pdf] R1_EN = META[:misc][:report1_en] R1_ES = META[:misc][:report1_es] R2_EN = META[:misc][:report2_en] R2_ES = META[:misc][:report2_es] REPORT1_EN = META[:titles][:report1_en] REPORT1_ES = META[:titles][:report1_es] REPORT2_EN = META[:titles][:report2_en] REPORT2_ES = META[:titles][:report2_es] SUBTITLE = META[:subtitle] TAGS = META[:tags] TAR = META[:dl][:tar] TITLE = META[:title] TODO_LIST = META[:titles][:todo_list] WEB = META[:research][:html] XML = META[:research][:icml] ZIP = META[:dl][:zip] ``` Las constantes pueden tener cualquier tipo de dato, incluyendo aquellos que son resultado de un método. Por eso es posible tener constantes para tener la fecha y la marca temporal de cada vez que esta receta se mande a cocer: ```ruby=+ DATE = puts_date T = puts_timestamp ``` Método que coloca el valor de una constante a partir de una cadena de texto ```ruby=+ def puts_value_from(string) if string[0].ord != 96 pre = string[0] key = string[2..-1] val = Object.const_defined?(key) ? Object.const_get(key) : nil val ? pre + val : string else string end end ``` Método que reemplaza contenido con constantes en un pad ```ruby=+ def replace_content_of(pad) pad = META[:pads].has_value?(pad) ? obtain_content_from(pad) : pad pad.gsub(/.#[A-Z0-9_]+/) { |match| puts_value_from(match) } end ``` Una vez declarados los métodos, se implementa el intercambio entre las constantes y sus valores: ```ruby=+ data.each do |pad_name, pad_content| data[pad_name] = replace_content_of(data[pad_name]) end ``` La sintaxis de las constantes a reemplazar empiezan con `#`, por ejemplo, `#TITLE`. El reemplazo de la constante por su valor solo es efectivo si esta no está escrita en una línea de código. Por eso es que `#TITLE` es la declaración de una constante en una línea de código que no es reemplazada por su valor. Pruebas de reemplazos: * Datos como el metadato `#TITLE` se reemplazaría a: «*#TITLE*». * Resultados de métodos como `#DATE` también se reemplazarían: «#DATE». * Constantes no declaradas como `#NADA` no serían reemplazadas: «#NADA». ## La automatización con Pandoc Una vez terminada la edición, nos ocupamos ahora del proceso de publicación definiendo el método que implementa Pandoc. ```ruby=+ require 'pandoc-ruby' def convert(from: false, to: false, prefix: '', suffix: '', arguments: '--eol=native') markdown = from file_format = to from_md = "#{prefix}#{markdown}#{suffix}" with_args = arguments PandocRuby.new(from_md, with_args).send("to_#{file_format}") end ``` El método `convert` convertirá del contenido en v#MD a diversos formatos estipulados a continuación. De manera opcional se puede indicar un prefijo de datos para añadir texto antes del texto del contenido en Markdown. También es posible añadir sufijo de datos, además de argumentos para procesos de publicación específicos. ## La multipublicación en Git Al fin algunas metáforas familiares... _[Método para generación de directorios (carpetas)](https://pad.programando.li/ruweb:cli:mkdir/download). Generación de directorios ```ruby=+ mkdir('public/bib', 'public/research', 'public/misc', 'public/src/raw', 'public/src/cooked') ``` Guardado y publicación del index ```ruby=+ index_in_markdown = data[:index] index_content = convert(from: index_in_markdown, to: 'html') File.write("public/index.html", index_content) ``` Publicación de ficheros (archivos) MD crudos ```ruby=+ raw_data.each do |pad_name, pad_content| file = "public/src/raw/#{pad_name}.md" File.write(file, pad_content) end ``` Publicación de ficheros (archivos) MD cocidos ```ruby=+ data.each do |pad_name, pad_content| file = "public/src/cooked/#{pad_name}.md" File.write(file, pad_content) end ``` Generación de metadatos de publicación ```ruby=+ def puts_meta_template(title) template = <<-'EOS' --- lang: es pagetitle: "#title" --- EOS template.gsub('#title', title) end ``` Publicación de anexos ```ruby=+ META[:misc].each do |pad_name, file_path| metadata = puts_meta_template(META[:titles][pad_name]) markdown = data[pad_name] file = "public/#{file_path}" content = convert(from: markdown, to: 'html', prefix: metadata, arguments: '--standalone') File.write(file, content) end ``` Publicación de la investigación en múltiples formatos ```ruby=+ META[:research].each do |format, file_path| metadata = puts_meta_template(META[:title]) markdown = data[:creador_creado] file = "public/#{file_path}" case format when :mobi epub = File.basename(EPUB) Dir.chdir('public/research') system("kindlegen #{epub}") else content = convert(from: markdown, to: format.to_s, prefix: metadata, arguments: '--standalone') File.write(file, content) end end ``` La producción del formato propietario es lo último que hace, porque así fue definido en los metadatos, por eso es posible cambiar de directorio, una cuestión que puede resultar problemática al momento de hacer operaciones con directorios y ficheros. Aquí termina cocción de esta receta con v#RuWEB. ==TODO== Expicación de cómo mandar a cocer. Si se realizó en una pipa que trabaja en el repositorio Git de esta investigación, en este momento toda la información ha sido guardada y los datos ya se encuentran disponibles públicamente en [el texto cocido](https://nikazhenya.gitlab.io/maestria-investigacion/misc/reporte2.html?v=1619459632) de esta receta. ## El resultado Con todas estas etapas de edición se obtuvieron 37 ficheros, 7 publicaciones, 4 formatos de salida, 2 reportes, 1 ensayo, 1 sitio _web_ y 1 libro en diversos formatos, para impresión o lectura en digital, a partir de 1 formato de entrada y usando procesos automatizados con _software_ libre. Nosotros no modificamos __ni creamos__ ningúna carpeta, archivo o libro, pero sin duda produjimos este «árbol» de directorios a partir de esta receta: ![Árbol de directorios generado automáticamente.](https://i.imgur.com/xYtM6lN.png) El proceso de producción escrito en Markdown y programado en Ruby toma entre ~30--90 s en producirse, y si se uso Git, también de autoguardarse. El flujo se puede inspeccionar en diferentes temporalidades: * Segundos o minutos en el pad. * Horas o días en los _commit_ de Git. * Semanas, años o ediciones en las ramas de Git. No se requirieron los programas necesarios para publicar ni se empleó la terminal. El proceso puede hacerse online pero también puede adaptarse para trabajar en una red local de una comunidad, escuela o universidad. Una [maquinaria de publicación](https://pad.programando.li/s/qTK4mA7Ys) que no es una caja negra, sino en pos de la cultura, el _software_ y la edición libres. Este reporte describe cómo está rehecha la publicación de la investigación. Pero al mismo tiempo, cuando el reporte se ejecuta, hace lo que describe: publica la investigación. En un solo documento está el programa y su documentación. Pero quizá no solo eso... En _My Mother Was a Computer_ (2005), Katherine Hayles nos indica: > I claim that theories about speech, writing, and code as represented by these sources are fraught with presuppositions, premises, and implications, in effect constituting what, for lack of a better term, I call “worldviews.” > The worldviews of speech, writing, and code are inextricably entwined with the technological conditions enveloping the theorists that developed these ideas, the philosophical, linguistic, and scientific traditions in which they claimed lineage, and the purposes toward which they wanted their work to contribute. En está [maquinaria de escritura](https://pad.programando.li/s/SkN7FSHoP) y de publicación, ¿se produjo un solo texto donde están los tres “worldviews” del discurso, escritura y código? ¿Es posible escribir de otra manera donde no esté tan presente la «división» del Markdown en bloques de código ejecutables y bloques no ejecutables? ¿Es posible que todos los bloques, sin importar su sintaxis, puedan ser ejecutables? ## Tareas pendientes - [ ] Terminar redacción ---de presentación a artículo---. - [x] Exportar al resto de los formatos. - [x] Push después de pipa. - [ ] Probar con marcado: - [ ] Estilos de párrafos ---p. ej., `.sin-sangria`, `.espacio-arriba1`, `#id`---. - [x] Numeración de figuras. - [x] Numeración de encabezados en capítulos. - [ ] Uso de marca delimitadora. - [ ] Uso de método como argumento de `cut`. - [ ] Añadir diseño a las publicaciones. - [ ] Implementar Zotero para adición de referencias y bibliografía. - [ ] v#RuWEB ejecutable en intérprete de Ruby en línea.