mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-22 16:56:21 +00:00
cambiar el archivo y metadatos
This commit is contained in:
parent
cbe46babdc
commit
9573776b61
6 changed files with 91 additions and 14 deletions
|
@ -1,39 +1,84 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
|
require 'jekyll/utils'
|
||||||
|
|
||||||
module Sutty
|
module Sutty
|
||||||
module Models
|
module Models
|
||||||
# Un post
|
# Un post
|
||||||
class Post
|
class Post
|
||||||
attr_accessor :content, :front_matter
|
attr_accessor :content, :front_matter
|
||||||
attr_reader :post, :site
|
attr_reader :post, :site, :errors
|
||||||
|
|
||||||
REJECT_FROM_DATA = %w[excerpt slug draft date ext].freeze
|
REJECT_FROM_DATA = %w[excerpt slug draft date ext].freeze
|
||||||
|
|
||||||
def initialize(site, post = nil)
|
def initialize(site, post = nil, front_matter = {})
|
||||||
@site = site
|
@site = site
|
||||||
@post = post
|
@post = post
|
||||||
|
@errors = []
|
||||||
|
@front_matter = front_matter
|
||||||
|
|
||||||
|
load_data!
|
||||||
end
|
end
|
||||||
|
|
||||||
def new?
|
def new?
|
||||||
!@post.is_a? Jekyll::Document
|
!@post.is_a? ::Jekyll::Document
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Guarda los cambios
|
||||||
def save
|
def save
|
||||||
front_matter_from_data!
|
merge_data_with_front_matter!
|
||||||
clean_content!
|
clean_content!
|
||||||
|
|
||||||
return unless write.zero?
|
return unless write
|
||||||
|
return unless detect_file_rename!
|
||||||
|
|
||||||
|
# Vuelve a leer el post para tomar los cambios
|
||||||
@post.read
|
@post.read
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def front_matter_from_data!
|
# Cambiar el nombre del archivo si cambió el título o la fecha.
|
||||||
@front_matter ||= @post.data.reject do |key, _|
|
# 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, _|
|
||||||
REJECT_FROM_DATA.include? key
|
REJECT_FROM_DATA.include? key
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -43,8 +88,9 @@ module Sutty
|
||||||
@content = @content.delete("\r")
|
@content = @content.delete("\r")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Guarda los cambios en el archivo destino
|
||||||
def write
|
def write
|
||||||
File.open(@post.path, File::RDWR | File::CREAT, 0o640) do |f|
|
r = File.open(@post.path, File::RDWR | File::CREAT, 0o640) do |f|
|
||||||
# Bloquear el archivo para que no sea accedido por otro
|
# Bloquear el archivo para que no sea accedido por otro
|
||||||
# proceso u otra editora
|
# proceso u otra editora
|
||||||
f.flock(File::LOCK_EX)
|
f.flock(File::LOCK_EX)
|
||||||
|
@ -59,10 +105,15 @@ module Sutty
|
||||||
f.flush
|
f.flush
|
||||||
f.truncate(f.pos)
|
f.truncate(f.pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return true if r.zero?
|
||||||
|
|
||||||
|
@errors << 'No se pudo escribir el archivo'
|
||||||
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def full_content
|
def full_content
|
||||||
"#{@front_matter.to_yaml}---\n\n#{@content}"
|
"#{@data.to_yaml}---\n\n#{@content}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,12 +47,19 @@ module Sutty
|
||||||
end
|
end
|
||||||
|
|
||||||
post do
|
post do
|
||||||
post = Sutty::Models::Post.new(@site, @post)
|
front_matter = {
|
||||||
|
tags: params[:post][:tags].split(',').map(&:strip),
|
||||||
|
categories: params[:post][:categories].split(',').map(&:strip),
|
||||||
|
title: params[:post][:title],
|
||||||
|
date: Time.new(params[:post][:date])
|
||||||
|
}
|
||||||
|
|
||||||
|
post = Sutty::Models::Post.new(@site, @post, front_matter)
|
||||||
post.content = params[:post][:content]
|
post.content = params[:post][:content]
|
||||||
|
|
||||||
if post.save
|
if post.save
|
||||||
flash[:success] = 'Artículo guardado con éxito'
|
flash[:success] = 'Artículo guardado con éxito'
|
||||||
redirect to("/sites/#{@site.name}/posts/#{@post.basename}")
|
redirect to("/sites/#{@site.name}/posts/#{post.post.basename}")
|
||||||
else
|
else
|
||||||
flash[:error] = 'Hubo un error al guardar el artículo'
|
flash[:error] = 'Hubo un error al guardar el artículo'
|
||||||
redirect back
|
redirect back
|
||||||
|
|
|
@ -29,3 +29,8 @@ body {
|
||||||
line-height: $footer-height;
|
line-height: $footer-height;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea.post-content {
|
||||||
|
min-height: 80vh;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
.background-cover{background:url(/assets/img/background.jpg) no-repeat center center fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover}.full-height{height:calc(100vh - 60px)}html{position:relative;min-height:100%}body{margin-bottom:60px}.footer{position:absolute;bottom:0;width:100%;height:60px;line-height:60px;text-align:center}
|
.background-cover{background:url(/assets/img/background.jpg) no-repeat center center fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover}.full-height{height:calc(100vh - 60px)}html{position:relative;min-height:100%}body{margin-bottom:60px}.footer{position:absolute;bottom:0;width:100%;height:60px;line-height:60px;text-align:center}textarea.post-content{min-height:80vh;font-family:monospace}
|
||||||
/*# sourceMappingURL=sutty.css.map */
|
/*# sourceMappingURL=sutty.css.map */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"mappings": "AAEA,iBAAkB,CAChB,UAAU,CAAE,6DAA6D,CACzE,uBAAuB,CAAE,KAAK,CAC9B,oBAAoB,CAAE,KAAK,CAC3B,kBAAkB,CAAE,KAAK,CACzB,eAAe,CAAE,KAAK,CAGxB,YAAa,CACX,MAAM,CAAE,kBAA+B,CAGzC,IAAK,CACH,QAAQ,CAAE,QAAQ,CAClB,UAAU,CAAE,IAAI,CAGlB,IAAK,CACH,aAAa,CApBC,IAAI,CAuBpB,OAAQ,CACN,QAAQ,CAAE,QAAQ,CAClB,MAAM,CAAE,CAAC,CACT,KAAK,CAAE,IAAI,CACX,MAAM,CA3BQ,IAAI,CA4BlB,WAAW,CA5BG,IAAI,CA6BlB,UAAU,CAAE,MAAM",
|
"mappings": "AAEA,iBAAkB,CAChB,UAAU,CAAE,6DAA6D,CACzE,uBAAuB,CAAE,KAAK,CAC9B,oBAAoB,CAAE,KAAK,CAC3B,kBAAkB,CAAE,KAAK,CACzB,eAAe,CAAE,KAAK,CAGxB,YAAa,CACX,MAAM,CAAE,kBAA+B,CAGzC,IAAK,CACH,QAAQ,CAAE,QAAQ,CAClB,UAAU,CAAE,IAAI,CAGlB,IAAK,CACH,aAAa,CApBC,IAAI,CAuBpB,OAAQ,CACN,QAAQ,CAAE,QAAQ,CAClB,MAAM,CAAE,CAAC,CACT,KAAK,CAAE,IAAI,CACX,MAAM,CA3BQ,IAAI,CA4BlB,WAAW,CA5BG,IAAI,CA6BlB,UAAU,CAAE,MAAM,CAGpB,qBAAsB,CACpB,UAAU,CAAE,IAAI,CAChB,WAAW,CAAE,SAAS",
|
||||||
"sources": ["sass/sutty.scss"],
|
"sources": ["sass/sutty.scss"],
|
||||||
"names": [],
|
"names": [],
|
||||||
"file": "sutty.css"
|
"file": "sutty.css"
|
||||||
|
|
|
@ -2,5 +2,19 @@
|
||||||
.form-group
|
.form-group
|
||||||
%button.btn.btn-success{type: 'submit'} Guardar
|
%button.btn.btn-success{type: 'submit'} Guardar
|
||||||
.form-group
|
.form-group
|
||||||
%textarea.form-control{name: 'post[content]', id: 'contents', autofocus: true}
|
%textarea.form-control.post-content{name: 'post[content]', id: 'contents', autofocus: true}
|
||||||
= @post.content
|
= @post.content
|
||||||
|
.form-group
|
||||||
|
%label{for: 'date'} Fecha de publicación
|
||||||
|
%input.form-control{type: 'text', name: 'post[date]', id: 'date', value: @post.data['date']}
|
||||||
|
.form-group
|
||||||
|
%label{for: 'title'} Título
|
||||||
|
%input.form-control{type: 'text', name: 'post[title]', id: 'title', value: @post.data['title']}
|
||||||
|
.form-group
|
||||||
|
%label{for: 'tags'} Etiquetas
|
||||||
|
%input.form-control{type: 'text', name: 'post[tags]', id: 'tags', value: @post.data['tags'].join(',')}
|
||||||
|
%small.form-text.text-muted Separadas por comas
|
||||||
|
.form-group
|
||||||
|
%label{for: 'categories'} Categorías
|
||||||
|
%input.form-control{type: 'text', name: 'post[categories]', id: 'categories', value: @post.data['categories'].join(',')}
|
||||||
|
%small.form-text.text-muted Separadas por comas
|
||||||
|
|
Loading…
Reference in a new issue