richer_text 0.9.0 → 0.11.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03e9732ed2320f56a2c30cbcd6af7614b6840b601aab70d790c96e6e8412babf
4
- data.tar.gz: 4413b9240e46d0153dff22c7b4dd7161a555f572ada62b69159f0c267ae7b0b4
3
+ metadata.gz: b0896d20faa3ab1fcf20e72e0be2fe6902bf2831b8f21bc5d006f6bbac0d4aad
4
+ data.tar.gz: e0b592625c14d7c867087b29129b4bf711e01675eb8e1187a6aa4114fab9eb48
5
5
  SHA512:
6
- metadata.gz: 39f20dfc3cecd2f74f4cc4d01b396d9678ceeed635ff4dc2a35bc62ba0dc8f6361f882dfe1df67b9286d63b1c86fbd6b7e73b729175e8fd3948435eb041a7ade
7
- data.tar.gz: 4718871930d84edd4de392d9ea2d321f6a04782e5f0c774906e468e8c70ecac6ea9c78fb4ed92dcf7aa8598fea600dea3d13a117beef8287d5b709a8547d2318
6
+ metadata.gz: 3f386bd1e15a650db59353b2627224d5dbdcbcfdaa28f49fe7fde165266cac6d876d618da844a00c7c1d7457468543060437aff4a7c2d41736f7eaf6152d92dc
7
+ data.tar.gz: 364abb9092c4f8bb13959c3dc13291a22b485e8360f12219064ec4bcb73deeff965c4942d5b0320e8d3977ad7bc107a78133649f72a2b02264fa3945a07adc06
@@ -0,0 +1,81 @@
1
+ require "oembed"
2
+
3
+ module RicherText
4
+ class OEmbed < ApplicationRecord
5
+ include RicherText::Embeddable
6
+
7
+ PATTERNS = [
8
+ {source: "^http:\\/\\/([^\\.]+\\.)?flickr\\.com\\/(.*?)", options: ""},
9
+ {source: "^https:\\/\\/([^\\.]+\\.)?flickr\\.com\\/(.*?)", options: ""},
10
+ {source: "^http:\\/\\/flic\\.kr\\/(.*?)", options: ""},
11
+ {source: "^https:\\/\\/flic\\.kr\\/(.*?)", options: ""},
12
+ {source: "^https:\\/\\/([^\\.]+\\.)?imgur\\.com\\/gallery\\/(.*?)", options: ""},
13
+ {source: "^http:\\/\\/([^\\.]+\\.)?imgur\\.com\\/gallery\\/(.*?)", options: ""},
14
+ {source: "^http:\\/\\/instagr\\.am\\/p\\/(.*?)", options: ""},
15
+ {source: "^http:\\/\\/instagram\\.com\\/p\\/(.*?)", options: ""},
16
+ {source: "^http:\\/\\/www\\.instagram\\.com\\/p\\/(.*?)", options: ""},
17
+ {source: "^https:\\/\\/instagr\\.am\\/p\\/(.*?)", options: ""},
18
+ {source: "^https:\\/\\/instagram\\.com\\/p\\/(.*?)", options: ""},
19
+ {source: "^https:\\/\\/www\\.instagram\\.com\\/p\\/(.*?)", options: ""},
20
+ {source: "^http:\\/\\/([^\\.]+\\.)?soundcloud\\.com\\/(.*?)", options: ""},
21
+ {source: "^https:\\/\\/([^\\.]+\\.)?soundcloud\\.com\\/(.*?)", options: ""},
22
+ {source: "^http:\\/\\/open\\.spotify\\.com\\/(.*?)", options: ""},
23
+ {source: "^https:\\/\\/open\\.spotify\\.com\\/(.*?)", options: ""},
24
+ {source: "^http:\\/\\/play\\.spotify\\.com\\/(.*?)", options: ""},
25
+ {source: "^https:\\/\\/play\\.spotify\\.com\\/(.*?)", options: ""},
26
+ {source: "^spotify\\:(.*?)", options: ""},
27
+ {source: "^https:\\/\\/([^\\.]+\\.)?twitter\\.com\\/(.*?)\\/status\\/(.*?)", options: ""},
28
+ {source: "^http:\\/\\/([^\\.]+\\.)?vimeo\\.com\\/(.*?)", options: ""},
29
+ {source: "^https:\\/\\/([^\\.]+\\.)?vimeo\\.com\\/(.*?)", options: ""},
30
+ {source: "^http:\\/\\/([^\\.]+\\.)?youtube\\.com\\/(.*?)", options: ""},
31
+ {source: "^https:\\/\\/([^\\.]+\\.)?youtube\\.com\\/(.*?)", options: ""},
32
+ {source: "^http:\\/\\/([^\\.]+\\.)?youtu\\.be\\/(.*?)", options: ""},
33
+ {source: "^https:\\/\\/([^\\.]+\\.)?youtu\\.be\\/(.*?)", options: ""}
34
+ ]
35
+
36
+ def self.from_url(url)
37
+ find_by!(url: url)
38
+ rescue ActiveRecord::RecordNotFound
39
+ resource = ::OEmbed::Providers.get(url)
40
+ create!(url: url, fields: resource.fields)
41
+ end
42
+
43
+ def self.delegate_fields(*keys)
44
+ keys.each do |key|
45
+ define_method(key) do
46
+ fields[key.to_s]
47
+ end
48
+ end
49
+ end
50
+
51
+ delegate_fields(
52
+ :type,
53
+ :version,
54
+ :title,
55
+ :author_name,
56
+ :author_url,
57
+ :provider_name,
58
+ :provider_url,
59
+ :thumbnail_url,
60
+ :thumbnail_width,
61
+ :thumbnail_height,
62
+ :height,
63
+ :width,
64
+ :html
65
+ )
66
+
67
+ %w[link photo rich video].each do |embed_type|
68
+ define_method "#{embed_type}?" do
69
+ type == embed_type
70
+ end
71
+ end
72
+
73
+ def to_embeddable_partial_path
74
+ "richer_text/o_embeds/embed"
75
+ end
76
+
77
+ def to_richer_text_editor_partial_path
78
+ "richer_text/o_embeds/richer_text_editor_embed"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,11 @@
1
+ <% if o_embed.thumbnail_url && !o_embed.html %>
2
+ <div class="embed">
3
+ <%= image_tag o_embed.thumbnail_url %>
4
+ </div>
5
+ <% elsif o_embed.html %>
6
+ <div class="embed">
7
+ <%= o_embed.html.html_safe %>
8
+ </div>
9
+ <% elsif o_embed.provider_name %>
10
+ <%= link_to o_embed.provider_name, o_embed.url %>
11
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% if o_embed.thumbnail_url %>
2
+ <div class="embed">
3
+ <%= image_tag o_embed.thumbnail_url %>
4
+ </div>
5
+ <% elsif o_embed.html %>
6
+ <div class="embed">
7
+ <%= o_embed.html.html_safe %>
8
+ </div>
9
+ <% elsif o_embed.provider_name %>
10
+ <%= link_to o_embed.provider_name, o_embed.url %>
11
+ <% end %>
@@ -0,0 +1,10 @@
1
+ class CreateRicherTextOEmbeds < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :richer_text_o_embeds do |t|
4
+ t.jsonb :fields
5
+ t.string :url
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ module RicherText
2
+ class Embed
3
+ include Rendering
4
+
5
+ def self.find(sgid)
6
+ @embed = GlobalID::Locator.locate_signed(sgid, for: "embeddable")
7
+ new(@embed) if @embed
8
+ end
9
+
10
+ attr_reader :embed
11
+
12
+ def initialize(embed)
13
+ @embed = embed
14
+ end
15
+
16
+ def object
17
+ @embed
18
+ end
19
+
20
+ delegate :to_richer_text_editor_partial_path, to: :@embed
21
+ delegate :model_name, to: :@embed
22
+
23
+ def html
24
+ render partial: to_richer_text_editor_partial_path, object: object, as: model_name.element
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module RicherText
2
+ module Embeddable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def embeddable_sgid
7
+ to_sgid(expires_in: nil, for: "embeddable").to_s
8
+ end
9
+
10
+ def to_embeddable_partial_path
11
+ to_partial_path
12
+ end
13
+
14
+ def to_richer_text_editor_partial_path
15
+ to_partial_path
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,4 +1,5 @@
1
1
  require "rails"
2
+ require "oembed"
2
3
 
3
4
  module RicherText
4
5
  class Engine < ::Rails::Engine
@@ -15,5 +16,13 @@ module RicherText
15
16
  helper RicherText::TagHelper
16
17
  end
17
18
  end
19
+
20
+ config.after_initialize do
21
+ ::OEmbed::Providers.register_all
22
+ ::OEmbed::Providers.register_fallback(
23
+ ::OEmbed::ProviderDiscovery,
24
+ ::OEmbed::Providers::Noembed
25
+ )
26
+ end
18
27
  end
19
28
  end
@@ -57,6 +57,10 @@ module RicherText
57
57
  "<p style='#{node.style}'>#{visit_children(node).join}</p>"
58
58
  end
59
59
 
60
+ def visit_richer_text_embed(node)
61
+ node.html
62
+ end
63
+
60
64
  def visit_list_item(node)
61
65
  "<li>#{visit_children(node).join}</li>"
62
66
  end
@@ -78,7 +82,7 @@ module RicherText
78
82
  end
79
83
 
80
84
  def visit_image(node)
81
- "<img src='#{node.src}' />"
85
+ "<img src='#{node.src}' width='#{node.width}' />"
82
86
  end
83
87
 
84
88
  def visit_text(node, marks)
@@ -1,6 +1,7 @@
1
1
  module RicherText
2
2
  class Node
3
3
  attr_reader :json, :attrs, :children, :type
4
+ include RicherText::Rendering
4
5
 
5
6
  STYLES = {
6
7
  "textAlign" => "text-align",
@@ -8,6 +8,10 @@ module RicherText
8
8
  def signed_id
9
9
  @signed_id = attrs['signedId']
10
10
  end
11
+
12
+ def width
13
+ attrs['width']
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -0,0 +1,19 @@
1
+ module RicherText
2
+ module Nodes
3
+ class RicherTextEmbed < ::RicherText::Node
4
+ def sgid
5
+ attrs["sgid"]
6
+ end
7
+
8
+ def html
9
+ render partial: embeddable.to_embeddable_partial_path, object: embeddable, as: embeddable.model_name.element
10
+ rescue ActiveRecord::RecordNotFound, NoMethodError
11
+ "" # TODO: handle this better
12
+ end
13
+
14
+ def embeddable
15
+ @embeddable ||= GlobalID::Locator.locate_signed(sgid, for: "embeddable")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,13 +1,23 @@
1
+ require "active_support/concern"
2
+ require "active_support/core_ext/module/attribute_accessors_per_thread"
3
+
1
4
  module RicherText
2
5
  module Rendering
3
- private
6
+ extend ActiveSupport::Concern
4
7
 
5
- def render(*args, &block)
6
- action_controller_renderer.render(*args, &block)
8
+ included do
9
+ thread_cattr_accessor :renderer, instance_accessor: false
10
+ delegate :render, to: :class
7
11
  end
8
12
 
9
- def action_controller_renderer
10
- ActionController::Base.renderer
13
+ class_methods do
14
+ def action_controller_renderer
15
+ @action_controller_renderer ||= Class.new(ActionController::Base).renderer
16
+ end
17
+
18
+ def render(*args, &block)
19
+ (renderer || action_controller_renderer).render_to_string(*args, &block)
20
+ end
11
21
  end
12
22
  end
13
23
  end
@@ -1,3 +1,3 @@
1
1
  module RicherText
2
- VERSION = "0.9.0"
2
+ VERSION = "0.11.0"
3
3
  end
data/lib/richer_text.rb CHANGED
@@ -14,6 +14,9 @@ module RicherText
14
14
  autoload :Serialization
15
15
  autoload :TagHelper
16
16
 
17
+ autoload :Embed
18
+ autoload :Embeddable
19
+
17
20
  autoload :Node
18
21
  autoload :Mark
19
22
  autoload :HTMLVisitor
@@ -36,6 +39,7 @@ module RicherText
36
39
  autoload :Mention
37
40
  autoload :OrderedList
38
41
  autoload :Paragraph
42
+ autoload :RicherTextEmbed
39
43
  autoload :Text
40
44
  autoload :Table
41
45
  autoload :TableCell
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: richer_text
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrea Fomera
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-22 00:00:00.000000000 Z
11
+ date: 2023-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 7.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-oembed
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description:
28
42
  email:
29
43
  - afomera@hey.com
@@ -44,16 +58,22 @@ files:
44
58
  - app/mailers/richer_text/application_mailer.rb
45
59
  - app/models/richer_text/application_record.rb
46
60
  - app/models/richer_text/json_text.rb
61
+ - app/models/richer_text/o_embed.rb
47
62
  - app/models/richer_text/rich_text.rb
48
63
  - app/views/layouts/richer_text/application.html.erb
49
64
  - app/views/richer_text/contents/_content.html.erb
65
+ - app/views/richer_text/o_embeds/_embed.html.erb
66
+ - app/views/richer_text/o_embeds/_richer_text_editor_embed.html.erb
50
67
  - config/routes.rb
51
68
  - db/migrate/20230107020316_create_richer_text_rich_texts.rb
52
69
  - db/migrate/20230916224959_create_richer_text_json_texts.rb
70
+ - db/migrate/20230926034114_create_richer_text_o_embeds.rb
53
71
  - lib/generators/richer_text/install/install_generator.rb
54
72
  - lib/richer_text.rb
55
73
  - lib/richer_text/attribute.rb
56
74
  - lib/richer_text/content.rb
75
+ - lib/richer_text/embed.rb
76
+ - lib/richer_text/embeddable.rb
57
77
  - lib/richer_text/engine.rb
58
78
  - lib/richer_text/fragment.rb
59
79
  - lib/richer_text/html_visitor.rb
@@ -74,6 +94,7 @@ files:
74
94
  - lib/richer_text/nodes/mention.rb
75
95
  - lib/richer_text/nodes/ordered_list.rb
76
96
  - lib/richer_text/nodes/paragraph.rb
97
+ - lib/richer_text/nodes/richer_text_embed.rb
77
98
  - lib/richer_text/nodes/table.rb
78
99
  - lib/richer_text/nodes/table_cell.rb
79
100
  - lib/richer_text/nodes/table_header.rb