mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-24 15:46:23 +00:00
This commit is contained in:
parent
805225a093
commit
915ba0761f
18 changed files with 100 additions and 64 deletions
|
@ -2,23 +2,17 @@
|
||||||
|
|
||||||
# Una lista de valores
|
# Una lista de valores
|
||||||
class MetadataArray < MetadataTemplate
|
class MetadataArray < MetadataTemplate
|
||||||
|
include Metadata::IndexableConcern
|
||||||
|
include Metadata::AlwaysPublicConcern
|
||||||
|
|
||||||
# El valor por defecto es una array vacía
|
# El valor por defecto es una array vacía
|
||||||
|
#
|
||||||
|
# @return [Array]
|
||||||
def default_value
|
def default_value
|
||||||
super || []
|
super || []
|
||||||
end
|
end
|
||||||
|
|
||||||
# Los Arrays no se pueden cifrar todavía
|
# @return [String]
|
||||||
# TODO: Cifrar y decifrar arrays
|
|
||||||
def private?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
# Solo los datos públicos se indexan, aunque MetadataArray no se cifra
|
|
||||||
# aun, dejamos esto preparado para la posteridad.
|
|
||||||
def indexable?
|
|
||||||
true && !private?
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
value.join(', ')
|
value.join(', ')
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,26 +3,29 @@
|
||||||
# Se encarga del contenido del artículo y quizás otros campos que
|
# Se encarga del contenido del artículo y quizás otros campos que
|
||||||
# requieran texto largo.
|
# requieran texto largo.
|
||||||
class MetadataContent < MetadataTemplate
|
class MetadataContent < MetadataTemplate
|
||||||
|
include Metadata::ContentConcern
|
||||||
|
include Metatada::IndexableConcern
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def default_value
|
def default_value
|
||||||
super || ''
|
super || ''
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def value
|
def value
|
||||||
self[:value] || legacy_content || default_value
|
self[:value] || legacy_content || default_value
|
||||||
end
|
end
|
||||||
|
|
||||||
def front_matter?
|
# Trae el contenido desde el Post
|
||||||
false
|
#
|
||||||
end
|
# @return [String]
|
||||||
|
|
||||||
def document_value
|
def document_value
|
||||||
document.content
|
document.content
|
||||||
end
|
end
|
||||||
|
|
||||||
def indexable?
|
# Eliminar HTML
|
||||||
true && !private?
|
#
|
||||||
end
|
# @return [String]
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
sanitizer.sanitize value, tags: [], attributes: []
|
sanitizer.sanitize value, tags: [], attributes: []
|
||||||
end
|
end
|
||||||
|
@ -30,6 +33,8 @@ class MetadataContent < MetadataTemplate
|
||||||
private
|
private
|
||||||
|
|
||||||
# Detectar si el contenido estaba en Markdown y pasarlo a HTML
|
# Detectar si el contenido estaba en Markdown y pasarlo a HTML
|
||||||
|
#
|
||||||
|
# @return [String,nil]
|
||||||
def legacy_content
|
def legacy_content
|
||||||
return unless document_value
|
return unless document_value
|
||||||
return document_value if /^\s*</ =~ document_value
|
return document_value if /^\s*</ =~ document_value
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MetadataDate < MetadataTemplate
|
class MetadataDate < MetadataTemplate
|
||||||
|
include Metadata::NonIndexableConcern
|
||||||
|
|
||||||
|
# La fecha de hoy
|
||||||
|
#
|
||||||
|
# @return [Date]
|
||||||
def default_value
|
def default_value
|
||||||
Date.today
|
Date.today
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#
|
#
|
||||||
# TODO: Deprecar
|
# TODO: Deprecar
|
||||||
class MetadataEncryptedText < MetadataText
|
class MetadataEncryptedText < MetadataText
|
||||||
|
include Metadata::NonIndexableConcern
|
||||||
|
|
||||||
def private?
|
def private?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
# Define un campo de coordenadas geográficas
|
# Define un campo de coordenadas geográficas
|
||||||
class MetadataGeo < MetadataTemplate
|
class MetadataGeo < MetadataTemplate
|
||||||
|
include Metadata::IndexableConcern
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
super || { 'lat' => nil, 'lng' => nil }
|
super || { 'lat' => nil, 'lng' => nil }
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
# Campos en HTML
|
# Campos en HTML
|
||||||
class MetadataHtml < MetadataContent
|
class MetadataHtml < MetadataContent
|
||||||
def front_matter?
|
include Metadata::FrontMatterConcern
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
|
# Volver a obtener el valor desde el documento
|
||||||
|
#
|
||||||
|
# @return [String,nil]
|
||||||
def document_value
|
def document_value
|
||||||
document.data[name.to_s]
|
document.data[name.to_s]
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
# Un campo de idioma
|
# Un campo de idioma
|
||||||
class MetadataLang < MetadataTemplate
|
class MetadataLang < MetadataTemplate
|
||||||
|
include Metadata::NonIndexableConcern
|
||||||
|
include Metadata::AlwaysPublicConcern
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
super || I18n.locale
|
super || I18n.locale
|
||||||
end
|
end
|
||||||
|
@ -11,10 +14,14 @@ class MetadataLang < MetadataTemplate
|
||||||
document.collection.label.to_sym
|
document.collection.label.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [Symbol]
|
||||||
def value
|
def value
|
||||||
self[:value] ||= document_value || default_value
|
self[:value] ||= document_value || default_value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Todos los locales
|
||||||
|
#
|
||||||
|
# @return [Array<Symbol>]
|
||||||
def values
|
def values
|
||||||
site.locales
|
site.locales
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,29 +1,37 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Contenido con el editor de Markdown
|
# Contenido con el editor de Markdown
|
||||||
|
#
|
||||||
|
# @todo Deprecar
|
||||||
class MetadataMarkdownContent < MetadataText
|
class MetadataMarkdownContent < MetadataText
|
||||||
|
include Metadata::ContentConcern
|
||||||
|
|
||||||
# Renderizar a HTML y sanitizar
|
# Renderizar a HTML y sanitizar
|
||||||
def to_s
|
def to_s
|
||||||
sanitize CommonMarker.render_doc(value, %i[FOOTNOTES SMART],
|
sanitize CommonMarker.render_doc(value, %i[FOOTNOTES SMART],
|
||||||
%i[table strikethrough autolink]).to_html
|
%i[table strikethrough autolink]).to_html
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def value
|
def value
|
||||||
self[:value] || document_value || default_value
|
self[:value] || document_value || default_value
|
||||||
end
|
end
|
||||||
|
|
||||||
def front_matter?
|
# Obtener el contenido desde el documento
|
||||||
false
|
#
|
||||||
end
|
|
||||||
|
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def document_value
|
def document_value
|
||||||
document.content
|
document.content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
# XXX: No sanitizamos acá porque se escapan varios símbolos de
|
# XXX: No sanitizamos acá porque se escapan varios símbolos de
|
||||||
# markdown y se eliminan autolinks. Mejor es deshabilitar la
|
# markdown y se eliminan autolinks. Mejor es deshabilitar la
|
||||||
# generación SAFE de CommonMark en la configuración del sitio.
|
# generación SAFE de CommonMark en la configuración del sitio.
|
||||||
|
#
|
||||||
|
# @param :string [String]
|
||||||
|
# @return [String]
|
||||||
def sanitize(string)
|
def sanitize(string)
|
||||||
string.tr("\r", '').unicode_normalize
|
string.tr("\r", '').unicode_normalize
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Un mapa no geográfico
|
||||||
class MetadataNonGeo < MetadataGeo; end
|
class MetadataNonGeo < MetadataGeo; end
|
||||||
|
|
|
@ -2,11 +2,18 @@
|
||||||
|
|
||||||
# Un campo numérico
|
# Un campo numérico
|
||||||
class MetadataNumber < MetadataTemplate
|
class MetadataNumber < MetadataTemplate
|
||||||
# Nada
|
include Metadata::NonIndexableConcern
|
||||||
|
|
||||||
|
# El valor por defecto desde el esquema de datos o nada
|
||||||
|
#
|
||||||
|
# @return [Integer, nil]
|
||||||
def default_value
|
def default_value
|
||||||
super || nil
|
super || nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Convertir a Integer
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
def save
|
def save
|
||||||
return true unless changed?
|
return true unless changed?
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,20 @@
|
||||||
|
|
||||||
# Un campo de orden
|
# Un campo de orden
|
||||||
class MetadataOrder < MetadataTemplate
|
class MetadataOrder < MetadataTemplate
|
||||||
|
include Metadata::NonIndexableConcern
|
||||||
|
include Metadata::AlwaysPublicConcern
|
||||||
|
|
||||||
# El valor según la posición del post en la relación ordenada por
|
# El valor según la posición del post en la relación ordenada por
|
||||||
# fecha, a fecha más alta, posición más alta
|
# fecha, a fecha más alta, posición más alta
|
||||||
|
#
|
||||||
|
# @return [Integer]
|
||||||
def default_value
|
def default_value
|
||||||
super || site.posts(lang: lang).sort_by(:date).index(post)
|
super || site.posts(lang: lang).sort_by(:date).index(post)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Convertir el valor en un entero
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
def save
|
def save
|
||||||
return true unless changed?
|
return true unless changed?
|
||||||
|
|
||||||
|
@ -15,9 +23,4 @@ class MetadataOrder < MetadataTemplate
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# El orden nunca puede ser privado
|
|
||||||
def private?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,7 @@
|
||||||
|
|
||||||
# Almacena una contraseña
|
# Almacena una contraseña
|
||||||
class MetadataPassword < MetadataString
|
class MetadataPassword < MetadataString
|
||||||
# Las contraseñas no son indexables
|
include Metadata::NonIndexableConcern
|
||||||
#
|
|
||||||
# @return [boolean]
|
|
||||||
def indexable?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
# Este campo representa el archivo donde se almacenan los datos
|
# Este campo representa el archivo donde se almacenan los datos
|
||||||
class MetadataPath < MetadataTemplate
|
class MetadataPath < MetadataTemplate
|
||||||
|
include Metadata::NonIndexableConcern
|
||||||
|
include Metadata::AlwaysPublicConcern
|
||||||
|
|
||||||
# :label en este caso es el idioma/colección
|
# :label en este caso es el idioma/colección
|
||||||
#
|
#
|
||||||
# @return [String]
|
# @return [String]
|
||||||
|
@ -22,10 +25,12 @@ class MetadataPath < MetadataTemplate
|
||||||
alias absolute value
|
alias absolute value
|
||||||
alias to_s value
|
alias to_s value
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def relative
|
def relative
|
||||||
Pathname.new(value).relative_path_from(Pathname.new(site.path)).to_s
|
Pathname.new(value).relative_path_from(Pathname.new(site.path)).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def basename
|
def basename
|
||||||
File.basename(value, ext)
|
File.basename(value, ext)
|
||||||
end
|
end
|
||||||
|
@ -35,14 +40,19 @@ class MetadataPath < MetadataTemplate
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Obtiene la extensión
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
def ext
|
def ext
|
||||||
document.data['ext'].blank? ? '.markdown' : document.data['ext']
|
document.data['ext'].blank? ? '.markdown' : document.data['ext']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def slug
|
def slug
|
||||||
post.slug.value
|
post.slug.value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def date
|
def date
|
||||||
post.date.value.strftime('%F')
|
post.date.value.strftime('%F')
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
|
|
||||||
# Este metadato permite generar rutas manuales.
|
# Este metadato permite generar rutas manuales.
|
||||||
class MetadataPermalink < MetadataString
|
class MetadataPermalink < MetadataString
|
||||||
# Los permalinks nunca pueden ser privados
|
include Metadata::AlwaysPublicConcern
|
||||||
def private?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
# Devuelve una lista de títulos y UUID de todos los posts del mismo
|
# Devuelve una lista de títulos y UUID de todos los posts del mismo
|
||||||
# idioma que el actual, para usar con input-map.js
|
# idioma que el actual, para usar con input-map.js
|
||||||
class MetadataRelatedPosts < MetadataArray
|
class MetadataRelatedPosts < MetadataArray
|
||||||
|
# @todo ¿Deberíamos indexar algo de esto?
|
||||||
|
include Metadata::NonIndexableConcern
|
||||||
|
include Metadata::AlwaysPublicConcern
|
||||||
|
|
||||||
# Genera un Hash de { title (schema) => uuid } para usar en
|
# Genera un Hash de { title (schema) => uuid } para usar en
|
||||||
# options_for_select
|
# options_for_select
|
||||||
#
|
#
|
||||||
|
@ -15,19 +19,6 @@ class MetadataRelatedPosts < MetadataArray
|
||||||
end.to_h
|
end.to_h
|
||||||
end
|
end
|
||||||
|
|
||||||
# Las relaciones nunca son privadas
|
|
||||||
def private?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def indexable?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def indexable_values
|
|
||||||
posts.where(post_id: value).pluck(:title)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Obtiene todos los posts menos el actual y opcionalmente los filtra
|
# Obtiene todos los posts menos el actual y opcionalmente los filtra
|
||||||
|
|
|
@ -23,11 +23,17 @@ require 'jekyll/utils'
|
||||||
#
|
#
|
||||||
# TODO: Transliterar tildes?
|
# TODO: Transliterar tildes?
|
||||||
class MetadataSlug < MetadataTemplate
|
class MetadataSlug < MetadataTemplate
|
||||||
|
include Metadata::AlwaysPublicConcern
|
||||||
|
include Metadata::NonIndexableConcern
|
||||||
|
|
||||||
# Trae el slug desde el título si existe o una string al azar
|
# Trae el slug desde el título si existe o una string al azar
|
||||||
def default_value
|
def default_value
|
||||||
title ? Jekyll::Utils.slugify(title, mode: site.slugify_mode) : SecureRandom.uuid
|
title ? Jekyll::Utils.slugify(title, mode: site.slugify_mode) : SecureRandom.uuid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Permite que Jekyll::Document se encargue de la generación del slug
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
def value
|
def value
|
||||||
self[:value] ||= document.data.fetch('slug', default_value)
|
self[:value] ||= document.data.fetch('slug', default_value)
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,18 +2,22 @@
|
||||||
|
|
||||||
# Un campo de texto
|
# Un campo de texto
|
||||||
class MetadataString < MetadataTemplate
|
class MetadataString < MetadataTemplate
|
||||||
|
include Metadata::IndexableConcern
|
||||||
|
|
||||||
# Una string vacía
|
# Una string vacía
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
def default_value
|
def default_value
|
||||||
super || ''
|
super || ''
|
||||||
end
|
end
|
||||||
|
|
||||||
def indexable?
|
|
||||||
true && !private?
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# No se permite HTML en las strings
|
# No se permite HTML en las strings
|
||||||
|
#
|
||||||
|
# @todo Escapar https://0xacab.org/sutty/sutty/-/issues/4101
|
||||||
|
# @param :string [String]
|
||||||
|
# @return [String]
|
||||||
def sanitize(string)
|
def sanitize(string)
|
||||||
return '' if string.blank?
|
return '' if string.blank?
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
|
|
||||||
# Asigna un identificador único al artículo
|
# Asigna un identificador único al artículo
|
||||||
class MetadataUuid < MetadataTemplate
|
class MetadataUuid < MetadataTemplate
|
||||||
|
include Metadata::AlwaysPublicConcern
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
SecureRandom.uuid
|
SecureRandom.uuid
|
||||||
end
|
end
|
||||||
|
|
||||||
def private?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue