spina 2.3.5 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of spina might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +10 -3
- data/app/assets/javascripts/spina/application.js +1 -1
- data/app/assets/javascripts/spina/controllers/application.js +11 -0
- data/app/assets/javascripts/spina/controllers/embed_controller.js +16 -0
- data/app/assets/javascripts/spina/controllers/embed_tag_controller.js +16 -0
- data/app/assets/javascripts/spina/controllers/index.js +5 -0
- data/app/assets/javascripts/spina/controllers/trix_controller.js +12 -2
- data/app/assets/stylesheets/spina/_fonts.css.erb +114 -0
- data/app/assets/stylesheets/spina/_tailwind.css +18 -5
- data/app/assets/stylesheets/spina/application.css +6 -0
- data/app/assets/stylesheets/spina/tailwind/custom.css +13 -5
- data/app/components/spina/forms/trix_toolbar_component.html.erb +26 -15
- data/app/components/spina/media_picker/image_component.html.erb +1 -1
- data/app/components/spina/pages/new_page_button_component.html.erb +32 -0
- data/app/components/spina/pages/new_page_button_component.rb +19 -0
- data/app/controllers/concerns/spina/frontend.rb +1 -1
- data/app/controllers/spina/admin/embeds_controller.rb +36 -0
- data/app/controllers/spina/admin/pages_controller.rb +1 -2
- data/app/controllers/spina/admin/password_resets_controller.rb +2 -4
- data/app/helpers/spina/admin/icons_helper.rb +2 -2
- data/app/helpers/spina/images_helper.rb +1 -1
- data/app/helpers/spina/spina_helper.rb +3 -2
- data/app/mailers/spina/application_mailer.rb +7 -0
- data/app/mailers/spina/user_mailer.rb +6 -14
- data/app/models/spina/embeds/base.rb +7 -0
- data/app/models/spina/embeds/button.rb +13 -0
- data/app/models/spina/embeds/vimeo.rb +39 -0
- data/app/models/spina/embeds/youtube.rb +39 -0
- data/app/models/spina/page.rb +10 -3
- data/app/models/spina/user.rb +6 -0
- data/app/presenters/spina/content_presenter.rb +1 -1
- data/app/presenters/spina/rich_text_presenter.rb +45 -0
- data/app/views/layouts/spina/admin/application.html.erb +1 -1
- data/app/views/layouts/spina/mail.html.erb +476 -1
- data/app/views/spina/admin/embeds/new.html.erb +47 -0
- data/app/views/spina/admin/pages/edit_template.html.erb +1 -1
- data/app/views/spina/admin/pages/index.html.erb +1 -21
- data/app/views/spina/admin/shared/_flash.html.erb +2 -2
- data/app/views/spina/embeds/buttons/_button.html.erb +3 -0
- data/app/views/spina/embeds/buttons/_button_fields.html.erb +14 -0
- data/app/views/spina/embeds/buttons/_trix_button.html.erb +3 -0
- data/app/views/spina/embeds/vimeos/_thumbnail.html.erb +6 -0
- data/app/views/spina/embeds/vimeos/_vimeo.html.erb +1 -0
- data/app/views/spina/embeds/vimeos/_vimeo_fields.html.erb +9 -0
- data/app/views/spina/embeds/youtubes/_thumbnail.html.erb +6 -0
- data/app/views/spina/embeds/youtubes/_youtube.html.erb +1 -0
- data/app/views/spina/embeds/youtubes/_youtube_fields.html.erb +9 -0
- data/app/views/spina/user_mailer/forgot_password.html.erb +57 -1
- data/app/views/spina/user_mailer/forgot_password.text.erb +9 -0
- data/config/initializers/importmap.rb +12 -0
- data/config/locales/en.yml +30 -0
- data/config/locales/nl.yml +1 -0
- data/config/routes.rb +5 -2
- data/lib/generators/spina/embed_generator.rb +18 -0
- data/lib/generators/spina/install_generator.rb +36 -14
- data/lib/generators/spina/templates/app/models/spina/embeds/embed.rb.tt +18 -0
- data/lib/generators/spina/templates/app/views/default/pages/homepage.html.erb +1 -1
- data/lib/generators/spina/templates/app/views/spina/embeds/_fields.html.erb +13 -0
- data/lib/generators/spina/templates/app/views/spina/embeds/_partial.html.erb +2 -0
- data/lib/generators/spina/templates/config/initializers/spina.rb +7 -0
- data/lib/generators/spina/templates/config/initializers/themes/default.rb +3 -0
- data/lib/generators/spina/templates/config/initializers/themes/demo.rb +4 -1
- data/lib/spina/embeddable.rb +48 -0
- data/lib/spina/embeds/trix_conversion.rb +41 -0
- data/lib/spina/embeds.rb +11 -0
- data/lib/spina/engine.rb +7 -21
- data/lib/spina/part.rb +10 -2
- data/lib/spina/railtie.rb +10 -0
- data/lib/spina/theme.rb +16 -3
- data/lib/spina/theme_reloader.rb +20 -0
- data/lib/spina/version.rb +1 -1
- data/lib/spina.rb +11 -0
- data/lib/tasks/spina_tasks.rake +19 -2
- metadata +66 -34
- data/app/assets/stylesheets/spina/_fonts.scss +0 -114
- data/app/assets/stylesheets/spina/application.sass +0 -3
- data/app/views/spina/user_mailer/forgot_password.txt.erb +0 -1
@@ -1,10 +1,11 @@
|
|
1
1
|
module Spina::SpinaHelper
|
2
2
|
|
3
|
-
def spina_importmap_tags(entry_point = "application")
|
3
|
+
def spina_importmap_tags(entry_point = "application", shim: true)
|
4
4
|
safe_join [
|
5
5
|
javascript_inline_importmap_tag(Spina.config.importmap.to_json(resolver: self)),
|
6
6
|
javascript_importmap_module_preload_tags(Spina.config.importmap),
|
7
|
-
|
7
|
+
(javascript_importmap_shim_nonce_configuration_tag if shim),
|
8
|
+
(javascript_importmap_shim_tag if shim),
|
8
9
|
javascript_import_module_tag(entry_point)
|
9
10
|
], "\n"
|
10
11
|
end
|
@@ -1,21 +1,13 @@
|
|
1
1
|
module Spina
|
2
|
-
class UserMailer <
|
3
|
-
layout 'spina/mail'
|
2
|
+
class UserMailer < ApplicationMailer
|
4
3
|
|
5
|
-
def forgot_password(user)
|
4
|
+
def forgot_password(user, user_agent_string = nil)
|
6
5
|
@user = user
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
subject: t('spina.forgot_password.mail_subject')
|
12
|
-
)
|
6
|
+
@browser = Browser.new(user_agent_string)
|
7
|
+
|
8
|
+
mail to: @user.email,
|
9
|
+
subject: t('spina.user_mailer.forgot_password.subject')
|
13
10
|
end
|
14
11
|
|
15
|
-
private
|
16
|
-
|
17
|
-
def current_account
|
18
|
-
Spina::Account.first
|
19
|
-
end
|
20
12
|
end
|
21
13
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Spina::Embeds
|
4
|
+
class Vimeo < Base
|
5
|
+
attributes :url
|
6
|
+
|
7
|
+
heroicon "video-camera"
|
8
|
+
|
9
|
+
REGEX = /(https?:\/\/)?(www.)?(player.)?vimeo.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*/
|
10
|
+
|
11
|
+
validates :url, presence: true, format: {with: REGEX}
|
12
|
+
|
13
|
+
def id
|
14
|
+
REGEX.match(url).try(:[], 5)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get title from Vimeo API (remote call)
|
18
|
+
def remote_title
|
19
|
+
get_vimeo_json&.dig(0, "title")
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_trix_partial_path
|
23
|
+
"spina/embeds/vimeos/thumbnail"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def get_vimeo_json
|
29
|
+
uri = URI("https://vimeo.com/api/v2/video/#{id}.json")
|
30
|
+
response = Net::HTTP.get(uri)
|
31
|
+
begin
|
32
|
+
JSON.parse(response)
|
33
|
+
rescue
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Spina::Embeds
|
4
|
+
class Youtube < Base
|
5
|
+
attributes :url
|
6
|
+
|
7
|
+
heroicon "video-camera"
|
8
|
+
|
9
|
+
REGEX = /(?:youtube(?:-nocookie)?\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/
|
10
|
+
|
11
|
+
validates :url, presence: true, format: {with: REGEX}
|
12
|
+
|
13
|
+
def id
|
14
|
+
REGEX.match(url).try(:[], 1)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get title from Youtube API (remote call)
|
18
|
+
def remote_title
|
19
|
+
get_youtube_json&.dig("title")
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_trix_partial_path
|
23
|
+
"spina/embeds/youtubes/thumbnail"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def get_youtube_json
|
29
|
+
uri = URI("https://www.youtube.com/oembed?url=http://youtube.com/watch?v=#{id}&format=json")
|
30
|
+
response = Net::HTTP.get(uri)
|
31
|
+
begin
|
32
|
+
JSON.parse(response)
|
33
|
+
rescue
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/app/models/spina/page.rb
CHANGED
@@ -26,6 +26,8 @@ module Spina
|
|
26
26
|
scope :sorted, -> { order(:position) }
|
27
27
|
scope :live, -> { active.where(draft: false) }
|
28
28
|
scope :in_menu, -> { where(show_in_menu: true) }
|
29
|
+
|
30
|
+
before_create :set_default_position
|
29
31
|
|
30
32
|
# Copy resource from parent
|
31
33
|
before_save :set_resource_from_parent, if: -> { parent.present? }
|
@@ -102,6 +104,10 @@ module Spina
|
|
102
104
|
end
|
103
105
|
|
104
106
|
private
|
107
|
+
|
108
|
+
def set_default_position
|
109
|
+
self.position ||= self.class.maximum(:position).to_i.next
|
110
|
+
end
|
105
111
|
|
106
112
|
def set_resource_from_parent
|
107
113
|
self.resource_id = parent.resource_id
|
@@ -116,11 +122,12 @@ module Spina
|
|
116
122
|
end
|
117
123
|
|
118
124
|
def localized_materialized_path
|
119
|
-
if Mobility.locale == I18n.default_locale
|
120
|
-
generate_materialized_path
|
125
|
+
segments = if Mobility.locale == I18n.default_locale
|
126
|
+
[Spina.mounted_at, generate_materialized_path]
|
121
127
|
else
|
122
|
-
|
128
|
+
[Spina.mounted_at, Mobility.locale, generate_materialized_path]
|
123
129
|
end
|
130
|
+
File.join(*segments.map(&:to_s).compact)
|
124
131
|
end
|
125
132
|
|
126
133
|
def generate_materialized_path
|
data/app/models/spina/user.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Spina
|
2
|
+
class RichTextPresenter
|
3
|
+
attr_reader :html, :view_context
|
4
|
+
|
5
|
+
EMBED_CONTENT_TYPE = "application/vnd+spina.embed+html"
|
6
|
+
|
7
|
+
def initialize(view_context, html)
|
8
|
+
@view_context = view_context || Spina::Current.page&.view_context
|
9
|
+
@html = html
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
ActiveSupport::SafeBuffer.new(render_embeds(html))
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def embed_selector
|
19
|
+
"figure[data-trix-content-type=\"#{EMBED_CONTENT_TYPE}\"]"
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_embeds(html)
|
23
|
+
doc = Nokogiri::HTML(html)
|
24
|
+
doc.css(embed_selector).each do |node|
|
25
|
+
node.replace render_embed(node.first_element_child)
|
26
|
+
end
|
27
|
+
doc.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
def render_embed(element)
|
31
|
+
embeddable = element_to_embeddable(element)
|
32
|
+
view_context.render(embeddable)
|
33
|
+
end
|
34
|
+
|
35
|
+
def element_to_embeddable(element)
|
36
|
+
embeddable = Spina::Embeds.constantize(element["data-embed-type"])
|
37
|
+
embeddable&.from_json(element["data-embed-attributes"]) || null_object
|
38
|
+
end
|
39
|
+
|
40
|
+
def null_object
|
41
|
+
{inline: ""}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|