notion_to_md 0.1.0 → 1.0.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: 77ebe548eec487347104eabbac6911836cef0ec6e5ea350cb9a376ef8e07ce50
4
- data.tar.gz: b2fd0700b53683daa6e59a729418139bbdee41da8184dad57eff0f2c17578dc7
3
+ metadata.gz: 924eafad078f99447e1a9d88403d48448e5011c87a9d2ae32b527a9e4a201f85
4
+ data.tar.gz: 791bf46ea8cfbb49958cc80862fe63047e1158f4845f21665ce21d20b37628ad
5
5
  SHA512:
6
- metadata.gz: e7f09feec62553d76c72e670aa4fa05d02e98f19e74352237c8c42a255960570f77ae530b3196be24a054fa8a55f744f0b0b96dfbfb1c5e7d06f71b1423bcdf6
7
- data.tar.gz: '09a041dab71e1fea3796ca9193c6a5fdf385de1d7fc212373f2e7cec086568935c72171ba900c90001907fdd4e1667e819b69c28740c2e5fa18a4b17821facb3'
6
+ metadata.gz: e50e6688db3930ecca7c808d357fe07799465dfa5274a6b0141d97de5adb204f361782240c35152c21165eb8e68cdbf44a04e696006cd345293948825a2a74da
7
+ data.tar.gz: 349e89d00109d05b7dfe24499a80dc0318cf6895524e527b025ef02325bc27f06775544f20a995166cef1229b62aacd6344c1331c2c7549eb01f3be5181198cb
data/README.md CHANGED
@@ -40,7 +40,60 @@ md = notion_converter.convert
40
40
 
41
41
  And that's all. The `md` is a string variable containing the notion page formatted in markdown.
42
42
 
43
+
44
+ ### Front matter
45
+
46
+ From version 0.2.0, notion_to_md supports front matter in markdown files.
47
+
48
+ By default, the front matter section is not included to the document. To do so, provide the `:frontmatter` option set to `true` to `convert` method.
49
+
50
+ ```ruby
51
+ NotionToMd::Converter.new(page_id: 'b91d5...').convert(frontmatter: tue)
52
+ ```
53
+
54
+ Default notion properties are page `id`, `title`, `created_time`, `last_edited_time`, `icon`, `archived` and `cover`.
55
+
56
+ ```yml
57
+ ---
58
+ id: e42383cd-4975-4897-b967-ce453760499f
59
+ title: An amazing post
60
+ cover: https://img.bank.sh/an_image.jpg
61
+ created_time: 2022-01-23T12:31:00.000Z
62
+ last_edited_time: 2022-01-23T12:31:00.000Z
63
+ icon: 💥
64
+ archived: false
65
+ ---
66
+ ```
67
+
68
+ In addition to default properties, custom properties are also supported.
69
+ Custom properties name is [parameterized](https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize) and [underscorized](https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-underscore) before added to front matter.
70
+ For example, two properties named `Multiple Options` and `Tags` will be transformed to `multiple_options` and `tags`, respectively.
71
+
72
+ ```yml
73
+ ---
74
+ tags: tag1, tag2, tag3
75
+ multiple_options: option1, option2
76
+ ---
77
+ ```
78
+
79
+ The supported property types are:
80
+
81
+ * `number`
82
+ * `select`
83
+ * `multi_select`
84
+ * `date`
85
+ * `people`
86
+ * `files`
87
+ * `checkbox`
88
+ * `url`
89
+ * `email`
90
+ * `phone_number`
91
+
92
+ `rich_text` as advanced types like `formula`, `relation` and `rollup` are not supported.
93
+
94
+ Check notion documentation about [property values](https://developers.notion.com/reference/property-value-object#all-property-values) to know more.
95
+
43
96
  ## Test
44
97
  ```bash
45
- $ ruby -Ilib:test test/notion_to_md/converter_spec.rb
98
+ rspec
46
99
  ```
@@ -9,25 +9,20 @@ module NotionToMd
9
9
  @page_id = page_id
10
10
  end
11
11
 
12
- def convert
13
- md = page_blocks[:results].map do |block|
14
- next Block.blank if block[:type] == 'paragraph' && block.dig(:paragraph, :text).empty?
15
-
16
- block_type = block[:type].to_sym
17
-
18
- begin
19
- Block.send(block_type, block[block_type])
20
- rescue StandardError
21
- Logger.info("Unsupported block type: #{block_type}")
22
- next nil
23
- end
24
- end
25
- Logger.info("Notion page #{page_id} converted to markdown")
26
- md.compact.join("\n\n")
12
+ def convert(frontmatter: false)
13
+ md_page = Page.new(page: page, blocks: page_blocks)
14
+ <<~MD
15
+ #{md_page.frontmatter if frontmatter}
16
+ #{md_page.body}
17
+ MD
27
18
  end
28
19
 
29
20
  private
30
21
 
22
+ def page
23
+ @page ||= @notion.page(id: page_id)
24
+ end
25
+
31
26
  def page_blocks
32
27
  @page_blocks ||= @notion.block_children(id: page_id)
33
28
  end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionToMd
4
+ class Page
5
+ attr_reader :page, :blocks
6
+
7
+ def initialize(page:, blocks:)
8
+ @page = page
9
+ @blocks = blocks
10
+ end
11
+
12
+ def title
13
+ page.dig(:properties, :Name, :title).inject('') do |acc, slug|
14
+ acc + slug[:plain_text]
15
+ end
16
+ end
17
+
18
+ def cover
19
+ page.dig(:cover, :external, :url)
20
+ end
21
+
22
+ def icon
23
+ page.dig(:icon, :emoji)
24
+ end
25
+
26
+ def id
27
+ page[:id]
28
+ end
29
+
30
+ def created_time
31
+ DateTime.parse(page['created_time'])
32
+ end
33
+
34
+ def last_edited_time
35
+ DateTime.parse(page['last_edited_time'])
36
+ end
37
+
38
+ def url
39
+ page[:url]
40
+ end
41
+
42
+ def archived
43
+ page[:archived]
44
+ end
45
+
46
+ def body
47
+ @body ||= blocks[:results].map do |block|
48
+ next Block.blank if block[:type] == 'paragraph' && block.dig(:paragraph, :text).empty?
49
+
50
+ block_type = block[:type].to_sym
51
+
52
+ begin
53
+ Block.send(block_type, block[block_type])
54
+ rescue StandardError
55
+ Logger.info("Unsupported block type: #{block_type}")
56
+ next nil
57
+ end
58
+ end.compact.join("\n\n")
59
+ end
60
+
61
+ def frontmatter
62
+ @frontmatter ||= <<~CONTENT
63
+ ---
64
+ #{props.to_a.map do |k, v|
65
+ "#{k}: #{v}"
66
+ end.join("\n")}
67
+ ---
68
+ CONTENT
69
+ end
70
+
71
+ def props
72
+ @props ||= custom_props.deep_merge(default_props)
73
+ end
74
+
75
+ def custom_props
76
+ @custom_props ||= page.properties.each_with_object({}) do |prop, memo|
77
+ name = prop.first
78
+ value = prop.last # Notion::Messages::Message
79
+ type = value.type
80
+
81
+ next memo unless CustomProperty.respond_to?(type.to_sym)
82
+
83
+ memo[name.parameterize.underscore] = CustomProperty.send(type, value)
84
+ end.reject { |_k, v| v.presence.nil? }
85
+ end
86
+
87
+ def default_props
88
+ @default_props ||= {
89
+ 'id' => id,
90
+ 'title' => title,
91
+ 'created_time' => created_time,
92
+ 'cover' => cover,
93
+ 'icon' => icon,
94
+ 'last_edited_time' => last_edited_time,
95
+ 'archived' => archived
96
+ }
97
+ end
98
+
99
+ class CustomProperty
100
+ class << self
101
+ def multi_select(prop)
102
+ prop.multi_select.map(&:name)
103
+ end
104
+
105
+ def select(prop)
106
+ prop['select'].name
107
+ end
108
+
109
+ def people(prop)
110
+ prop.people.map(&:name)
111
+ end
112
+
113
+ def files(prop)
114
+ prop.files.map { |f| f.file.url }
115
+ end
116
+
117
+ def phone_number(prop)
118
+ prop.phone_number
119
+ end
120
+
121
+ def number(prop)
122
+ prop.number
123
+ end
124
+
125
+ def email(prop)
126
+ prop.email
127
+ end
128
+
129
+ def checkbox(prop)
130
+ prop.checkbox.to_s
131
+ end
132
+
133
+ # date type properties not supported:
134
+ # - end
135
+ # - time_zone
136
+ def date(prop)
137
+ prop.date.start
138
+ end
139
+
140
+ def url(prop)
141
+ prop.url
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NotionToMd
4
- VERSION = '0.1.0'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/notion_to_md.rb CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  require 'notion'
4
4
  require 'logger'
5
+ require 'active_support/inflector'
6
+ require 'active_support/core_ext/object/blank'
5
7
  require_relative './notion_to_md/version'
6
8
  require_relative './notion_to_md/converter'
7
9
  require_relative './notion_to_md/logger'
10
+ require_relative './notion_to_md/page'
8
11
  require_relative './notion_to_md/block'
9
12
  require_relative './notion_to_md/text'
10
13
  require_relative './notion_to_md/text_annotation'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: notion_to_md
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Enrique Arias
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-13 00:00:00.000000000 Z
11
+ date: 2022-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: notion-ruby-client
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -77,6 +91,7 @@ files:
77
91
  - lib/notion_to_md/block.rb
78
92
  - lib/notion_to_md/converter.rb
79
93
  - lib/notion_to_md/logger.rb
94
+ - lib/notion_to_md/page.rb
80
95
  - lib/notion_to_md/text.rb
81
96
  - lib/notion_to_md/text_annotation.rb
82
97
  - lib/notion_to_md/version.rb