5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-23 03:46:23 +00:00
panel/lib/sutty/models/post.rb

121 lines
2.8 KiB
Ruby
Raw Permalink Normal View History

2017-10-05 19:42:32 +00:00
# frozen_string_literal: true
require 'yaml'
2017-10-09 22:29:31 +00:00
require 'jekyll/utils'
2017-10-05 19:42:32 +00:00
module Sutty
module Models
# Un post
class Post
attr_accessor :content, :front_matter
2017-10-09 22:29:31 +00:00
attr_reader :post, :site, :errors
2017-10-05 19:42:32 +00:00
REJECT_FROM_DATA = %w[excerpt slug draft date ext].freeze
2017-10-09 22:29:31 +00:00
def initialize(site, post = nil, front_matter = {})
2017-10-05 19:42:32 +00:00
@site = site
@post = post
2017-10-09 22:29:31 +00:00
@errors = []
@front_matter = front_matter
load_data!
2017-10-05 19:42:32 +00:00
end
def new?
2017-10-09 22:29:31 +00:00
!@post.is_a? ::Jekyll::Document
2017-10-05 19:42:32 +00:00
end
2017-10-09 22:29:31 +00:00
# Guarda los cambios
2017-10-05 19:42:32 +00:00
def save
2017-10-09 22:29:31 +00:00
merge_data_with_front_matter!
2017-10-05 19:42:32 +00:00
clean_content!
2017-10-09 22:29:31 +00:00
return unless write
return unless detect_file_rename!
2017-10-05 19:42:32 +00:00
2017-10-09 22:29:31 +00:00
# Vuelve a leer el post para tomar los cambios
2017-10-05 19:42:32 +00:00
@post.read
true
end
private
2017-10-09 22:29:31 +00:00
# Cambiar el nombre del archivo si cambió el título o la fecha.
# Como Jekyll no tiene métodos para modificar un Document, lo
# engañamos eliminando la instancia de @post y recargando otra.
def detect_file_rename!
basename = basename_from_front_matter
path = File.join(File.dirname(@post.path), basename)
return true if basename == @post.basename
if File.exist? path
@errors << 'El archivo destino ya existe'
return
end
FileUtils.mv @post.path, path
replace_post! path
end
def replace_post!(path)
opts = { site: @site, collection: @site.posts }
@site.posts.docs.delete @post
@post = ::Jekyll::Document.new(path, opts)
@site.posts.docs << @post
@site.posts.docs.sort!
end
def basename_from_front_matter
date = @front_matter[:date].strftime('%F')
title = ::Jekyll::Utils.slugify(@front_matter[:title])
"#{date}-#{title}.markdown"
end
def merge_data_with_front_matter!
@data.merge! Hash[@front_matter.map { |k, v| [k.to_s, v] }]
end
def load_data!
@data ||= @post.data.reject do |key, _|
2017-10-05 19:42:32 +00:00
REJECT_FROM_DATA.include? key
end
end
# Aplica limpiezas básicas del contenido
def clean_content!
@content = @content.delete("\r")
end
2017-10-09 22:29:31 +00:00
# Guarda los cambios en el archivo destino
2017-10-05 19:42:32 +00:00
def write
2017-10-09 22:29:31 +00:00
r = File.open(@post.path, File::RDWR | File::CREAT, 0o640) do |f|
2017-10-05 19:42:32 +00:00
# Bloquear el archivo para que no sea accedido por otro
# proceso u otra editora
f.flock(File::LOCK_EX)
# Empezar por el principio
f.rewind
# Escribir
f.write(full_content)
# Eliminar el resto
f.flush
f.truncate(f.pos)
end
2017-10-09 22:29:31 +00:00
return true if r.zero?
@errors << 'No se pudo escribir el archivo'
false
2017-10-05 19:42:32 +00:00
end
def full_content
2017-10-09 22:29:31 +00:00
"#{@data.to_yaml}---\n\n#{@content}"
2017-10-05 19:42:32 +00:00
end
end
end
end