notion_rails 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
 - data/README.md +1 -1
 - data/lib/notion_rails/base_block.rb +98 -0
 - data/lib/notion_rails/base_page.rb +52 -0
 - data/lib/notion_rails/page.rb +18 -0
 - data/lib/notion_rails/renderers.rb +171 -0
 - data/lib/notion_rails/service.rb +90 -0
 - data/lib/notion_rails/version.rb +1 -1
 - metadata +6 -1
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: ca08751cb4669bed3cd0ad791b3242ba6c2f873e3272310750beaa940eb17151
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: fe85cdedfe168e670b5cd2588cb03d514347408ac24396e1dec60e3df8c2bdf6
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: '052119acf124d0543367b3bbbc14d762eb08132428f3c1b92242b4069f8f3e8c9665f7fbd1db79f3e5a6915eec853531417853af72096fcd83e18e0fdf39669f'
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: '09a7d8478a722c303e6f22782069dbf74ad83cad14a0949f1fe84453ba4e29dc3703a25de7ab31f4943b6258ab3f5fb471b421f638be2b97f8b780bdbc4533f5'
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            TODO: Delete this and the text below, and describe your gem
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ 
     | 
| 
      
 5 
     | 
    
         
            +
            Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/notion_rails`. To experiment with that code, run `bin/console` for an interactive prompt.
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            ## Installation
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
         @@ -0,0 +1,98 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module NotionRails
         
     | 
| 
      
 2 
     | 
    
         
            +
              class BaseBlock
         
     | 
| 
      
 3 
     | 
    
         
            +
                include NotionRails::Renderers
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                # TODO: validate object type is block
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :id,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  :created_time,
         
     | 
| 
      
 9 
     | 
    
         
            +
                  :last_edited_time,
         
     | 
| 
      
 10 
     | 
    
         
            +
                  :created_by,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  :last_edited_by,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  :parent,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  :archived,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  :has_children,
         
     | 
| 
      
 15 
     | 
    
         
            +
                  :children,
         
     | 
| 
      
 16 
     | 
    
         
            +
                  :siblings,
         
     | 
| 
      
 17 
     | 
    
         
            +
                  :type,
         
     | 
| 
      
 18 
     | 
    
         
            +
                  :properties
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                attr_accessor :children, :siblings
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                BLOCK_TYPES = %w[
         
     | 
| 
      
 23 
     | 
    
         
            +
                  paragraph
         
     | 
| 
      
 24 
     | 
    
         
            +
                  heading_1
         
     | 
| 
      
 25 
     | 
    
         
            +
                  heading_2
         
     | 
| 
      
 26 
     | 
    
         
            +
                  heading_3
         
     | 
| 
      
 27 
     | 
    
         
            +
                  bulleted_list_item
         
     | 
| 
      
 28 
     | 
    
         
            +
                  numbered_list_item
         
     | 
| 
      
 29 
     | 
    
         
            +
                  quote
         
     | 
| 
      
 30 
     | 
    
         
            +
                  callout
         
     | 
| 
      
 31 
     | 
    
         
            +
                  code
         
     | 
| 
      
 32 
     | 
    
         
            +
                  image
         
     | 
| 
      
 33 
     | 
    
         
            +
                  video
         
     | 
| 
      
 34 
     | 
    
         
            +
                  table_of_contents
         
     | 
| 
      
 35 
     | 
    
         
            +
                ].freeze
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def initialize(data)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @id = data['id']
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @created_time = data['created_time']
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @last_edited_time = data['last_edited_time']
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # TODO: handle user object
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @created_by = data['created_by']
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @last_edited_by = data['last_edited_by']
         
     | 
| 
      
 44 
     | 
    
         
            +
                  # TODO: handle page_id type
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @parent = data['parent']
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @archived = data['archived']
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @has_children = data['has_children']
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @children = []
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @siblings = []
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @type = data['type']
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @properties = data[@type]
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def render(options = {})
         
     | 
| 
      
 55 
     | 
    
         
            +
                  case @type
         
     | 
| 
      
 56 
     | 
    
         
            +
                  when 'paragraph' then render_paragraph(rich_text, class: options[:paragraph])
         
     | 
| 
      
 57 
     | 
    
         
            +
                  when 'heading_1' then render_heading_1(rich_text, class: options[:heading_1])
         
     | 
| 
      
 58 
     | 
    
         
            +
                  when 'heading_2' then render_heading_2(rich_text, class: options[:heading_2])
         
     | 
| 
      
 59 
     | 
    
         
            +
                  when 'heading_3' then render_heading_3(rich_text, class: options[:heading_3])
         
     | 
| 
      
 60 
     | 
    
         
            +
                  when 'table_of_contents' then render_table_of_contents
         
     | 
| 
      
 61 
     | 
    
         
            +
                  when 'bulleted_list_item' then render_bulleted_list_item(rich_text, @siblings, @children, class: options[:bulleted_list_item])
         
     | 
| 
      
 62 
     | 
    
         
            +
                  when 'numbered_list_item' then render_numbered_list_item(rich_text, @siblings, @children, class: options[:numbered_list_item])
         
     | 
| 
      
 63 
     | 
    
         
            +
                  when 'quote' then render_quote(rich_text, class: options[:quote])
         
     | 
| 
      
 64 
     | 
    
         
            +
                  when 'callout' then render_callout(rich_text, icon, class: options[:callout])
         
     | 
| 
      
 65 
     | 
    
         
            +
                  when 'code' then render_code(rich_text, class: "#{options[:code]} language-#{@properties['language']}")
         
     | 
| 
      
 66 
     | 
    
         
            +
                  when 'image' then render_image(*multi_media)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  when 'video' then render_video(*multi_media)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  else
         
     | 
| 
      
 69 
     | 
    
         
            +
                    'Error'
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def rich_text
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @properties['rich_text'] || []
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def icon
         
     | 
| 
      
 78 
     | 
    
         
            +
                  icon = @properties['icon']
         
     | 
| 
      
 79 
     | 
    
         
            +
                  @properties['icon'][icon['type']] || []
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def multi_media
         
     | 
| 
      
 83 
     | 
    
         
            +
                  case @properties['type']
         
     | 
| 
      
 84 
     | 
    
         
            +
                  when 'file'
         
     | 
| 
      
 85 
     | 
    
         
            +
                    [@properties.dig('file', 'url'), @properties.dig('file', 'expiry_time'), @properties['caption'], 'file']
         
     | 
| 
      
 86 
     | 
    
         
            +
                  when 'external'
         
     | 
| 
      
 87 
     | 
    
         
            +
                    [@properties.dig('external', 'url'), nil, @properties['caption'], 'external']
         
     | 
| 
      
 88 
     | 
    
         
            +
                  else
         
     | 
| 
      
 89 
     | 
    
         
            +
                    [nil, nil, @properties['caption'], nil]
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                private
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                def render_table_of_contents
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module NotionRails
         
     | 
| 
      
 2 
     | 
    
         
            +
              class BasePage
         
     | 
| 
      
 3 
     | 
    
         
            +
                include NotionRails::Renderers
         
     | 
| 
      
 4 
     | 
    
         
            +
                # TODO: validate object type is page
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :id,
         
     | 
| 
      
 6 
     | 
    
         
            +
                  :created_time,
         
     | 
| 
      
 7 
     | 
    
         
            +
                  :last_edited_time,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  :created_by,
         
     | 
| 
      
 9 
     | 
    
         
            +
                  :last_edited_by,
         
     | 
| 
      
 10 
     | 
    
         
            +
                  :cover,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  :icon,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  :parent,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  :archived,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  :properties,
         
     | 
| 
      
 15 
     | 
    
         
            +
                  :tags,
         
     | 
| 
      
 16 
     | 
    
         
            +
                  :title,
         
     | 
| 
      
 17 
     | 
    
         
            +
                  :slug,
         
     | 
| 
      
 18 
     | 
    
         
            +
                  :url
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def initialize(data)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @id = data['id']
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @created_time = data['created_time']
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @last_edited_time = data['last_edited_time']
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # TODO: handle user object
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @created_by = data['created_by']
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @last_edited_by = data['last_edited_by']
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # TODO: handle external type
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @cover = data['cover']
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # TODO: handle emoji type
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @icon = data['icon']
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # TODO: handle database_id type
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @parent = data['parent']
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @archived = data['archived']
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # TODO: handle properties object
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @properties = data['properties']
         
     | 
| 
      
 36 
     | 
    
         
            +
                  process_properties
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @url = data['url']
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def formatted_title(options = {})
         
     | 
| 
      
 41 
     | 
    
         
            +
                  render_title(@title, options)
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                private
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def process_properties
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @tags = @properties['tags']
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @title = @properties.dig('name', 'title')
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @slug = @properties['slug']
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module NotionRails
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Page
         
     | 
| 
      
 3 
     | 
    
         
            +
                include NotionRails::Renderers
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :metadata, :blocks
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                delegate :formatted_title, to: :metadata
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(base_page, base_blocks)
         
     | 
| 
      
 10 
     | 
    
         
            +
            	  	@metadata = base_page
         
     | 
| 
      
 11 
     | 
    
         
            +
            		  @blocks = base_blocks
         
     | 
| 
      
 12 
     | 
    
         
            +
              	end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            		def formatted_blocks(options = {})
         
     | 
| 
      
 15 
     | 
    
         
            +
            			@blocks.map { |block| block.render(options) }
         
     | 
| 
      
 16 
     | 
    
         
            +
            		end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,171 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module NotionRails
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Renderers
         
     | 
| 
      
 3 
     | 
    
         
            +
                include ActionView::Helpers::AssetTagHelper
         
     | 
| 
      
 4 
     | 
    
         
            +
                include ActionView::Helpers::TagHelper
         
     | 
| 
      
 5 
     | 
    
         
            +
                include ActionView::Helpers::UrlHelper
         
     | 
| 
      
 6 
     | 
    
         
            +
                include ActionView::Context
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def annotation_to_css_class(annotations)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  classes = annotations.keys.map do |key|
         
     | 
| 
      
 10 
     | 
    
         
            +
                    case key
         
     | 
| 
      
 11 
     | 
    
         
            +
                    when 'strikethrough'
         
     | 
| 
      
 12 
     | 
    
         
            +
                      'line-through' if annotations[key]
         
     | 
| 
      
 13 
     | 
    
         
            +
                    when 'bold'
         
     | 
| 
      
 14 
     | 
    
         
            +
                      'font-bold' if annotations[key]
         
     | 
| 
      
 15 
     | 
    
         
            +
                    when 'code'
         
     | 
| 
      
 16 
     | 
    
         
            +
                      'inline-code' if annotations[key]
         
     | 
| 
      
 17 
     | 
    
         
            +
                    when 'color'
         
     | 
| 
      
 18 
     | 
    
         
            +
                      "text-#{annotations['color']}-600" if annotations[key] != 'default'
         
     | 
| 
      
 19 
     | 
    
         
            +
                    else
         
     | 
| 
      
 20 
     | 
    
         
            +
                      annotations[key] ? key : nil
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  classes.compact.join(' ')
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def text_renderer(properties)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  properties.map do |rich_text|
         
     | 
| 
      
 28 
     | 
    
         
            +
                    classes = annotation_to_css_class(rich_text['annotations'])
         
     | 
| 
      
 29 
     | 
    
         
            +
                    if rich_text['href']
         
     | 
| 
      
 30 
     | 
    
         
            +
                      link_to(
         
     | 
| 
      
 31 
     | 
    
         
            +
                        rich_text['plain_text'],
         
     | 
| 
      
 32 
     | 
    
         
            +
                        rich_text['href'],
         
     | 
| 
      
 33 
     | 
    
         
            +
                        class: "link #{classes}"
         
     | 
| 
      
 34 
     | 
    
         
            +
                      )
         
     | 
| 
      
 35 
     | 
    
         
            +
                    elsif classes.present?
         
     | 
| 
      
 36 
     | 
    
         
            +
                      content_tag(:span, rich_text['plain_text'], class: classes)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    else
         
     | 
| 
      
 38 
     | 
    
         
            +
                      rich_text['plain_text']
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def render_title(title, options = {})
         
     | 
| 
      
 44 
     | 
    
         
            +
                  render_paragraph(title, options)
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def render_paragraph(rich_text_array, options = {})
         
     | 
| 
      
 48 
     | 
    
         
            +
                  content_tag(:p, options) do
         
     | 
| 
      
 49 
     | 
    
         
            +
                    text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                def render_heading_1(rich_text_array, options = {})
         
     | 
| 
      
 54 
     | 
    
         
            +
                    content_tag(:h1, class: 'mb-4 mt-6 text-3xl font-semibold', **options) do
         
     | 
| 
      
 55 
     | 
    
         
            +
                      text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def render_heading_2(rich_text_array, options = {})
         
     | 
| 
      
 60 
     | 
    
         
            +
                    content_tag(:h2, class: 'mb-4 mt-6 text-2xl font-semibold', **options) do
         
     | 
| 
      
 61 
     | 
    
         
            +
                      text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def render_heading_3(rich_text_array, options = {})
         
     | 
| 
      
 66 
     | 
    
         
            +
                    content_tag(:h3, class: 'mb-2 mt-6 text-xl font-semibold', **options) do
         
     | 
| 
      
 67 
     | 
    
         
            +
                      text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                def render_code(rich_text_array, options = {})
         
     | 
| 
      
 72 
     | 
    
         
            +
                  # TODO: render captions
         
     | 
| 
      
 73 
     | 
    
         
            +
                  pre_options = options
         
     | 
| 
      
 74 
     | 
    
         
            +
                  pre_options[:class] = "p-6 rounded #{pre_options[:class]}"
         
     | 
| 
      
 75 
     | 
    
         
            +
                  content_tag(:div, class: 'mt-4', data: { controller: 'highlight' }) do
         
     | 
| 
      
 76 
     | 
    
         
            +
                    content_tag(:div, data: { highlight_target: 'source' }) do
         
     | 
| 
      
 77 
     | 
    
         
            +
                      content_tag(:pre, pre_options) do
         
     | 
| 
      
 78 
     | 
    
         
            +
                        content_tag(:code, options) do
         
     | 
| 
      
 79 
     | 
    
         
            +
                          text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 80 
     | 
    
         
            +
                        end
         
     | 
| 
      
 81 
     | 
    
         
            +
                      end
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def render_bulleted_list_item(rich_text_array, siblings, children, options = {})
         
     | 
| 
      
 87 
     | 
    
         
            +
                  pre_options = options
         
     | 
| 
      
 88 
     | 
    
         
            +
                  pre_options[:class] = "list-disc break-words #{pre_options[:class]}"
         
     | 
| 
      
 89 
     | 
    
         
            +
                  content_tag(:ul, pre_options) do
         
     | 
| 
      
 90 
     | 
    
         
            +
                    content = content_tag(:li, options) do
         
     | 
| 
      
 91 
     | 
    
         
            +
                      text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end
         
     | 
| 
      
 93 
     | 
    
         
            +
                    if children.present?
         
     | 
| 
      
 94 
     | 
    
         
            +
                      res = children.map do |child|
         
     | 
| 
      
 95 
     | 
    
         
            +
                        render_bulleted_list_item(child.rich_text, child.siblings, child.children, options)
         
     | 
| 
      
 96 
     | 
    
         
            +
                      end
         
     | 
| 
      
 97 
     | 
    
         
            +
                      content += res.join('').html_safe
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
                    content.html_safe
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                def render_numbered_list_item(rich_text_array, siblings, children, options = {})
         
     | 
| 
      
 104 
     | 
    
         
            +
                  pre_options = options
         
     | 
| 
      
 105 
     | 
    
         
            +
                  pre_options[:class] = "list-decimal #{pre_options[:class]}"
         
     | 
| 
      
 106 
     | 
    
         
            +
                  content_tag(:ol, pre_options) do
         
     | 
| 
      
 107 
     | 
    
         
            +
                    render_list_items(:numbered_list_item, rich_text_array, siblings, children, options)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                def render_list_items(type, rich_text_array, siblings, children, options = {})
         
     | 
| 
      
 112 
     | 
    
         
            +
                  content = content_tag(:li, options) do
         
     | 
| 
      
 113 
     | 
    
         
            +
                    text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
                  if children.present?
         
     | 
| 
      
 116 
     | 
    
         
            +
                      res = children.map do |child|
         
     | 
| 
      
 117 
     | 
    
         
            +
                        render_numbered_list_item(child.rich_text, child.siblings, child.children)
         
     | 
| 
      
 118 
     | 
    
         
            +
                      end
         
     | 
| 
      
 119 
     | 
    
         
            +
                      content += res.join('').html_safe
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  if siblings.present?
         
     | 
| 
      
 122 
     | 
    
         
            +
                    content += siblings.map do |sibling|
         
     | 
| 
      
 123 
     | 
    
         
            +
                      render_list_items(type, sibling.rich_text, sibling.siblings, sibling.children, options)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end.join('').html_safe
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  content.html_safe
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                def render_quote(rich_text_array, options = {})
         
     | 
| 
      
 130 
     | 
    
         
            +
                  div_options = options.dup
         
     | 
| 
      
 131 
     | 
    
         
            +
                  pre_options = options.dup
         
     | 
| 
      
 132 
     | 
    
         
            +
                  div_options[:class] = "mt-4 #{options[:class]}"
         
     | 
| 
      
 133 
     | 
    
         
            +
                  content_tag(:div, div_options) do
         
     | 
| 
      
 134 
     | 
    
         
            +
                    pre_options[:class] = "border-l-4 border-black px-5 py-1 #{options[:class]}"
         
     | 
| 
      
 135 
     | 
    
         
            +
                    content_tag(:cite, pre_options) do
         
     | 
| 
      
 136 
     | 
    
         
            +
                      text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 137 
     | 
    
         
            +
                    end
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                def render_callout(rich_text_array, icon, options = {})
         
     | 
| 
      
 142 
     | 
    
         
            +
                  pre_options = options
         
     | 
| 
      
 143 
     | 
    
         
            +
                  pre_options[:class] = "p-4 rounded bg-neutral-200 mt-4 #{pre_options[:class]}"
         
     | 
| 
      
 144 
     | 
    
         
            +
                  content_tag(:div, pre_options) do
         
     | 
| 
      
 145 
     | 
    
         
            +
                    content = tag.span(icon, class: 'pr-2')
         
     | 
| 
      
 146 
     | 
    
         
            +
                    content += text_renderer(rich_text_array).join('').html_safe
         
     | 
| 
      
 147 
     | 
    
         
            +
                    content
         
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
                end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                def render_image(src, expiry_time, caption, type, options = {})
         
     | 
| 
      
 152 
     | 
    
         
            +
                  content_tag(:figure, options) do
         
     | 
| 
      
 153 
     | 
    
         
            +
                    content = tag.img(src:, alt: '')
         
     | 
| 
      
 154 
     | 
    
         
            +
                    content += tag.figcaption(text_renderer(caption).join('').html_safe)
         
     | 
| 
      
 155 
     | 
    
         
            +
                    content
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                def render_video(src, expiry_time, caption, type, options = {})
         
     | 
| 
      
 160 
     | 
    
         
            +
                  content_tag(:figure, options) do
         
     | 
| 
      
 161 
     | 
    
         
            +
                    content = if type == 'file'
         
     | 
| 
      
 162 
     | 
    
         
            +
                      video_tag(src, controls: true)
         
     | 
| 
      
 163 
     | 
    
         
            +
                    elsif type == 'external'
         
     | 
| 
      
 164 
     | 
    
         
            +
                      tag.iframe(src:, allowfullscreen: true, class: 'w-full aspect-video')
         
     | 
| 
      
 165 
     | 
    
         
            +
                    end
         
     | 
| 
      
 166 
     | 
    
         
            +
                    content += tag.figcaption(text_renderer(caption).join('').html_safe)
         
     | 
| 
      
 167 
     | 
    
         
            +
                    content
         
     | 
| 
      
 168 
     | 
    
         
            +
                  end
         
     | 
| 
      
 169 
     | 
    
         
            +
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
              end
         
     | 
| 
      
 171 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module NotionRails
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Service
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @client = Notion::Client.new
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def get_articles(tag: nil, slug: nil)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  query = [
         
     | 
| 
      
 9 
     | 
    
         
            +
                    {
         
     | 
| 
      
 10 
     | 
    
         
            +
                      property: 'public',
         
     | 
| 
      
 11 
     | 
    
         
            +
                      checkbox: {
         
     | 
| 
      
 12 
     | 
    
         
            +
                        equals: true
         
     | 
| 
      
 13 
     | 
    
         
            +
                      }
         
     | 
| 
      
 14 
     | 
    
         
            +
                    },
         
     | 
| 
      
 15 
     | 
    
         
            +
                    {
         
     | 
| 
      
 16 
     | 
    
         
            +
                      property: 'slug',
         
     | 
| 
      
 17 
     | 
    
         
            +
                      rich_text: {
         
     | 
| 
      
 18 
     | 
    
         
            +
                        is_not_empty: true
         
     | 
| 
      
 19 
     | 
    
         
            +
                      }
         
     | 
| 
      
 20 
     | 
    
         
            +
                    }
         
     | 
| 
      
 21 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  query.push({
         
     | 
| 
      
 24 
     | 
    
         
            +
                    property: 'slug',
         
     | 
| 
      
 25 
     | 
    
         
            +
                    rich_text: {
         
     | 
| 
      
 26 
     | 
    
         
            +
                      equals: slug,
         
     | 
| 
      
 27 
     | 
    
         
            +
                    }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  }) if slug
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  query.push({
         
     | 
| 
      
 31 
     | 
    
         
            +
                    property: 'tags',
         
     | 
| 
      
 32 
     | 
    
         
            +
                    multi_select: {
         
     | 
| 
      
 33 
     | 
    
         
            +
                      contains: tag,
         
     | 
| 
      
 34 
     | 
    
         
            +
                    }
         
     | 
| 
      
 35 
     | 
    
         
            +
                  }) if tag
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  pages = @client.database_query(
         
     | 
| 
      
 38 
     | 
    
         
            +
                    database_id: Rails.application.credentials.notion.database_id,
         
     | 
| 
      
 39 
     | 
    
         
            +
                    sorts: [
         
     | 
| 
      
 40 
     | 
    
         
            +
                      {
         
     | 
| 
      
 41 
     | 
    
         
            +
                        property: 'published',
         
     | 
| 
      
 42 
     | 
    
         
            +
                        direction: 'descending'
         
     | 
| 
      
 43 
     | 
    
         
            +
                      }
         
     | 
| 
      
 44 
     | 
    
         
            +
                    ],
         
     | 
| 
      
 45 
     | 
    
         
            +
                    filter: {
         
     | 
| 
      
 46 
     | 
    
         
            +
                      'and': query
         
     | 
| 
      
 47 
     | 
    
         
            +
                    }
         
     | 
| 
      
 48 
     | 
    
         
            +
                  )
         
     | 
| 
      
 49 
     | 
    
         
            +
                  pages['results'].map { |page| Notion::BasePage.new(page) }
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def get_article(id)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  base_page = Notion::BasePage.new(@client.page(page_id: id))
         
     | 
| 
      
 54 
     | 
    
         
            +
                  base_blocks = get_blocks(id)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  Notion::Page.new(base_page, base_blocks)
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def get_blocks(id)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  blocks = @client.block_children(block_id: id)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  parent_list_block_index = nil
         
     | 
| 
      
 61 
     | 
    
         
            +
                  results = []
         
     | 
| 
      
 62 
     | 
    
         
            +
                  blocks['results'].each_with_index do |block, index|
         
     | 
| 
      
 63 
     | 
    
         
            +
                    base_block = Notion::BaseBlock.new(block)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    if base_block.has_children
         
     | 
| 
      
 65 
     | 
    
         
            +
                      base_block.children = get_blocks(base_block.id)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
                    # Notion returns same list items as different blocks so we have to do some processing to have them be related
         
     | 
| 
      
 68 
     | 
    
         
            +
                    # TODO: Separate this into a function, add support for bulleted items.
         
     | 
| 
      
 69 
     | 
    
         
            +
                    #       Currently bulleted items render fine, but they do it in separate ul blocks
         
     | 
| 
      
 70 
     | 
    
         
            +
                    #       Make them appear in the same ul block as numbered_items appear in the same ol block
         
     | 
| 
      
 71 
     | 
    
         
            +
                    if %w[numbered_list_item].include? base_block.type
         
     | 
| 
      
 72 
     | 
    
         
            +
                      siblings = !parent_list_block_index.nil? &&
         
     | 
| 
      
 73 
     | 
    
         
            +
                                  index != parent_list_block_index &&
         
     | 
| 
      
 74 
     | 
    
         
            +
                                  base_block.type == results[parent_list_block_index]&.type &&
         
     | 
| 
      
 75 
     | 
    
         
            +
                                  base_block.parent == results[parent_list_block_index]&.parent
         
     | 
| 
      
 76 
     | 
    
         
            +
                      if siblings
         
     | 
| 
      
 77 
     | 
    
         
            +
                        results[parent_list_block_index].siblings << base_block
         
     | 
| 
      
 78 
     | 
    
         
            +
                        next
         
     | 
| 
      
 79 
     | 
    
         
            +
                      else
         
     | 
| 
      
 80 
     | 
    
         
            +
                        parent_list_block_index = results.length
         
     | 
| 
      
 81 
     | 
    
         
            +
                      end
         
     | 
| 
      
 82 
     | 
    
         
            +
                    else
         
     | 
| 
      
 83 
     | 
    
         
            +
                      parent_list_block_index = nil
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
                    results << base_block
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
                  results
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/notion_rails/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: notion_rails
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Guillermo Aguirre
         
     | 
| 
         @@ -34,6 +34,11 @@ files: 
     | 
|
| 
       34 
34 
     | 
    
         
             
            - LICENSE.txt
         
     | 
| 
       35 
35 
     | 
    
         
             
            - README.md
         
     | 
| 
       36 
36 
     | 
    
         
             
            - lib/notion_rails.rb
         
     | 
| 
      
 37 
     | 
    
         
            +
            - lib/notion_rails/base_block.rb
         
     | 
| 
      
 38 
     | 
    
         
            +
            - lib/notion_rails/base_page.rb
         
     | 
| 
      
 39 
     | 
    
         
            +
            - lib/notion_rails/page.rb
         
     | 
| 
      
 40 
     | 
    
         
            +
            - lib/notion_rails/renderers.rb
         
     | 
| 
      
 41 
     | 
    
         
            +
            - lib/notion_rails/service.rb
         
     | 
| 
       37 
42 
     | 
    
         
             
            - lib/notion_rails/version.rb
         
     | 
| 
       38 
43 
     | 
    
         
             
            homepage: https://github.com/guillermoap/notion-rails
         
     | 
| 
       39 
44 
     | 
    
         
             
            licenses:
         
     |