notion_to_md 2.5.0 → 3.0.0.beta1

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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: notion_to_md
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 3.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Enrique Arias
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-10 00:00:00.000000000 Z
11
+ date: 2025-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '7'
27
- - !ruby/object:Gem::Dependency
28
- name: callee
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 0.3.6
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 0.3.6
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: notion-ruby-client
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -53,89 +39,19 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: '1'
55
41
  - !ruby/object:Gem::Dependency
56
- name: hashie
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop
42
+ name: zeitwerk
85
43
  requirement: !ruby/object:Gem::Requirement
86
44
  requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop-rspec
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: simplecov
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: vcr
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
45
+ - - "~>"
130
46
  - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
47
+ version: '2.6'
48
+ type: :runtime
133
49
  prerelease: false
134
50
  version_requirements: !ruby/object:Gem::Requirement
135
51
  requirements:
136
- - - ">="
52
+ - - "~>"
137
53
  - !ruby/object:Gem::Version
138
- version: '0'
54
+ version: '2.6'
139
55
  description: Notion Markdown Exporter in Ruby
140
56
  email: emoriarty81@gmail.com
141
57
  executables: []
@@ -144,33 +60,38 @@ extra_rdoc_files: []
144
60
  files:
145
61
  - README.md
146
62
  - lib/notion_to_md.rb
147
- - lib/notion_to_md/blocks.rb
148
63
  - lib/notion_to_md/blocks/block.rb
149
- - lib/notion_to_md/blocks/builder.rb
150
64
  - lib/notion_to_md/blocks/bulleted_list_block.rb
151
65
  - lib/notion_to_md/blocks/bulleted_list_item_block.rb
152
66
  - lib/notion_to_md/blocks/factory.rb
153
67
  - lib/notion_to_md/blocks/normalizer.rb
154
68
  - lib/notion_to_md/blocks/numbered_list_block.rb
155
69
  - lib/notion_to_md/blocks/numbered_list_item_block.rb
70
+ - lib/notion_to_md/blocks/renderer.rb
156
71
  - lib/notion_to_md/blocks/table_block.rb
157
72
  - lib/notion_to_md/blocks/table_row_block.rb
158
73
  - lib/notion_to_md/blocks/to_do_list_block.rb
159
74
  - lib/notion_to_md/blocks/to_do_list_item_block.rb
160
- - lib/notion_to_md/blocks/types.rb
161
- - lib/notion_to_md/converter.rb
162
- - lib/notion_to_md/helpers.rb
163
- - lib/notion_to_md/helpers/yaml_sanitizer.rb
75
+ - lib/notion_to_md/database.rb
76
+ - lib/notion_to_md/database/builder.rb
164
77
  - lib/notion_to_md/logger.rb
78
+ - lib/notion_to_md/metadata_type.rb
165
79
  - lib/notion_to_md/page.rb
166
- - lib/notion_to_md/page_property.rb
80
+ - lib/notion_to_md/page/builder.rb
81
+ - lib/notion_to_md/support/frontmatter.rb
82
+ - lib/notion_to_md/support/metadata_properties.rb
83
+ - lib/notion_to_md/support/pagination.rb
84
+ - lib/notion_to_md/support/yaml_sanitizer.rb
167
85
  - lib/notion_to_md/text.rb
168
86
  - lib/notion_to_md/text_annotation.rb
169
87
  - lib/notion_to_md/version.rb
170
88
  homepage: https://github.com/emoriarty/notion_to_md
171
89
  licenses:
172
90
  - MIT
173
- metadata: {}
91
+ metadata:
92
+ rubygems_mfa_required: 'true'
93
+ status: beta
94
+ source_code_uri: https://github.com/emoriarty/notion_to_md
174
95
  post_install_message:
175
96
  rdoc_options: []
176
97
  require_paths:
@@ -179,12 +100,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
179
100
  requirements:
180
101
  - - ">="
181
102
  - !ruby/object:Gem::Version
182
- version: '0'
103
+ version: 2.7.0
183
104
  required_rubygems_version: !ruby/object:Gem::Requirement
184
105
  requirements:
185
- - - ">="
106
+ - - ">"
186
107
  - !ruby/object:Gem::Version
187
- version: '0'
108
+ version: 1.3.1
188
109
  requirements: []
189
110
  rubygems_version: 3.1.6
190
111
  signing_key:
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class NotionToMd
4
- module Blocks
5
- class Builder
6
- ##
7
- # Array containing the block types allowed to have nested blocks (children).
8
- BLOCKS_WITH_PERMITTED_CHILDREN = %i[
9
- bulleted_list_item
10
- numbered_list_item
11
- paragraph
12
- to_do
13
- table
14
- ].freeze
15
-
16
- # === Parameters
17
- # block::
18
- # A {Notion::Messages::Message}[https://github.com/orbit-love/notion-ruby-client/blob/main/lib/notion/messages/message.rb] object.
19
- #
20
- # === Returns
21
- # A boolean indicating if the blocked passed in
22
- # is permitted to have children based on its type.
23
- #
24
- def self.permitted_children_for?(block:)
25
- BLOCKS_WITH_PERMITTED_CHILDREN.include?(block.type.to_sym) && block.has_children
26
- end
27
-
28
- attr_reader :block_id, :fetch_blocks
29
-
30
- # === Parameters
31
- # block_id::
32
- # A string representing a notion block id .
33
- # fetch_blocks::
34
- # A block that fetches the blocks from the Notion API.
35
- #
36
- # === Returns
37
- # An array of NotionToMd::Blocks::Block.
38
- #
39
- def initialize(block_id:, &fetch_blocks)
40
- @block_id = block_id
41
- @fetch_blocks = fetch_blocks
42
- end
43
-
44
- # === Parameters
45
- #
46
- # === Returns
47
- # An array of NotionToMd::Blocks::Block.
48
- #
49
- def build
50
- notion_messages = fetch_blocks.call(block_id)
51
- blocks = notion_messages.results.map do |block|
52
- children = if Builder.permitted_children_for?(block: block)
53
- Builder.new(block_id: block.id, &fetch_blocks).build
54
- else
55
- []
56
- end
57
- Factory.build(block: block, children: children)
58
- end
59
-
60
- Normalizer.normalize(blocks: blocks)
61
- end
62
- end
63
- end
64
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './blocks/builder'
4
- require_relative './blocks/normalizer'
5
- require_relative './blocks/factory'
6
- require_relative './blocks/types'
7
- require_relative './blocks/block'
8
- require_relative './blocks/table_block'
9
- require_relative './blocks/table_row_block'
10
- require_relative './blocks/bulleted_list_block'
11
- require_relative './blocks/bulleted_list_item_block'
12
- require_relative './blocks/numbered_list_block'
13
- require_relative './blocks/numbered_list_item_block'
14
- require_relative './blocks/to_do_list_block'
15
- require_relative './blocks/to_do_list_item_block'
16
-
17
- class NotionToMd
18
- module Blocks
19
- # === Parameters
20
- # block_id::
21
- # A string representing a notion block id .
22
- # fetch_blocks::
23
- # A block that fetches the blocks from the Notion API.
24
- #
25
- # === Returns
26
- # An array of NotionToMd::Blocks::Block.
27
- #
28
- def self.build(block_id:, &fetch_blocks)
29
- Builder.new(block_id: block_id, &fetch_blocks).build
30
- end
31
- end
32
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class NotionToMd
4
- # The Converter class allows to transform notion pages to markdown documents.
5
- # Just create a new Converter instance by providing the page_id:
6
- # page_converter = NotionToMd::Converter.new(page_id: '9dc17c9c9d2e469dbbf0f9648f3288d3')
7
- # Then, call for convert to obtain the markdown document:
8
- # page_converter.convert
9
- class Converter
10
- include Callee
11
-
12
- attr_reader :page_id, :frontmatter
13
-
14
- # === Parameters
15
- # page_id::
16
- # A string representing the notion page id.
17
- # token::
18
- # The notion API secret token. The token can replaced by the environment variable NOTION_TOKEN.
19
- #
20
- # === Returns
21
- # A NotionToMd::Converter object.
22
- #
23
- def initialize(page_id:, token: nil, frontmatter: false)
24
- @notion = Notion::Client.new(token: token || ENV['NOTION_TOKEN'])
25
- @page_id = page_id
26
- @frontmatter = frontmatter
27
- end
28
-
29
- # === Parameters
30
- # frontmatter::
31
- # A boolean value that indicates whether the front matter block is included in the markdown document.
32
- #
33
- # === Returns
34
- # The string that represent the markdown document.
35
- #
36
- def convert(frontmatter: false)
37
- md_page = Page.new(page: page, blocks: page_blocks)
38
- <<~MD
39
- #{md_page.frontmatter if frontmatter}
40
- #{md_page.body}
41
- MD
42
- end
43
-
44
- def call
45
- md = convert frontmatter: frontmatter
46
-
47
- yield md if block_given?
48
-
49
- md
50
- end
51
-
52
- private
53
-
54
- def page
55
- @page ||= @notion.page(page_id: page_id)
56
- end
57
-
58
- def page_blocks
59
- @page_blocks ||= build_blocks(block_id: page_id)
60
- end
61
-
62
- def build_blocks(block_id:)
63
- Blocks.build(block_id: block_id) do |nested_block_id|
64
- fetch_blocks(block_id: nested_block_id)
65
- end
66
- end
67
-
68
- def fetch_blocks(block_id:)
69
- @notion.block_children(block_id: block_id)
70
- end
71
- end
72
- end
@@ -1,17 +0,0 @@
1
- class NotionToMd
2
- module Helpers
3
- module YamlSanitizer
4
- # Escape the frontmatter value if it contains a colon or a dash followed by a space
5
- # @param value [String] the value to escape
6
- # @return [String] the escaped value
7
- def escape_frontmatter_value(value)
8
- if value.match?(/: |-\s/)
9
- # Escape the double quotes inside the string
10
- "\"#{value.gsub('"', '\"')}\""
11
- else
12
- value
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1 +0,0 @@
1
- require_relative './helpers/yaml_sanitizer'
@@ -1,106 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class NotionToMd
4
- class PageProperty
5
- class << self
6
- include Helpers::YamlSanitizer
7
-
8
- def file(prop)
9
- prop.dig(:file, :url)
10
- rescue NoMethodError
11
- nil
12
- end
13
-
14
- def external(prop)
15
- prop.dig(:external, :url)
16
- rescue NoMethodError
17
- nil
18
- end
19
-
20
- def emoji(prop)
21
- prop[:emoji]
22
- rescue NoMethodError
23
- nil
24
- end
25
-
26
- def multi_select(prop)
27
- prop[:multi_select].map { |sel| sel[:name] }
28
- rescue NoMethodError
29
- nil
30
- end
31
-
32
- def select(prop)
33
- escape_frontmatter_value(prop.dig(:select, :name))
34
- rescue NoMethodError
35
- nil
36
- end
37
-
38
- def people(prop)
39
- prop[:people].map { |sel| sel[:name] }
40
- rescue NoMethodError
41
- nil
42
- end
43
-
44
- def files(prop)
45
- prop[:files].map { |f| file(f) || external(f) }
46
- rescue NoMethodError
47
- nil
48
- end
49
-
50
- def phone_number(prop)
51
- prop[:phone_number]
52
- rescue NoMethodError
53
- nil
54
- end
55
-
56
- def number(prop)
57
- prop[:number]
58
- rescue NoMethodError
59
- nil
60
- end
61
-
62
- def email(prop)
63
- prop[:email]
64
- rescue NoMethodError
65
- nil
66
- end
67
-
68
- def checkbox(prop)
69
- prop[:checkbox].nil? ? nil : prop[:checkbox].to_s
70
- rescue NoMethodError
71
- nil
72
- end
73
-
74
- # date type properties not supported:
75
- # - end
76
- # - time_zone
77
- def date(prop)
78
- date = prop.dig(:date, :start)
79
-
80
- case date
81
- when Date
82
- date.to_time
83
- when String
84
- Time.parse(date)
85
- else
86
- date # Time or nil
87
- end
88
- rescue NoMethodError
89
- nil
90
- end
91
-
92
- def url(prop)
93
- prop[:url]
94
- rescue NoMethodError
95
- nil
96
- end
97
-
98
- def rich_text(prop)
99
- text = prop[:rich_text].map { |text| text[:plain_text] }.join
100
- text.blank? ? nil : escape_frontmatter_value(text)
101
- rescue NoMethodError
102
- nil
103
- end
104
- end
105
- end
106
- end