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



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

def render_bulleted_list_item(rich_text_array, _siblings, children, options = {})
  (:ul, class: 'list-disc break-words', **options.except(:class)) 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



142
143
144
145
146
147
148
# File 'lib/notion_rails/renderers.rb', line 142

def render_callout(rich_text_array, icon, options = {})
  (:div, class: 'p-4 rounded bg-neutral-200 mt-4', **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
# File 'lib/notion_rails/renderers.rb', line 81

def render_code(rich_text_array, options = {})
  # TODO: render captions
  (:div, class: 'mt-4', data: { controller: 'highlight' }) do
    (:div, data: { highlight_target: 'source' }) do
      (:pre, class: "border-2 p-6 rounded w-full overflow-x-auto language-#{options[:language]}",
**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



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

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



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/notion_rails/renderers.rb', line 114

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



108
109
110
111
112
# File 'lib/notion_rails/renderers.rb', line 108

def render_numbered_list_item(rich_text_array, siblings, children, options = {})
  (:ol, class: 'list-decimal', **options.except(:class)) 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



132
133
134
135
136
137
138
139
140
# File 'lib/notion_rails/renderers.rb', line 132

def render_quote(rich_text_array, options = {})
  (:div, class: 'mt-4', **options) do
    (:cite) do
      (:p, class: 'border-l-4 border-black px-5 py-1', **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



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

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