jekyll-notion 0.2.1 → 1.1.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: 1c220aa475033e8ddb50ef928b9104c3b8d5da793bbe777062783eb5fbd1491e
4
- data.tar.gz: c99b1e1b3cebbc00420d8b857e545fa9ae6ac83aad4da110fabf780a0c42a816
3
+ metadata.gz: 043b3ae753a651d756c95dc6372af86589106030dd3d41d8b886ccc95c5d5d7a
4
+ data.tar.gz: 5a6bf3508185e27978836cd1158ef70a080d53be183c642d7948015f6d7de215
5
5
  SHA512:
6
- metadata.gz: 74c1c36de04d025b121fce5634bfdd739796880208114e1dcdac9f49ec2302b16188f54abb1f8bafc07b3911627a2753e6e6c8d750559384ea9bfb94f1c25cb0
7
- data.tar.gz: a42ae853c9371cd60ffd6e4cd00cc47e02c9eee64d44579ec1ea88f1e4c0e64208a536cec7bc2fea0c6ab1b6ea00b6dcdde23d5aa1110190b48e7e3b6bceabc3
6
+ metadata.gz: 74e147fe3f6f91a88bafb24f273284bb71d42f39f207c48f85577229aebb6ceb6de6cbe331b48e6f99afb6191466e9f27d436fb45bc710104a0ac3a80e016c6c
7
+ data.tar.gz: 2257337e331db87e4594e5117739ea7e1082739b3f497a4c63bba7f2dc79d2c173a484fc574ea20eb40d8650c14c84a607c9e17cef9f49174ff97bf79edab73e
data/README.md CHANGED
@@ -40,6 +40,8 @@ notion:
40
40
  id: e42383cd-4975-4897-b967-ce453760499f
41
41
  ```
42
42
 
43
+ After running `jekyll build` (or `serve`) command, the `posts` collection is loaded with pages of the notion database specified in the configuration.
44
+
43
45
  ### Mutiple dabatases
44
46
 
45
47
  You can also define multiple databases as follows.
@@ -58,7 +60,20 @@ notion:
58
60
  collection: films
59
61
  ```
60
62
 
61
- When no collection is defined, the `posts` collection is used by default.
63
+ In this example, the notion database `b0e688e1-99af-4295-ae80-b67eb52f2e2f` pages are mapped into the posts collection. `recipes` and `films` will contain the database pages `2190450d-4cb3-4739-a5c8-340c4110fe21` and `e42383cd-4975-4897-b967-ce453760499f`, respectively.
64
+
65
+ ### data
66
+
67
+ Instead of storing notion pages in a collection, you can also map to the data object. Declare the data property as follows.
68
+
69
+ ```yml
70
+ notion:
71
+ database:
72
+ id: e42383cd-4975-4897-b967-ce453760499f
73
+ data: films
74
+ ```
75
+
76
+ Unlike collections, only the properties of the notion page are assigned to the each data item. The body of the notion page is omitted.
62
77
 
63
78
  ### Database options
64
79
 
@@ -68,7 +83,6 @@ Each dabatase support the following options.
68
83
  * `collection`: the collection each page belongs to (posts by default),
69
84
  * `filter`: the database query filter,
70
85
  * `sort`: the database query sort,
71
- * `frontmatter`: additional front matter to append to each page in the collection.
72
86
 
73
87
  ```yml
74
88
  notion:
@@ -77,12 +91,8 @@ notion:
77
91
  collection: posts
78
92
  filter: { "property": "Published", "checkbox": { "equals": true } }
79
93
  sort: { "property": "Last ordered", "direction": "ascending" }
80
- frontmatter:
81
- layout: post
82
94
  ```
83
95
 
84
- Note that you can also use [front matter defaults](https://jekyllrb.com/docs/configuration/front-matter-defaults/) to declare common key value pairs per collection.
85
-
86
96
  ### Watch
87
97
 
88
98
  By default, databases are only requested during the first build. Subsequent builds use the results from the cache.
@@ -102,7 +112,7 @@ And that's all. Each page in the notion database will be included in the selecte
102
112
 
103
113
  Below, default properties per notion page are set for each document front matter.
104
114
 
105
- Notion properties include page `id`, `title`, `created_time`, `last_edited_time`, `icon` and `cover`.
115
+ Notion page properties are `id`, `title`, `created_time`, `last_edited_time`, `icon`, `cover` and `archived`.
106
116
 
107
117
  ```
108
118
  ---
@@ -110,47 +120,14 @@ id: e42383cd-4975-4897-b967-ce453760499f
110
120
  title: An amazing post
111
121
  cover: https://img.bank.sh/an_image.jpg
112
122
  date: 2022-01-23T12:31:00.000Z
113
- icon: \U0001F4A5
114
- ---
115
- ```
116
-
117
- Default properties prevail over custom properties declared in the front matter config.
118
-
119
- ### Custom properties
120
-
121
- In addition to default properties, custom properties are also supported.
122
-
123
- Custom properties are appended to the page frontmatter by default. Every property name are downcased and snake-cased.
124
- For example, two properties named `Multiple Options` and `Tags` will be transformed to `multiple_options` and `tags`, respectively.
125
-
126
- ```
127
- ---
128
- id: 2190450d-4cb3-4739-a5c8-340c4110fe21
129
- title: A title
130
- cover: https://img.bank.sh/an_image.jpg
131
- date: 2022-01-23T12:31:00.000Z
132
- icon: \U0001F4A5
133
- tags: tag1, tag2, tag3
134
- multiple_options: option1, option2
123
+ icon: 💥
124
+ archived: false
135
125
  ---
136
126
  ```
137
127
 
138
- The supported property types are:
139
-
140
- * `number`
141
- * `select`
142
- * `multi_select`
143
- * `date`
144
- * `people`
145
- * `files`
146
- * `checkbox`
147
- * `url`
148
- * `email`
149
- * `phone_number`
150
-
151
- `created_by`, `last_edited_by`, `rich_text` as advanced types like `formula`, `relation` and `rollup` are not supported.
128
+ In addition to default properties, custom properties are also appended to front matter.
152
129
 
153
- Check notion documentation about [property values](https://developers.notion.com/reference/property-value-object#all-property-values).
130
+ Please, refer to the [notion_to_md](https://github.com/emoriarty/notion_to_md/) gem to learn more.
154
131
 
155
132
  ## Page filename
156
133
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllNotion
4
+ class AbstractGenerator
5
+ def initialize(db:, site:, plugin:)
6
+ @db = db
7
+ @site = site
8
+ @plugin = plugin
9
+ end
10
+
11
+ def generate
12
+ raise "Do not use the AbstractGenerator class directly. Implement the generate method in a subclass."
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllNotion
4
+ class CollectionGenerator < AbstractGenerator
5
+ def generate
6
+ @db.pages.each do |page|
7
+ next if file_exists?(make_path(page))
8
+
9
+ collection.docs << make_doc(page)
10
+ log_new_page(page)
11
+ end
12
+ # Caching current collection
13
+ @plugin.collections[@db.collection] = collection
14
+ end
15
+
16
+ def collection
17
+ @site.collections[@db.collection]
18
+ end
19
+
20
+ private
21
+
22
+ # Checks if a file already exists in the site source
23
+ def file_exists?(file_path)
24
+ File.exist? @site.in_source_dir(file_path)
25
+ end
26
+
27
+ def make_doc(page)
28
+ new_post = DocumentWithoutAFile.new(
29
+ make_path(page),
30
+ { :site => @site, :collection => collection }
31
+ )
32
+ new_post.content = make_md(page)
33
+ new_post.read
34
+ new_post
35
+ end
36
+
37
+ def make_path(page)
38
+ "_#{@db.collection}/#{make_filename(page)}"
39
+ end
40
+
41
+ def make_filename(page)
42
+ if @db.collection == "posts"
43
+ "#{page.created_time.to_date}-#{Jekyll::Utils.slugify(page.title,
44
+ :mode => "latin")}.md"
45
+ else
46
+ "#{page.title.downcase.parameterize}.md"
47
+ end
48
+ end
49
+
50
+ def make_md(page)
51
+ NotionToMd::Converter.new(:page_id => page.id).convert(:frontmatter => true)
52
+ end
53
+
54
+ def log_new_page(page)
55
+ Jekyll.logger.info("Jekyll Notion:", "Page => #{page.title}")
56
+ if @site.config.dig(
57
+ "collections", @db.collection, "output"
58
+ )
59
+ Jekyll.logger.info("",
60
+ "Path => #{collection.docs.last.path}")
61
+ end
62
+ Jekyll.logger.debug("", "Props => #{collection.docs.last.data.keys.inspect}")
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllNotion
4
+ class DataGenerator < AbstractGenerator
5
+ def generate
6
+ @site.data[@db.data] = data
7
+ # Caching current data
8
+ @plugin.data[@db.data] = data
9
+ end
10
+
11
+ private
12
+
13
+ def data
14
+ @data ||= @db.pages.map(&:props)
15
+ end
16
+ end
17
+ end
@@ -16,23 +16,6 @@ module JekyllNotion
16
16
  end
17
17
  end
18
18
 
19
- protected
20
-
21
- def read_notion_database
22
- databases.each do |db_config|
23
- @current_db = NotionDatabase.new(:config => db_config)
24
- @current_db.pages.each do |page|
25
- @current_page = page
26
- next if file_exists?(make_path)
27
-
28
- current_collection.docs << make_page
29
- log_new_page
30
- end
31
- # Store current collection
32
- collections[current_db.collection] = current_collection
33
- end
34
- end
35
-
36
19
  def databases
37
20
  config["databases"] || [config["database"]]
38
21
  end
@@ -41,62 +24,25 @@ module JekyllNotion
41
24
  @collections ||= {}
42
25
  end
43
26
 
44
- # Checks if a file already exists in the site source
45
- def file_exists?(file_path)
46
- File.exist? @site.in_source_dir(file_path)
47
- end
48
-
49
- def make_page
50
- new_post = DocumentWithoutAFile.new(
51
- make_path,
52
- { :site => @site, :collection => current_collection }
53
- )
54
- new_post.content = "#{make_frontmatter}\n\n#{make_md}"
55
- new_post.read
56
- new_post
27
+ def data
28
+ @data ||= {}
57
29
  end
58
30
 
59
- def make_path
60
- "_#{current_db.collection}/#{make_filename}"
61
- end
31
+ protected
62
32
 
63
- def make_filename
64
- if current_db.collection == "posts"
65
- "#{current_page.created_date}-#{Jekyll::Utils.slugify(current_page.title,
66
- :mode => "latin")}.md"
67
- else
68
- "#{current_page.title.downcase.parameterize}.md"
33
+ def read_notion_database
34
+ databases.each do |db_config|
35
+ db = NotionDatabase.new(:config => db_config)
36
+ GeneratorFactory.for(:db => db, :site => @site, :plugin => self).generate
69
37
  end
70
38
  end
71
39
 
72
- def make_md
73
- NotionToMd::Converter.new(:page_id => current_page.id).convert
74
- end
75
-
76
- def make_frontmatter
77
- data = Jekyll::Utils.deep_merge_hashes(current_db.frontmatter, page_frontmatter)
78
- frontmatter = data.to_a.map { |k, v| "#{k}: #{v}" }.join("\n")
79
- <<~CONTENT
80
- ---
81
- #{frontmatter}
82
- ---
83
- CONTENT
84
- end
85
-
86
- def page_frontmatter
87
- Jekyll::Utils.deep_merge_hashes(current_page.custom_props, current_page.default_props)
88
- end
89
-
90
- def current_collection
91
- @site.collections[current_db.collection]
92
- end
93
-
94
40
  def config
95
41
  @config ||= @site.config["notion"] || {}
96
42
  end
97
43
 
98
44
  def fetch_on_watch?
99
- config["fetch_on_watch"].present?
45
+ config["fetch_on_watch"] == true
100
46
  end
101
47
 
102
48
  def notion_token?
@@ -114,16 +60,5 @@ module JekyllNotion
114
60
  end
115
61
  true
116
62
  end
117
-
118
- def log_new_page
119
- Jekyll.logger.info("Jekyll Notion:", "Page => #{current_page.title}")
120
- if @site.config.dig(
121
- "collections", current_db.collection, "output"
122
- )
123
- Jekyll.logger.info("",
124
- "Path => #{current_collection.docs.last.path}")
125
- end
126
- Jekyll.logger.debug("", "Props => #{page_frontmatter.keys.inspect}")
127
- end
128
63
  end
129
64
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllNotion
4
+ class GeneratorFactory
5
+ def self.for(db:, site:, plugin:)
6
+ if db.data.nil?
7
+ CollectionGenerator.new(:db => db, :site => site, :plugin => plugin)
8
+ else
9
+ DataGenerator.new(:db => db, :site => site, :plugin => plugin)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -11,7 +11,7 @@ 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 => layout)
14
+ NotionToMd::Page.new(:page => page)
15
15
  end
16
16
  end
17
17
 
@@ -31,16 +31,12 @@ module JekyllNotion
31
31
  config["id"]
32
32
  end
33
33
 
34
- def frontmatter
35
- config["frontmatter"] || {}
36
- end
37
-
38
34
  def collection
39
35
  config["collection"] || "posts"
40
36
  end
41
37
 
42
- def layout
43
- config["layout"]
38
+ def data
39
+ config["data"]
44
40
  end
45
41
 
46
42
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllNotion
4
- VERSION = "0.2.1"
4
+ VERSION = "1.1.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,10 @@ Notion.configure do |config|
15
13
  end
16
14
 
17
15
  module JekyllNotion
16
+ autoload :GeneratorFactory, "jekyll-notion/generator_factory"
17
+ autoload :AbstractGenerator, "jekyll-notion/abstract_generator"
18
+ autoload :CollectionGenerator, "jekyll-notion/collection_generator"
19
+ autoload :DataGenerator, "jekyll-notion/data_generator"
18
20
  autoload :DocumentWithoutAFile, "jekyll-notion/document_without_a_file"
19
21
  autoload :NotionDatabase, "jekyll-notion/notion_database"
20
- autoload :NotionPage, "jekyll-notion/notion_page"
21
22
  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.2.1
4
+ version: 1.1.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-12 00:00:00.000000000 Z
11
+ date: 2022-02-26 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,13 @@ extra_rdoc_files:
124
110
  files:
125
111
  - README.md
126
112
  - lib/jekyll-notion.rb
113
+ - lib/jekyll-notion/abstract_generator.rb
114
+ - lib/jekyll-notion/collection_generator.rb
115
+ - lib/jekyll-notion/data_generator.rb
127
116
  - lib/jekyll-notion/document_without_a_file.rb
128
117
  - lib/jekyll-notion/generator.rb
118
+ - lib/jekyll-notion/generator_factory.rb
129
119
  - lib/jekyll-notion/notion_database.rb
130
- - lib/jekyll-notion/notion_page.rb
131
120
  - lib/jekyll-notion/version.rb
132
121
  homepage: https://github.com/emoriarty/jekyll-notion
133
122
  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