notion_to_md 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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