mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-15 06:41:42 +00:00
la estructura de un artículo
This commit is contained in:
parent
b4877baa47
commit
3b46600ed5
7 changed files with 161 additions and 0 deletions
4
app/models/layout.rb
Normal file
4
app/models/layout.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Una plantilla agrupa metadatos que va a tener un artículo
|
||||||
|
Layout = Struct.new(:site, :name, :metadata, keyword_init: true)
|
9
app/models/metadata_array.rb
Normal file
9
app/models/metadata_array.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Una lista de valores
|
||||||
|
class MetadataArray < MetadataTemplate
|
||||||
|
# El valor por defecto es una array vacía
|
||||||
|
def default_value
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
8
app/models/metadata_factory.rb
Normal file
8
app/models/metadata_factory.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Devuelve metadatos de cierto tipo
|
||||||
|
class MetadataFactory
|
||||||
|
def self.build(**args)
|
||||||
|
"Metadata#{args[:type].camelcase}".constantize.new(args)
|
||||||
|
end
|
||||||
|
end
|
13
app/models/metadata_image.rb
Normal file
13
app/models/metadata_image.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Define un campo de imagen
|
||||||
|
class MetadataImage < MetadataTemplate
|
||||||
|
# Una ruta vacía a la imagen con una descripción vacía
|
||||||
|
def default_value
|
||||||
|
{ path: '', description: '' }
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty?
|
||||||
|
value == default_value
|
||||||
|
end
|
||||||
|
end
|
9
app/models/metadata_string.rb
Normal file
9
app/models/metadata_string.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Un campo de texto
|
||||||
|
class MetadataString < MetadataTemplate
|
||||||
|
# Una string vacía
|
||||||
|
def default_value
|
||||||
|
''
|
||||||
|
end
|
||||||
|
end
|
22
app/models/metadata_template.rb
Normal file
22
app/models/metadata_template.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Representa la plantilla de un campo en los metadatos del artículo
|
||||||
|
MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
|
:value, :help, :required,
|
||||||
|
keyword_init: true) do
|
||||||
|
# El valor por defecto
|
||||||
|
def default_value
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Valores posibles, busca todos los valores actuales en otros
|
||||||
|
# artículos del mismo sitio
|
||||||
|
def values
|
||||||
|
site.everything_of(name.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Valor actual o por defecto
|
||||||
|
def value
|
||||||
|
super || document.data.dig(name.to_s, default_value)
|
||||||
|
end
|
||||||
|
end
|
96
doc/posts.md
Normal file
96
doc/posts.md
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# Posts
|
||||||
|
|
||||||
|
Los posts no corresponden con un modelo en la base de datos, porque se
|
||||||
|
nos va a complicar sincronizar los datos con el repositorio.
|
||||||
|
|
||||||
|
## Jekyll
|
||||||
|
|
||||||
|
Como en Jekyll, los artículos son archivos con el siguiente formato:
|
||||||
|
|
||||||
|
* Ubicación: _lang/ en lugar de guardar los archivos en _posts, usamos
|
||||||
|
i18n y guardamos cada uno en el directorio de su propio idioma.
|
||||||
|
|
||||||
|
* Nombre: el nombre del archivo contiene la fecha en formato aaaa-mm-dd,
|
||||||
|
seguidos de un guión, el título en minúsculas y con los espacios
|
||||||
|
convertidos en guiones. La extensión es .markdown.
|
||||||
|
|
||||||
|
Esto también funciona como identificador único.
|
||||||
|
|
||||||
|
* Metadatos: Los metadatos del artículo se vuelcan en formato YAML al
|
||||||
|
principio del archivo, el bloque comienza y termina con tres guiones
|
||||||
|
("---") en líneas separadas
|
||||||
|
|
||||||
|
* Contenido: El contenido del artículo va a continuación de los
|
||||||
|
metadatos, en formato Markdown
|
||||||
|
|
||||||
|
## I18n
|
||||||
|
|
||||||
|
Todos los artículos están listos para ser traducidos. Esto ya no es
|
||||||
|
opcional como antes porque nos genera muchos casos especiales.
|
||||||
|
|
||||||
|
La i18n incluye una lista de los nombres de archivo que identifican a
|
||||||
|
los posts en otros idiomas, para intervincularlos.
|
||||||
|
|
||||||
|
## Plantillas de metadatos
|
||||||
|
|
||||||
|
Todos los campos de la sección de metadatos son plantillas, incluso para
|
||||||
|
los artículos, hay una plantilla por defecto con los campos más comunes.
|
||||||
|
|
||||||
|
Esto nos permite adaptar distintos tipos de artículos y unificar todo el
|
||||||
|
desarrollo en una sola lógica.
|
||||||
|
|
||||||
|
El sitio contiene una descripción de todas las plantillas. Cuando se
|
||||||
|
crea un artículo del tipo correspondiente con la plantilla, el artículo
|
||||||
|
hereda todas las plantillas como atributos y valida la presencia de los
|
||||||
|
obligatorios y los tipos de datos incorporados.
|
||||||
|
|
||||||
|
## Archivos
|
||||||
|
|
||||||
|
El nombre de la plantilla de metadatos corresponde con una plantilla
|
||||||
|
HTML:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
_data/templates/post.yml
|
||||||
|
_layouts/post.html
|
||||||
|
```
|
||||||
|
|
||||||
|
Al crear el artículo, el metadato `layout:` se completa con el nombre de
|
||||||
|
la plantilla. Todavía no tenemos un método para cambiar un artículo de
|
||||||
|
plantilla, ya que requiriría recargar todos los campos.
|
||||||
|
|
||||||
|
## Implementación
|
||||||
|
|
||||||
|
La clase `MetadataTemplate` representa los valores posibles de un
|
||||||
|
metadato abstracto. Cada tipo de valor específico tiene su
|
||||||
|
`MetadataType` donde `Type` es el tipo de metadato. Esto
|
||||||
|
permite que cada tipo sepa como cargar sus valores por defecto y demás.
|
||||||
|
|
||||||
|
La clase `Template` contiene un hash de `{ campo: MetadataTemplate }`.
|
||||||
|
Su nombre es el nombre de la plantilla.
|
||||||
|
|
||||||
|
`Site#templates` contiene un hash de `{ nombre: Template }` para
|
||||||
|
búsqueda rápida.
|
||||||
|
|
||||||
|
`Post#template` es el `Site#templates[:template]` correspondiente.
|
||||||
|
|
||||||
|
`Post` es un tipo de `OpenStruct` que valida los valores contra las
|
||||||
|
plantillas de `Post#template`. Además, puede obtener valores por
|
||||||
|
defecto. Para esto, se lo construye con el sitio y plantilla. A partir
|
||||||
|
de esto se generan los `MetadataType` correspondientes, que son
|
||||||
|
los capaces de generar sus propios valores por defecto.
|
||||||
|
|
||||||
|
De dónde obtienen los valores actuales los `MetadataType`?
|
||||||
|
|
||||||
|
Cada atributo es una instancia de `PostMetadataType`.
|
||||||
|
|
||||||
|
`Post#title` trae el título desde los metadatos leídos o el título por
|
||||||
|
defecto. `Post#title.values` trae los valores posibles.
|
||||||
|
|
||||||
|
Los `Post` se generan desde `Site#posts` que es una relación, al estilo
|
||||||
|
ActiveRecord.
|
||||||
|
|
||||||
|
Al instanciar un `Post`, se pasan el sitio y la plantilla por defecto.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
* Leer artículos a medida que se los necesita en lugar de todos juntos.
|
Loading…
Reference in a new issue