jekyll-strapi-4 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b60b83febefc6dfb99cc3f9d41cc0e4e2f82bce56e1e166ca6a04045357794f9
4
+ data.tar.gz: a7a6f9c335cb714d7c52dc06ffd240eb70e18d3918c2b3eef0f9f8ab24dfb055
5
+ SHA512:
6
+ metadata.gz: 47db6f927bd95d671ca094db0dd4d0ca591401b2b3a1b3ae141097ae43fa7bef1530355cc8192f6d63803b58f8f53c97a584b045fb9fac90b57e1bc16382d66d
7
+ data.tar.gz: 59e61272e81d10fff14524436f6a57cdee50518d3e9f699bdafdc486f001c62495c2c611c25d59fa7375edaf33651571978c019f13ae427b519b3c3079ff5523
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (c) 2022 Rafał Zawadzki, Michał Krajewski
2
+
3
+ Copyright (c) 2015-2019 Strapi Solutions.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # jekyll-strapi-4
2
+
3
+ This plugin is based on the [jekyll-strapi](https://github.com/strapi-community/jekyll-strapi/) plugin.
4
+
5
+ ## Features
6
+
7
+ * Support for Strapi 4
8
+ * Authentication
9
+ * Permalinks
10
+ * Caching and collecting assets from Strapi
11
+ * Added UnitTests
12
+ * Documentation in Jekyll format
13
+
14
+ ## Install
15
+
16
+ Add the "jekyll-strapi" gem to your Gemfile:
17
+
18
+ ```
19
+ gem "jekyll-strapi"
20
+ ```
21
+
22
+ Then add "jekyll-strapi" to your plugins in `_config.yml`:
23
+
24
+ ```
25
+ plugins:
26
+ - jekyll-strapi
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ ```yaml
32
+ strapi:
33
+ # Your API endpoint (optional, default to http://localhost:1337)
34
+ endpoint: http://localhost:1337
35
+ # Collections, key is used to access in the strapi.collections
36
+ # template variable
37
+ collections:
38
+ # Example for a "Photo" collection
39
+ photos:
40
+ # Collection name (optional)
41
+ # type: photos
42
+ # Permalink used to generate the output files (eg. /articles/:id).
43
+ permalink: /photos/:id/
44
+ # Parameters (optional)
45
+ parameters:
46
+ sort: title:asc
47
+ pagination[pageSize]: 10
48
+ # Populate page (optional, default "*")
49
+ # populate: "*"
50
+ # Layout file for this collection
51
+ layout: photo.html
52
+ # Generate output files or not (default: false)
53
+ output: true
54
+ ```
55
+
56
+ This works for the following collection *Photo* in Strapi:
57
+
58
+ | Name | Type |
59
+ | ------- | ----- |
60
+ | Title | Text |
61
+ | Image | Media |
62
+ | Comment | Text |
63
+
64
+ ### Authentication
65
+
66
+ To access non Public collections (and by default all Strapi collections are non Public) you must to generate a token inside your strapi instance and set it as enviromental variable `STRAPI_TOKEN`.
67
+
68
+ It is recommended that you will use new Content API tokens for this task: https://strapi.io/blog/a-beginners-guide-to-authentication-and-authorization-in-strapi
69
+
70
+ ## Usage
71
+
72
+ This plugin provides the `strapi` template variable. This template provides access to the collections defined in the configuration.
73
+
74
+ ### Using Collections
75
+
76
+ Collections are accessed by their name in `strapi.collections`. The `articles` collections is available at `strapi.collections.articles`.
77
+
78
+ To list all documents of the collection ```_layouts/home.html```:
79
+
80
+ ```
81
+ ---
82
+ layout: default
83
+ ---
84
+ <div class="home">
85
+ <h1 class="page-heading">Photos</h1>
86
+ {%- if strapi.collections.photos.size > 0 -%}
87
+ <ul>
88
+ {%- for photo in strapi.collections.photos -%}
89
+ <li>
90
+ <a href="{{ photo.url }}">Title: {{ photo.strapi_attributes.Title }}</a>
91
+ </li>
92
+ {%- endfor -%}
93
+ </ul>
94
+ {%- endif -%}
95
+ </div>
96
+ ```
97
+
98
+ ### Attributes
99
+
100
+ All object's data you can access through ``` {{ page.document.strapi_attributes }}```. This plugin also introduces new filter asset_url which perform downloading the asset into the assets folder and provides correct url. Thanks for this you have copies of your assets locally without extra dependency on Strapi ```_layouts/photo.html```:
101
+
102
+ ```
103
+ ---
104
+ layout: default
105
+ ---
106
+
107
+ <div class="home">
108
+ <h1 class="page-heading">{{ page.document.title }}</h1>
109
+ <h2>{{ page.document.strapi_attributes.Title }}</h2>
110
+ <p>{{ page.document.strapi_attributes.Comment }}</p>
111
+ <img src="{{ page.document.strapi_attributes.Image.data.attributes.formats.thumbnail| asset_url }}"/>
112
+ </div>
113
+ ```
114
+
115
+ ### Request parameters
116
+
117
+ Define your request parameters in config files (check configuration).
118
+
119
+ If you want to add custom logic use custom_path_params method. You can use it by create _plugins/filename.rb.
120
+
121
+ ```ruby
122
+ module Jekyll
123
+ module Strapi
124
+ class StrapiCollection
125
+ def custom_path_params
126
+ # ex. for multilanguage plugin you might want get request by page lang
127
+ "&locale=#{@site.config["lang"]}"
128
+ end
129
+ end
130
+ end
131
+ end
132
+ ```
@@ -0,0 +1,94 @@
1
+ require "net/http"
2
+ require "ostruct"
3
+ require "json"
4
+
5
+
6
+
7
+
8
+
9
+ module Jekyll
10
+ module Strapi
11
+ class StrapiCollection
12
+ attr_accessor :collection_name, :config
13
+
14
+ def initialize(site, collection_name, config)
15
+ @site = site
16
+ @collection_name = collection_name
17
+ @config = config
18
+ Jekyll.logger.debug "Jekyll Collection init:" "#{site.config} #{collection_name} #{config}"
19
+ end
20
+
21
+ def generate?
22
+ @config['output'] || false
23
+ end
24
+
25
+ def get_data
26
+ # path = "/#{@config['type'] || @collection_name}?_limit=10000"
27
+ # This seems be not working anymore:
28
+ # https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#api-parameters
29
+ # and pagination is now done in following way:
30
+ # https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/sort-pagination.html#pagination-by-page
31
+ uri = URI("#{@site.endpoint}/api/#{endpoint}#{path_params}")
32
+ Jekyll.logger.debug "StrapiCollection get_document:" "#{collection_name} #{uri}"
33
+ response = strapi_request(uri)
34
+ response.data
35
+ end
36
+
37
+ def get_document(did)
38
+ uri_document = URI("#{@site.endpoint}/api/#{endpoint}/#{did}?populate=#{populate}")
39
+ Jekyll.logger.debug "StrapiCollection iterating uri_document:" "#{uri_document}"
40
+ strapi_request(uri_document)
41
+ # document
42
+ end
43
+
44
+ def each
45
+ data = get_data
46
+ data.each do |document|
47
+ Jekyll.logger.debug "StrapiCollection iterating over document:" "#{collection_name} #{document.id}"
48
+ document.type = collection_name
49
+ document.collection = collection_name
50
+ document.id ||= document._id
51
+ document_response = get_document(document.id)
52
+ # We will keep all the attributes in strapi_attributes
53
+ document.strapi_attributes = document_response['data']["attributes"]
54
+ document.url = @site.strapi_link_resolver(collection_name, document)
55
+ end
56
+ data.each {|x| yield(x)}
57
+ end
58
+
59
+ def endpoint
60
+ @config['type'] || @collection_name
61
+ end
62
+
63
+ def populate
64
+ @config["populate"] || "*"
65
+ end
66
+
67
+ def path_params
68
+ string = "?"
69
+ return_params = false
70
+
71
+ if @config["parameters"]
72
+ return_params = true
73
+
74
+ @config["parameters"].each do |k, v|
75
+ string += "&#{k}=#{v}"
76
+ end
77
+ end
78
+
79
+ if custom_path_params.length != 0
80
+ return_params = true
81
+
82
+ string += custom_path_params
83
+ end
84
+
85
+ return_params ? string : ""
86
+ end
87
+
88
+ def custom_path_params
89
+ # Define custom logic in your _plugins/file_name.rb
90
+ ""
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,62 @@
1
+ module Jekyll
2
+ module Strapi
3
+ # Strapi Document access in Liquid
4
+ class StrapiDocumentDrop < Liquid::Drop
5
+ attr_accessor :document
6
+
7
+ def initialize(document)
8
+ @document = document
9
+ end
10
+
11
+ def [](attribute)
12
+ value = @document[attribute]
13
+
14
+ case value
15
+ when OpenStruct
16
+ StrapiDocumentDrop.new(value)
17
+ when Array
18
+ StrapiCollectionDrop.new(value)
19
+ else
20
+ value
21
+ end
22
+ end
23
+ end
24
+
25
+ # Handles a single Strapi collection in Liquid
26
+ class StrapiCollectionDrop < Liquid::Drop
27
+ def initialize(collection)
28
+ @collection = collection
29
+ end
30
+
31
+ def to_liquid
32
+ results = []
33
+ @collection.each do |result|
34
+ results << StrapiDocumentDrop.new(result)
35
+ end
36
+ results
37
+ end
38
+ end
39
+
40
+ # Handles Strapi collections in Liquid, and creates the collection on demand
41
+ class StrapiCollectionsDrop < Liquid::Drop
42
+ def initialize(collections)
43
+ @collections = collections
44
+ end
45
+
46
+ def [](collection_name)
47
+ StrapiCollectionDrop.new(@collections[collection_name])
48
+ end
49
+ end
50
+
51
+ # Main Liquid Drop, handles lazy loading of collections to drops
52
+ class StrapiDrop < Liquid::Drop
53
+ def initialize(site)
54
+ @site = site
55
+ end
56
+
57
+ def collections
58
+ @collections ||= StrapiCollectionsDrop.new(@site.strapi_collections)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,52 @@
1
+ module Jekyll
2
+ module Strapi
3
+ # Generates pages for all collections with have the "generate" option set to True
4
+ class StrapiGenerator < Generator
5
+ safe true
6
+
7
+ def generate(site)
8
+ site.strapi_collections.each do |collection_name, collection|
9
+ if collection.generate?
10
+ collection.each do |document|
11
+ site.pages << StrapiPage.new(site, site.source, document, collection)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ class StrapiPage < Page
19
+ def initialize(site, base, document, collection)
20
+ @site = site
21
+ @base = base
22
+ @collection = collection
23
+ @document = document
24
+
25
+ @dir = @collection.config['output_dir'] || collection.collection_name
26
+ # Default file name, can be overwritten by permalink frontmatter setting
27
+ @name = "#{document.id}.html"
28
+ # filename_to_read = File.join(base, "_layouts"), @collection.config['layout']
29
+
30
+ self.process(@name)
31
+ self.read_yaml(File.join(base, "_layouts"), @collection.config['layout'])
32
+ if @collection.config.key? 'permalink'
33
+ self.data['permalink'] = @collection.config['permalink']
34
+ end
35
+
36
+ self.data['document'] = StrapiDocumentDrop.new(@document)
37
+ end
38
+
39
+ def url_placeholders
40
+ # This was not really providing :id for the mapping
41
+ # requiredValues = @document.strapi_attributes.to_h.select {|k, v|
42
+ # v.class == String and @collection.config['permalink'].include? k.to_s
43
+ # }
44
+ my_hash = {
45
+ :id => @document.id.to_s,
46
+ :slug => @document.attributes.slug
47
+ }
48
+ Utils.deep_merge_hashes(my_hash, super)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,8 @@
1
+ module Jekyll
2
+ module Strapi
3
+ # Add Strapi Liquid variables to all templates
4
+ Jekyll::Hooks.register :site, :pre_render do |site, payload|
5
+ payload['strapi'] = StrapiDrop.new(site)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,46 @@
1
+ module Jekyll
2
+ # Add helper methods for dealing with Strapi to the Site class
3
+ class Site
4
+ def strapi
5
+ return nil unless has_strapi?
6
+ end
7
+
8
+ def strapi_collections
9
+ return Array.new unless has_strapi_collections?
10
+ @strapi_collections ||= Hash[@config['strapi']['collections'].map {|name, config| [name, Strapi::StrapiCollection.new(self, name, config)]}]
11
+ end
12
+
13
+ def has_strapi?
14
+ @config['strapi'] != nil
15
+ end
16
+
17
+ def has_strapi_collections?
18
+ has_strapi? and @config['strapi']['collections'] != nil
19
+ end
20
+
21
+ def endpoint
22
+ has_strapi? and @config['strapi']['endpoint'] or "http://localhost:1337"
23
+ end
24
+
25
+ def strapi_link_resolver(collection = nil, document = nil)
26
+ return "/" unless collection != nil and @config['strapi']['collections'][collection]['permalink'] != nil
27
+ url = Jekyll::URL.new(
28
+ :template => @config['strapi']['collections'][collection]['permalink'],
29
+ :placeholders => {
30
+ :id => document.id.to_s,
31
+ :uid => document.uid,
32
+ :slug => document.attributes.slug,
33
+ :type => document.attributes.type,
34
+ :date => document.attributes.date,
35
+ :title => document.title
36
+ }
37
+ )
38
+
39
+ url.to_s
40
+ end
41
+
42
+ def strapi_collection(collection_name)
43
+ strapi_collections[collection_name]
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,42 @@
1
+ ##
2
+ # This is a helper method to authenticate during getting data from Strapi instance.
3
+ require "json"
4
+
5
+ def strapi_request(url)
6
+ uri = URI(url)
7
+ req = Net::HTTP::Get.new(uri)
8
+ strapi_token = ENV['STRAPI_TOKEN']
9
+ if strapi_token==nil
10
+ Jekyll.logger.info "STRAPI_TOKEN not set, non Authenticated request."
11
+ headers = {}
12
+ else
13
+ headers = {
14
+ 'Authorization'=>"Bearer #{strapi_token}"
15
+ }
16
+ req['Authorization'] = "Bearer #{strapi_token}"
17
+ end
18
+ Jekyll.logger.info "Jekyll StrapiHTTP:", "Fetching entries from #{uri} using headers: #{headers.keys}"
19
+ response = Net::HTTP.get_response(uri, headers)
20
+
21
+ ##
22
+ # Response structure
23
+ # https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#unified-response-format
24
+ # - data
25
+ # - meta
26
+ # - error
27
+ # TODO: add checking error and the meta and act if necessart
28
+
29
+ # Check response code
30
+ if response.code == "200"
31
+ response_json = JSON.parse(response.body, object_class: OpenStruct)
32
+ return response_json
33
+ elsif response.code == "401"
34
+ raise "The Strapi server sent a error with the following status: 401. Please make sure that your credentials are correct or that you have access to the API."
35
+ elsif response.code == "403"
36
+ raise "The Strapi server sent a error with the following status: 403. Please provide STRAPI_TOKEN or allow public access for find and findOne actions."
37
+ elsif response.code == "403"
38
+ raise "The Strapi server sent a error with the following status: 404. Please make sure that name of your collection is correct."
39
+ else
40
+ raise "The Strapi server sent a error with the following status: #{response.code}. Please make sure it is correctly running."
41
+ end
42
+ end
@@ -0,0 +1,5 @@
1
+ module Jekyll
2
+ module Strapi
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ require "down"
3
+
4
+ module Jekyll
5
+ class StrapiStaticFile < Jekyll::StaticFile
6
+ def initialize(site, base, dir, name, collection = nil)
7
+ @site = site
8
+ @base = base
9
+ @dir = dir
10
+ @name = name
11
+ @collection = collection
12
+ # TODO: Check if user can change 'assets' path
13
+ @relative_path = File.join(*["assets", @name].compact)
14
+ @extname = File.extname(@name)
15
+ end
16
+ end
17
+
18
+ module StrapiImageFilter
19
+ def asset_url(input)
20
+ # Sometimes to make this output visible in tests debug must be change for info
21
+ # Need to find switch of logging level during rake test TODO: <===
22
+ Jekyll.logger.debug "StrapiImageFilter 000 input:" " ==> YES"
23
+ Jekyll.logger.debug "StrapiImageFilter 111 input:" "#{input}"
24
+ Jekyll.logger.debug "StrapiImageFilter 222 context REGISTERS:" "#{@context.registers}"
25
+ strapi_endpoint = @context.registers[:site].config['strapi']['endpoint']
26
+ Jekyll.logger.debug "StrapiImageFilter strapi_endpoint:" "#{strapi_endpoint}"
27
+
28
+ uri_path = "#{strapi_endpoint}#{input['url']}"
29
+ if not Dir.exist?('_tmp_assets')
30
+ # TODO: Check if there is not ability to overwrite from the _config
31
+ Jekyll.logger.info "_tmp_assets directory does not exist, I am going to create one"
32
+ Dir.mkdir '_tmp_assets'
33
+ end
34
+ ##
35
+ # TODO: Investigate if there is a better way to download binaries
36
+ # Check if we need authenticate to get medias
37
+ Down.download(uri_path, destination: "_tmp_assets/#{input['name']}")
38
+ ##
39
+ # To perform copying of the assets in the cycle of Jenkins
40
+ # https://jekyllrb.com/docs/rendering-process/
41
+ site = Jekyll.sites.first
42
+ site.static_files << StrapiStaticFile.new(site, site.source, "_tmp_assets", "#{input['name']}")
43
+ "/assets/#{input['name']}"
44
+ end
45
+ end
46
+ end
47
+ Liquid::Template.register_filter(Jekyll::StrapiImageFilter)
@@ -0,0 +1,8 @@
1
+ require 'jekyll/strapi/strapihttp'
2
+ require 'jekyll/strapi/collection'
3
+ require 'jekyll/strapi/drops'
4
+ require 'jekyll/strapi/generator'
5
+ require 'jekyll/strapi/hooks'
6
+ require 'jekyll/strapi/site'
7
+ require 'jekyll/strapi/version'
8
+ require 'jekyll/tags/strapiimagefilter'
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-strapi-4
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Strapi Solutions
8
+ - Rafał Zawadzki
9
+ - Michał Krajewski
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2022-07-28 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: down
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '5.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '5.0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: jekyll
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '4'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '4'
43
+ - !ruby/object:Gem::Dependency
44
+ name: http
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.2'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '3.2'
57
+ - !ruby/object:Gem::Dependency
58
+ name: json
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '2.1'
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '2.1'
71
+ description: " A Jekyll plugin for retrieving content from a Strapi 4 API\n"
72
+ email:
73
+ - bluszcz@bluszcz.net
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - LICENSE
79
+ - README.md
80
+ - lib/jekyll-strapi.rb
81
+ - lib/jekyll/strapi/collection.rb
82
+ - lib/jekyll/strapi/drops.rb
83
+ - lib/jekyll/strapi/generator.rb
84
+ - lib/jekyll/strapi/hooks.rb
85
+ - lib/jekyll/strapi/site.rb
86
+ - lib/jekyll/strapi/strapihttp.rb
87
+ - lib/jekyll/strapi/version.rb
88
+ - lib/jekyll/tags/strapiimagefilter.rb
89
+ homepage: https://github.com/strapi/jekyll-strapi
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.0.3.1
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Strapi.io integration for Jekyll
112
+ test_files: []