Module: NotionRails::Renderers

Includes:
ActionView::Context, ActionView::Helpers::AssetTagHelper, ActionView::Helpers::TagHelper, ActionView::Helpers::UrlHelper
Included in:
BaseBlock, BasePage, Page
Defined in:
lib/notion_rails/renderers.rb

Instance Method Summary collapse

Instance Method Details

#annotation_to_css_class(annotations) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/notion_rails/renderers.rb', line 12

def annotation_to_css_class(annotations)
  classes = annotations.keys.map do |key|
    case key
    when 'strikethrough'
      'line-through' if annotations[key]
    when 'bold'
      'font-bold' if annotations[key]
    when 'code'
      'inline-code' if annotations[key]
    when 'color'
      "text-#{annotations["color"]}-600" if annotations[key] != 'default'
    else
      annotations[key] ? key : nil
    end
  end
  classes.compact.join(' ')
end

#render_bulleted_list_item(rich_text_array, siblings, children, options = {}) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/notion_rails/renderers.rb', line 94

def render_bulleted_list_item(rich_text_array, siblings, children, options = {})
  pre_options = options
  pre_options[:class] = "list-disc break-words #{pre_options[:class]}"
  (:ul, pre_options) do
    content = (:li, options) do
      text_renderer(rich_text_array)
    end
    if children.present?
      res = children.map do |child|
        render_bulleted_list_item(child.rich_text, child.siblings, child.children, options)
      end
      content += res.join('').html_safe
    end
    content.html_safe
  end
end

#render_callout(rich_text_array, icon, options = {}) ⇒ Object



151
152
153
154
155
156
157
158
159
# File 'lib/notion_rails/renderers.rb', line 151

def render_callout(rich_text_array, icon, options = {})
  pre_options = options
  pre_options[:class] = "p-4 rounded bg-neutral-200 mt-4 #{pre_options[:class]}"
  (:div, pre_options) do
    content = tag.span(icon, class: 'pr-2')
    content += text_renderer(rich_text_array)
    content
  end
end

#render_code(rich_text_array, options = {}) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/notion_rails/renderers.rb', line 81

def render_code(rich_text_array, options = {})
  # TODO: render captions
  pre_options = options
  pre_options[:class] = "border-2 p-6 rounded #{pre_options[:class]}"
  (:div, class: 'mt-4', data: { controller: 'highlight' }) do
    (:div, data: { highlight_target: 'source' }) do
      (:pre, pre_options) do
        text_renderer(rich_text_array, options)
      end
    end
  end
end

#render_date(date, options = {}) ⇒ Object



51
52
53
54
55
# File 'lib/notion_rails/renderers.rb', line 51

def render_date(date, options = {})
  # TODO: handle end and time zone
  # date=end=, start=2023-07-13, time_zone=, id=%5BsvU, type=date
  tag.p(date.to_date.to_fs(:long), class: options[:class])
end

#render_heading_1(rich_text_array, options = {}) ⇒ Object



63
64
65
66
67
# File 'lib/notion_rails/renderers.rb', line 63

def render_heading_1(rich_text_array, options = {})
  (:h1, class: 'mb-4 mt-6 text-3xl font-semibold', **options) do
    text_renderer(rich_text_array)
  end
end

#render_heading_2(rich_text_array, options = {}) ⇒ Object



69
70
71
72
73
# File 'lib/notion_rails/renderers.rb', line 69

def render_heading_2(rich_text_array, options = {})
  (:h2, class: 'mb-4 mt-6 text-2xl font-semibold', **options) do
    text_renderer(rich_text_array)
  end
end

#render_heading_3(rich_text_array, options = {}) ⇒ Object



75
76
77
78
79
# File 'lib/notion_rails/renderers.rb', line 75

def render_heading_3(rich_text_array, options = {})
  (:h3, class: 'mb-2 mt-6 text-xl font-semibold', **options) do
    text_renderer(rich_text_array)
  end
end

#render_image(src, expiry_time, caption, type, options = {}) ⇒ Object



161
162
163
164
165
166
167
# File 'lib/notion_rails/renderers.rb', line 161

def render_image(src, expiry_time, caption, type, options = {})
  (:figure, options) do
    content = tag.img(src: src, alt: '')
    content += tag.figcaption(text_renderer(caption))
    content
  end
end

#render_list_items(type, rich_text_array, siblings, children, options = {}) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/notion_rails/renderers.rb', line 119

def render_list_items(type, rich_text_array, siblings, children, options = {})
  content = (:li, options) do
    text_renderer(rich_text_array)
  end
  if children.present?
    res = children.map do |child|
      render_numbered_list_item(child.rich_text, child.siblings, child.children)
    end
    content += res.join('').html_safe
  end
  if siblings.present?
    content += siblings.map do |sibling|
      render_list_items(type, sibling.rich_text, sibling.siblings, sibling.children, options)
    end.join('').html_safe
  end
  content.html_safe
end

#render_numbered_list_item(rich_text_array, siblings, children, options = {}) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/notion_rails/renderers.rb', line 111

def render_numbered_list_item(rich_text_array, siblings, children, options = {})
  pre_options = options
  pre_options[:class] = "list-decimal #{pre_options[:class]}"
  (:ol, pre_options) do
    render_list_items(:numbered_list_item, rich_text_array, siblings, children, options)
  end
end

#render_paragraph(rich_text_array, options = {}) ⇒ Object



57
58
59
60
61
# File 'lib/notion_rails/renderers.rb', line 57

def render_paragraph(rich_text_array, options = {})
  (:p, options) do
    text_renderer(rich_text_array)
  end
end

#render_quote(rich_text_array, options = {}) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/notion_rails/renderers.rb', line 137

def render_quote(rich_text_array, options = {})
  div_options = options.dup
  pre_options = options.dup
  div_options[:class] = "mt-4 #{options[:class]}"
  (:div, div_options) do
    pre_options[:class] = "border-l-4 border-black px-5 py-1 #{options[:class]}"
    (:cite) do
      (:p, pre_options) do
        text_renderer(rich_text_array)
      end
    end
  end
end

#render_title(title, options = {}) ⇒ Object



47
48
49
# File 'lib/notion_rails/renderers.rb', line 47

def render_title(title, options = {})
  render_heading_1(title, options)
end

#render_video(src, expiry_time, caption, type, options = {}) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
# File 'lib/notion_rails/renderers.rb', line 169

def render_video(src, expiry_time, caption, type, options = {})
  (:figure, options) do
    content = if type == 'file'
                video_tag(src, controls: true)
              elsif type == 'external'
                tag.iframe(src: src, allowfullscreen: true, class: 'w-full aspect-video')
              end
    content += tag.figcaption(text_renderer(caption))
    content
  end
end

#text_renderer(properties, options = {}) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/notion_rails/renderers.rb', line 30

def text_renderer(properties, options = {})
  properties.map do |rich_text|
    classes = annotation_to_css_class(rich_text['annotations'])
    if rich_text['href']
      link_to(
        rich_text['plain_text'],
        rich_text['href'],
        class: "link #{classes} #{options[:class]}"
      )
    elsif classes.present?
      (:span, rich_text['plain_text'], class: "#{classes} #{options[:class]}")
    else
      tag.span(rich_text['plain_text'], class: options[:class])
    end
  end.join('').html_safe
end