jekyll-notion 0.1.6 → 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: db8a62e0d2b12f5cedd1f405e289e95a974a22a80e8c4ffd9e0798a75806773a
4
- data.tar.gz: 4668f71e64ff3604223b664a251b22931ce23d889c535b06e39f735891252074
3
+ metadata.gz: f85b870a3e8c0aa6ea64575b8ef8541f61183fa25ced6f41570384057a3a36dd
4
+ data.tar.gz: c66f6d831e8352f029fc1f81608f751aac1ed2b5959b6c2ee19f861eafcdb6f0
5
5
  SHA512:
6
- metadata.gz: ae19056b6cd4692b327d37803bf2c4a7afda07f6736cf2af660c12908694249a34c5e813191843d6ee2aa230f211a4044fbdca1fb203a827f6629aa3707e9e5c
7
- data.tar.gz: a7dd6dea825e2124032ec6900638a913fcc4e05de009798e24b365aa19c41f80fd399316bc6b9f811ea4c8a96e659d9cab11371dff60650752a7bd3aff847df8
6
+ metadata.gz: 26fda79bcfce19d75fda17e6f3e1a90080089c05132359b50f00ec3a4d54d844e6ef583bb558c961209d5818465c6ada865413a33f22fea15fdf943ecd213d8d
7
+ data.tar.gz: 430aa7ef405283f1568eacf4062a90a60fc0e086ae6c7d68cd96cd1eac5f8208d57d8cdebc02b0e98c653d0bff62b119c4ec6ceb4af31777c2a4a28121e0eb55
data/README.md CHANGED
@@ -32,86 +32,87 @@ Export the notion secret token in an environment variable named `NOTION_TOKEN`.
32
32
  $ export NOTION_TOKEN=<secret_...>
33
33
  ```
34
34
 
35
- Once your notion database has been shared, specify the `id` in your `_config.yml` as follows.
35
+ Once your notion database has been shared, specify the database `id` in your `_config.yml` as follows.
36
36
 
37
37
  ```yml
38
38
  notion:
39
- fetch_on_watch: false
40
39
  database:
41
- id: b91d5...
42
- collection: posts
43
- filter: { "property": "Published", "checkbox": { "equals": true } }
44
- sort: { "property": "Last ordered", "direction": "ascending" }
45
- frontmatter:
46
- layout: post
40
+ id: e42383cd-4975-4897-b967-ce453760499f
47
41
  ```
48
42
 
49
- `fetch_on_watch` when set to `true` it allows fetching notion pages on each rebuild. By default is off, pages are only retrieved in the first build.
43
+ ### Mutiple dabatases
44
+
45
+ You can also define multiple databases as follows.
46
+
47
+ ```yml
48
+ collections:
49
+ - recipes
50
+ - films
51
+
52
+ notion:
53
+ databases:
54
+ - id: b0e688e1-99af-4295-ae80-b67eb52f2e2f
55
+ - id: 2190450d-4cb3-4739-a5c8-340c4110fe21
56
+ collection: recipes
57
+ - id: e42383cd-4975-4897-b967-ce453760499f
58
+ collection: films
59
+ ```
60
+
61
+ When no collection is defined, the `posts` collection is used by default.
62
+
63
+ ### Database options
64
+
65
+ Each dabatase support the following options.
50
66
 
51
- `database` properties are:
52
67
  * `id`: the notion database unique identifier,
53
68
  * `collection`: the collection each page belongs to (posts by default),
54
69
  * `filter`: the database query filter,
55
70
  * `sort`: the database query sort,
56
- * `frontmatter`: additional frontmatter to append to each page in the collection.
57
-
58
- Note: Only one notion database is available.
59
71
 
60
- And that's all. Each page in the notion database will be included in the selected collection.
72
+ ```yml
73
+ notion:
74
+ database:
75
+ id: e42383cd-4975-4897-b967-ce453760499f
76
+ collection: posts
77
+ filter: { "property": "Published", "checkbox": { "equals": true } }
78
+ sort: { "property": "Last ordered", "direction": "ascending" }
79
+ ```
61
80
 
62
- ## Notion properties
81
+ ### Watch
63
82
 
64
- Below, page notion default properties are set in each page frontmatter.
83
+ By default, databases are only requested during the first build. Subsequent builds use the results from the cache.
65
84
 
66
- Default properties include `title`, created_time`, `last_edited_time`, `icon` and `cover.
85
+ Set `fetch_on_watch` to true to allow request on each rebuild.
67
86
 
68
- ```
69
- ---
70
- id: b2998...
71
- title: A title
72
- cover: https://img.bank.sh/an_image.jpg
73
- date: 2022-01-23T12:31:00.000Z
74
- icon: \U0001F4A5
75
- ---
87
+ ```yml
88
+ notion:
89
+ fetch_on_watch: true
90
+ database:
91
+ id: e42383cd-4975-4897-b967-ce453760499f
76
92
  ```
77
93
 
78
- Any property provided in the frontmatter config that matches a default property will be overwritten by the default value.
94
+ And that's all. Each page in the notion database will be included in the selected collection.
79
95
 
80
- ### Custom properties
96
+ ## Notion properties
81
97
 
82
- In addition to default properties, custom properties are also supported.
98
+ Below, default properties per notion page are set for each document front matter.
83
99
 
84
- Custom properties are appended to page frontmatter by default. Every property name is snake-cased.
85
- For example, two properties named `Multiple Options` and `Tags` will be transformed to `multiple_options` and `tags`, respectively.
100
+ Notion page properties are `id`, `title`, `created_time`, `last_edited_time`, `icon`, `cover` and `archived`.
86
101
 
87
102
  ```
88
103
  ---
89
- id: b2998...
90
- title: A title
104
+ id: e42383cd-4975-4897-b967-ce453760499f
105
+ title: An amazing post
91
106
  cover: https://img.bank.sh/an_image.jpg
92
107
  date: 2022-01-23T12:31:00.000Z
93
- icon: \U0001F4A5
94
- tags: tag1, tag2, tag3
95
- multiple_options: option1, option2
108
+ icon: 💥
109
+ archived: false
96
110
  ---
97
111
  ```
98
112
 
99
- The supported properties are:
100
-
101
- * `number`
102
- * `select`
103
- * `multi_select`
104
- * `date`
105
- * `people`
106
- * `files`
107
- * `checkbox`
108
- * `url`
109
- * `email`
110
- * `phone_number`
111
-
112
- `created_by`, `last_edited_by`, `rich_text` as advanced types like `formula`, `relation` and `rollup` are not supported.
113
+ In addition to default properties, custom properties are also appended to front matter.
113
114
 
114
- Check notion documentation about [property values](https://developers.notion.com/reference/property-value-object#all-property-values).
115
+ Please, refer to the [notion_to_md](https://github.com/emoriarty/notion_to_md/) gem to learn more.
115
116
 
116
117
  ## Page filename
117
118
 
@@ -0,0 +1,67 @@
1
+ module JekyllNotion
2
+ class CollectionGenerator
3
+ def initialize(db:, site:)
4
+ @db = db
5
+ @site = site
6
+ end
7
+
8
+ def generate
9
+ @db.pages.each do |page|
10
+ next if file_exists?(make_path(page))
11
+
12
+ collection.docs << make_doc(page)
13
+ log_new_page(page)
14
+ end
15
+ collection
16
+ end
17
+
18
+ def collection
19
+ @site.collections[@db.collection]
20
+ end
21
+
22
+ private
23
+
24
+ # Checks if a file already exists in the site source
25
+ def file_exists?(file_path)
26
+ File.exist? @site.in_source_dir(file_path)
27
+ end
28
+
29
+ def make_doc(page)
30
+ new_post = DocumentWithoutAFile.new(
31
+ make_path(page),
32
+ { :site => @site, :collection => collection }
33
+ )
34
+ new_post.content = make_md(page)
35
+ new_post.read
36
+ new_post
37
+ end
38
+
39
+ def make_path(page)
40
+ "_#{@db.collection}/#{make_filename(page)}"
41
+ end
42
+
43
+ def make_filename(page)
44
+ if @db.collection == "posts"
45
+ "#{page.created_time.to_date}-#{Jekyll::Utils.slugify(page.title,
46
+ :mode => "latin")}.md"
47
+ else
48
+ "#{page.title.downcase.parameterize}.md"
49
+ end
50
+ end
51
+
52
+ def make_md(page)
53
+ NotionToMd::Converter.new(:page_id => page.id).convert(:frontmatter => true)
54
+ end
55
+
56
+ def log_new_page(page)
57
+ Jekyll.logger.info("Jekyll Notion:", "Page => #{page.title}")
58
+ if @site.config.dig(
59
+ "collections", @db.collection, "output"
60
+ )
61
+ Jekyll.logger.info("",
62
+ "Path => #{collection.docs.last.path}")
63
+ end
64
+ Jekyll.logger.debug("", "Props => #{collection.docs.last.data.keys.inspect}")
65
+ end
66
+ end
67
+ end
@@ -2,81 +2,37 @@
2
2
 
3
3
  module JekyllNotion
4
4
  class Generator < Jekyll::Generator
5
- attr_reader :current_page
5
+ attr_reader :current_page, :current_db
6
6
 
7
7
  def generate(site)
8
8
  @site = site
9
9
 
10
10
  return unless notion_token? && config?
11
11
 
12
- if fetch_on_watch? || docs.empty?
12
+ if fetch_on_watch? || collections.empty?
13
13
  read_notion_database
14
14
  else
15
- collection.docs = docs
15
+ collections.each_pair { |key, val| @site.collections[key] = val }
16
16
  end
17
17
  end
18
18
 
19
- def read_notion_database
20
- @db = NotionDatabase.new(:config => config)
21
- @db.pages.each do |page|
22
- @current_page = page
23
- collection.docs << make_page
24
- Jekyll.logger.info("Jekyll Notion:", "New notion page at #{collection.docs.last.path}")
25
- end
26
- @docs = collection.docs
27
- end
28
-
29
- def docs
30
- @docs ||= []
31
- end
32
-
33
- def make_page
34
- new_post = DocumentWithoutAFile.new(
35
- "#{Dir.pwd}/_#{collection_name}/#{make_filename}",
36
- { :site => @site, :collection => collection }
37
- )
38
- new_post.content = "#{make_frontmatter}\n\n#{make_md}"
39
- new_post.read
40
- new_post
41
- end
42
-
43
- def make_md
44
- NotionToMd::Converter.new(:page_id => current_page.id).convert
45
- end
19
+ protected
46
20
 
47
- def make_frontmatter
48
- data = Jekyll::Utils.deep_merge_hashes(config_frontmatter, page_frontmatter)
49
- frontmatter = data.to_a.map { |k, v| "#{k}: #{v}" }.join("\n")
50
- <<~CONTENT
51
- ---
52
- #{frontmatter}
53
- ---
54
- CONTENT
55
- end
56
-
57
- def page_frontmatter
58
- Jekyll::Utils.deep_merge_hashes(current_page.custom_props, current_page.default_props)
59
- end
60
-
61
- def config_frontmatter
62
- config.dig("database", "frontmatter") || {}
63
- end
64
-
65
- def make_filename
66
- if collection_name == "posts"
67
- "#{current_page.created_date}-#{Jekyll::Utils.slugify(current_page.title,
68
- :mode => "latin")}.md"
69
- else
70
- "#{current_page.title.downcase.parameterize}.md"
21
+ def read_notion_database
22
+ databases.each do |db_config|
23
+ db = NotionDatabase.new(:config => db_config)
24
+ new_collection = CollectionGenerator.new(:db => db, :site => @site).generate
25
+ # Caching current collection
26
+ collections[db.collection] = new_collection
71
27
  end
72
28
  end
73
29
 
74
- def collection_name
75
- config.dig("database", "collection") || "posts"
30
+ def databases
31
+ config["databases"] || [config["database"]]
76
32
  end
77
33
 
78
- def collection
79
- @site.collections[collection_name]
34
+ def collections
35
+ @collections ||= {}
80
36
  end
81
37
 
82
38
  def config
@@ -84,7 +40,7 @@ module JekyllNotion
84
40
  end
85
41
 
86
42
  def fetch_on_watch?
87
- config["fetch_on_watch"].present?
43
+ config["fetch_on_watch"] == true
88
44
  end
89
45
 
90
46
  def notion_token?
@@ -11,28 +11,32 @@ module JekyllNotion
11
11
  return [] unless id?
12
12
 
13
13
  @pages ||= @notion.database_query(query)[:results].map do |page|
14
- NotionPage.new(:page => page, :layout => config["layout"])
14
+ NotionToMd::Page.new(:page => page)
15
15
  end
16
16
  end
17
17
 
18
- private
19
-
20
18
  def config
21
- @config["database"]
19
+ @config || {}
22
20
  end
23
21
 
24
22
  def filter
25
- @config.dig("database", "filter")
23
+ config["filter"]
26
24
  end
27
25
 
28
26
  def sort
29
- @config.dig("database", "sort")
27
+ config["sort"]
30
28
  end
31
29
 
32
30
  def id
33
- @config.dig("database", "id")
31
+ config["id"]
32
+ end
33
+
34
+ def collection
35
+ config["collection"] || "posts"
34
36
  end
35
37
 
38
+ private
39
+
36
40
  def id?
37
41
  if id.nil? || id.empty?
38
42
  Jekyll.logger.warn("Jekyll Notion:",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllNotion
4
- VERSION = "0.1.6"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/jekyll-notion.rb CHANGED
@@ -4,8 +4,6 @@ require "jekyll"
4
4
  require "notion"
5
5
  require "notion_to_md"
6
6
  require "logger"
7
- require "active_support/inflector"
8
- require "active_support/core_ext/object/blank"
9
7
  require "jekyll-notion/generator"
10
8
 
11
9
  NotionToMd::Logger.level = Logger::ERROR
@@ -15,7 +13,7 @@ Notion.configure do |config|
15
13
  end
16
14
 
17
15
  module JekyllNotion
16
+ autoload :CollectionGenerator, "jekyll-notion/collection_generator"
18
17
  autoload :DocumentWithoutAFile, "jekyll-notion/document_without_a_file"
19
18
  autoload :NotionDatabase, "jekyll-notion/notion_database"
20
- autoload :NotionPage, "jekyll-notion/notion_page"
21
19
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-notion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
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-05 00:00:00.000000000 Z
11
+ date: 2022-02-17 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'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: jekyll
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -124,10 +110,10 @@ extra_rdoc_files:
124
110
  files:
125
111
  - README.md
126
112
  - lib/jekyll-notion.rb
113
+ - lib/jekyll-notion/collection_generator.rb
127
114
  - lib/jekyll-notion/document_without_a_file.rb
128
115
  - lib/jekyll-notion/generator.rb
129
116
  - lib/jekyll-notion/notion_database.rb
130
- - lib/jekyll-notion/notion_page.rb
131
117
  - lib/jekyll-notion/version.rb
132
118
  homepage: https://github.com/emoriarty/jekyll-notion
133
119
  licenses:
@@ -1,123 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JekyllNotion
4
- class NotionPage
5
- attr_reader :page, :layout
6
-
7
- def initialize(page:, layout:)
8
- @page = page
9
- @layout = layout
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_date
31
- created_datetime.to_date
32
- end
33
-
34
- def created_datetime
35
- DateTime.parse(page["created_time"])
36
- end
37
-
38
- def updated_date
39
- updated_datetime.to_date
40
- end
41
-
42
- def updated_datetime
43
- DateTime.parse(page["last_edited_time"])
44
- end
45
-
46
- def url
47
- page[:url]
48
- end
49
-
50
- def custom_props
51
- @custom_props ||= page.properties.each_with_object({}) do |prop, memo|
52
- name = prop.first
53
- value = prop.last # Notion::Messages::Message
54
- type = value.type
55
-
56
- next memo unless CustomProperty.respond_to?(type.to_sym)
57
-
58
- memo[name.parameterize.underscore] = CustomProperty.send(type, value)
59
- end.reject { |_k, v| v.presence.nil? }
60
- end
61
-
62
- def default_props
63
- @default_props ||= {
64
- :id => id,
65
- :title => title,
66
- :date => created_datetime,
67
- :cover => cover,
68
- :icon => icon,
69
- :updated_date => updated_datetime,
70
- }
71
- end
72
-
73
- class CustomProperty
74
- class << self
75
- def multi_select(prop)
76
- multi_select = prop.multi_select.map(&:name).join(", ")
77
- "[#{multi_select}]"
78
- end
79
-
80
- def select(prop)
81
- prop["select"].name
82
- end
83
-
84
- def people(prop)
85
- people = prop.people.map(&:name).join(", ")
86
- "[#{people}]"
87
- end
88
-
89
- def files(prop)
90
- files = prop.files.map { |f| f.file.url }.join(", ")
91
- "[#{files}]"
92
- end
93
-
94
- def phone_number(prop)
95
- prop.phone_number
96
- end
97
-
98
- def number(prop)
99
- prop.number
100
- end
101
-
102
- def email(prop)
103
- prop.email
104
- end
105
-
106
- def checkbox(prop)
107
- prop.checkbox.to_s
108
- end
109
-
110
- # date type properties not supported:
111
- # - end
112
- # - time_zone
113
- def date(prop)
114
- prop.date.start
115
- end
116
-
117
- def url(prop)
118
- prop.url
119
- end
120
- end
121
- end
122
- end
123
- end