diff --git a/Gemfile b/Gemfile index 56de71d2..b7fca068 100644 --- a/Gemfile +++ b/Gemfile @@ -52,6 +52,8 @@ gem 'hiredis' gem 'image_processing' gem 'inline_svg' gem 'jekyll' +gem 'jekyll-data', require: 'jekyll-data', + git: 'https://0xacab.org/sutty/jekyll/jekyll-data.git' gem 'mini_magick' gem 'mobility' gem 'pg' @@ -69,6 +71,12 @@ gem 'validates_hostname' gem 'webpacker' gem 'yaml_db', git: 'https://0xacab.org/sutty/yaml_db.git' +group :themes do + gem 'editorial-autogestiva-jekyll-theme', require: false + gem 'minima', require: false + gem 'sutty-jekyll-theme', require: false +end + group :development, :test do gem 'pry' # Adds support for Capybara system testing and selenium driver diff --git a/Gemfile.lock b/Gemfile.lock index 99234830..676949fd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,10 @@ +GIT + remote: https://0xacab.org/sutty/jekyll/jekyll-data.git + revision: 1ad9c175be6bbb31ae6d19cbb8dde18828af90d9 + specs: + jekyll-data (1.1.0) + jekyll (>= 3.3, < 5.0.0) + GIT remote: https://0xacab.org/sutty/reverse_markdown.git revision: 5c243096669aa77e0dc173dec8006b4c5fe07683 @@ -122,6 +129,15 @@ GEM dotenv (= 2.7.5) railties (>= 3.2, < 6.1) ed25519 (1.2.4) + editorial-autogestiva-jekyll-theme (0.1.0) + jekyll (~> 4.0) + jekyll-data (~> 1.1) + jekyll-feed (~> 0.9) + jekyll-images (~> 0.2) + jekyll-include-cache (~> 0) + jekyll-locales (~> 0.1) + jekyll-relative-urls (~> 0.0) + jekyll-seo-tag (~> 2.1) em-websocket (0.5.1) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) @@ -193,8 +209,20 @@ GEM rouge (~> 3.0) safe_yaml (~> 1.0) terminal-table (~> 1.8) + jekyll-feed (0.13.0) + jekyll (>= 3.7, < 5.0) + jekyll-images (0.2.3) + ruby-filemagic (~> 0.7) + ruby-vips (~> 2) + jekyll-include-cache (0.2.0) + jekyll (>= 3.7, < 5.0) + jekyll-locales (0.1.7) + jekyll-relative-urls (0.0.5) + jekyll (>= 3.8, < 5) jekyll-sass-converter (2.1.0) sassc (> 2.0.1, < 3.0) + jekyll-seo-tag (2.6.1) + jekyll (>= 3.3, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) kramdown (2.1.0) @@ -222,6 +250,10 @@ GEM mini_magick (4.10.1) mini_mime (1.0.2) mini_portile2 (2.4.0) + minima (2.5.1) + jekyll (>= 3.5, < 5.0) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) minitest (5.14.0) mobility (0.8.10) i18n (>= 0.6.10, < 2) @@ -326,6 +358,7 @@ GEM rubocop (>= 0.72.0) ruby-enum (0.7.2) i18n + ruby-filemagic (0.7.2) ruby-progressbar (1.10.1) ruby-vips (2.0.17) ffi (~> 1.9) @@ -362,6 +395,13 @@ GEM sqlite3 (1.4.2) sucker_punch (2.1.2) concurrent-ruby (~> 1.0) + sutty-jekyll-theme (0.1.0) + jekyll (~> 4.0) + jekyll-feed (~> 0.9) + jekyll-images (~> 0.2) + jekyll-include-cache (~> 0) + jekyll-relative-urls (~> 0.0) + jekyll-seo-tag (~> 2.1) sysexits (1.2.0) temple (0.8.2) terminal-table (1.8.0) @@ -419,6 +459,7 @@ DEPENDENCIES devise_invitable dotenv-rails ed25519 + editorial-autogestiva-jekyll-theme email_address exception_notification factory_bot_rails @@ -430,9 +471,11 @@ DEPENDENCIES inline_svg jbuilder (~> 2.5) jekyll + jekyll-data! letter_opener listen (>= 3.0.5, < 3.2) mini_magick + minima mobility pg pry @@ -454,6 +497,7 @@ DEPENDENCIES spring-watcher-listen (~> 2.0.0) sqlite3 sucker_punch + sutty-jekyll-theme terminal-table timecop turbolinks (~> 5) diff --git a/app/models/site.rb b/app/models/site.rb index d6e87b39..8a1b17cd 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -68,7 +68,7 @@ class Site < ApplicationRecord end def hostname - return @hostname if @hostname + return @hostname unless name_changed? || @hostname.blank? sub = name || I18n.t('deploys.deploy_local.ejemplo') @hostname = if sub.ends_with? '.' @@ -261,6 +261,8 @@ class Site < ApplicationRecord end def reload_jekyll! + reset + Dir.chdir(path) do @jekyll = Jekyll::Site.new(jekyll_config) end @@ -287,10 +289,13 @@ class Site < ApplicationRecord 'quiet' => true, 'excerpt_separator' => '') # No necesitamos cargar plugins en este momento - %w[plugins gems theme].each do |unneeded| + %w[plugins gems].each do |unneeded| configuration[unneeded] = [] if configuration.key? unneeded end + # Eliminar el theme si no es una gema válida + configuration.delete 'theme' unless theme_available? + # Si estamos usando nuestro propio plugin de i18n, los posts están # en "colecciones" locales.each do |i| @@ -300,6 +305,20 @@ class Site < ApplicationRecord configuration end + # Lista los nombres de las plantillas disponibles como gemas, + # tomándolas dinámicamente de las que agreguemos en el grupo :themes + # del Gemfile. + def available_themes + @available_themes ||= Bundler.load.current_dependencies.select do |gem| + gem.groups.include? :themes + end.map(&:name) + end + + # Detecta si el tema actual es una gema + def theme_available? + available_themes.include? design.gem + end + # Devuelve el dominio actual def self.domain ENV.fetch('SUTTY', 'sutty.nl') @@ -310,6 +329,12 @@ class Site < ApplicationRecord File.join(Rails.root, '_sites') end + def reset + @read = false + @layouts = nil + @layouts_struct = nil + end + private # Clona el esqueleto de Sutty para crear el sitio nuevo, no pasa nada diff --git a/db/seeds/designs.yml b/db/seeds/designs.yml index 836f0990..047ef960 100644 --- a/db/seeds/designs.yml +++ b/db/seeds/designs.yml @@ -27,6 +27,13 @@ description_en: "A design with Sutty's look & feel" description_es: 'El diseño de Sutty' license: 'https://0xacab.org/sutty/jekyll/sutty-jekyll-theme/-/blob/master/LICENSE.txt' +- name_en: 'Self-managed Book Publisher' + name_es: 'Editorial Autogestiva' + gem: 'editorial-autogestiva-jekyll-theme' + url: 'https://subelamarea.sutty.nl/' + description_en: "A theme for self-managed book publishers." + description_es: 'Una plantilla para catálogos de editoriales autogestivas.' + license: 'https://0xacab.org/sutty/jekyll/editorial-autogestiva-jekyll-theme/-/blob/master/LICENSE.txt' - name_en: 'Other themes' name_es: 'Mi propio diseño' gem: 'sutty-theme-own' diff --git a/test/models/site_test.rb b/test/models/site_test.rb index bb6a4777..c50bfd20 100644 --- a/test/models/site_test.rb +++ b/test/models/site_test.rb @@ -3,14 +3,16 @@ require 'test_helper' class SiteTest < ActiveSupport::TestCase + def site + @site ||= create :site + end + # Asegurarse que el sitio se destruye al terminar de usarlo teardown do - @site&.destroy + site&.destroy end test 'se puede crear un sitio' do - site = create :site - assert site.valid? # TODO: Mover a la validación del sitio o hacer algo similar assert File.directory?(site.path) @@ -19,78 +21,92 @@ class SiteTest < ActiveSupport::TestCase end test 'el nombre tiene que ser único' do - @site = create :site - site2 = build :site, name: @site.name + site2 = build :site, name: site.name assert_not site2.valid? end test 'el nombre del sitio puede contener subdominios' do - site = build :site, name: 'hola.chau' + @site = build :site, name: 'hola.chau' site.validate assert_not site.errors.messages[:name].present? end test 'el nombre del sitio puede terminar con punto' do - site = build :site, name: 'hola.chau.' + @site = build :site, name: 'hola.chau.' site.validate assert_not site.errors.messages[:name].present? end test 'el nombre del sitio no puede contener wildcard' do - site = build :site, name: '*.chau' + @site = build :site, name: '*.chau' site.validate assert site.errors.messages[:name].present? end test 'el nombre del sitio solo tiene letras, numeros y guiones' do - site = build :site, name: 'A_Z!' + @site = build :site, name: 'A_Z!' site.validate assert site.errors.messages[:name].present? end test 'al destruir un sitio se eliminan los archivos' do - site = create :site + @site = create :site assert site.destroy assert !File.directory?(site.path) end test 'se puede leer un sitio' do - site = create :site - assert site.valid? assert !site.posts.empty? end test 'se pueden renombrar' do - @site = create :site - path = @site.path + path = site.path - @site.update_attribute :name, SecureRandom.hex + site.update_attribute :name, SecureRandom.hex - assert_not_equal path, @site.path - assert File.directory?(@site.path) + assert_not_equal path, site.path + assert File.directory?(site.path) assert_not File.directory?(path) end test 'no se puede guardar html en title y description' do - site = build :site - site.description = "hola" - site.title = "hola" + _site = build :site + _site.description = "hola" + _site.title = "hola" - assert_equal 'hola', site.description - assert_equal 'hola', site.title + assert_equal 'hola', _site.description + assert_equal 'hola', _site.title end test 'el sitio tiene artículos en distintos idiomas' do - @site = create :site - I18n.available_locales.each do |locale| - assert @site.posts(lang: locale).size.positive? + assert site.posts(lang: locale).size.positive? end end + + test 'tienen un hostname que puede cambiar' do + assert_equal "#{site.name}.#{Site.domain}", site.hostname + + site.name = name = SecureRandom.hex + + assert_equal "#{name}.#{Site.domain}", site.hostname + end + + test 'se pueden traer los datos de una plantilla' do + @site = create :site, design: Design.find_by(gem: 'editorial-autogestiva-jekyll-theme') + + assert_equal %i[post], site.layouts.to_h.keys + + site.config.write + site.reload + + assert_equal %w[book editorial post], site.data['layouts'].keys + assert_equal %i[book editorial post], site.layouts.to_h.keys + end end