jekyll-open-sdg-plugins 1.0.0.rc21 → 1.2.0.pre.beta1

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.
@@ -1,99 +1,127 @@
1
- require "jekyll"
2
-
3
- module JekyllOpenSdgPlugins
4
- class CreatePages < Jekyll::Generator
5
- safe true
6
- priority :normal
7
-
8
- def generate(site)
9
- # If site.create_pages is set, create the 4 required pages. These include:
10
- # - the home page: /
11
- # - the indicators json page: /indicators.json
12
- # - the search results page: /search
13
- # - the reporting status page: /reporting-status
14
- #
15
- # These can be overridden though, with a create_pages.pages setting in
16
- # _config.yml, like so:
17
- #
18
- # create_pages:
19
- # pages:
20
- # - folder: ''
21
- # layout: frontpage
22
- # - filename: my-json-file.json
23
- # folder: my-subfolder
24
- # layout: indicator-json
25
- #
26
- # Note the optional "filename" setting for when the page needs a specific
27
- # filename (as opposed to being "index.html" inside a named folder).
28
- #
29
- # To use the default 4 pages, simply put:
30
- #
31
- # create_pages: true
32
- if site.config['languages'] and site.config['create_pages']
33
-
34
- default_pages = [
35
- {
36
- 'folder' => '/',
37
- 'layout' => 'frontpage'
38
- },
39
- {
40
- 'folder' => '/reporting-status',
41
- 'layout' => 'reportingstatus'
42
- },
43
- {
44
- 'filename' => 'indicators.json',
45
- 'folder' => '/',
46
- 'layout' => 'indicator-json',
47
- },
48
- {
49
- 'folder' => '/search',
50
- 'layout' => 'search'
51
- }
52
- ]
53
- pages = default_pages
54
- if site.config['create_pages'].is_a?(Hash) and site.config['create_pages'].key?('pages')
55
- pages = site.config['create_pages']['pages']
56
- end
57
-
58
- # See if we need to "map" any language codes.
59
- languages_public = Hash.new
60
- if site.config['languages_public']
61
- languages_public = site.config['languages_public']
62
- end
63
-
64
- # Loop through the languages.
65
- site.config['languages'].each_with_index do |language, index|
66
- # Get the "public language" (for URLs) which may be different.
67
- language_public = language
68
- if languages_public[language]
69
- language_public = languages_public[language]
70
- end
71
- # Loop through the pages.
72
- pages.each do |page|
73
- # Add the language subfolder for all except the default (first) language.
74
- dir = index == 0 ? page['folder'] : File.join(language_public, page['folder'])
75
- # Create the page.
76
- site.collections['pages'].docs << OpenSdgPage.new(site, site.source, dir, page, language)
77
- end
78
- end
79
- end
80
- end
81
- end
82
-
83
- # A Page subclass used in the `CreatePages` class.
84
- class OpenSdgPage < Jekyll::Page
85
- def initialize(site, base, dir, page, language)
86
- @site = site
87
- @base = base
88
-
89
- index_files = (!page.key?('filename') or page['filename'] == 'index.html')
90
- @dir = index_files ? File.join(dir, '/') : dir
91
- @name = index_files ? 'index.html' : page['filename']
92
-
93
- self.process(@name)
94
- self.data = {}
95
- self.data['layout'] = page['layout']
96
- self.data['language'] = language
97
- end
98
- end
99
- end
1
+ require "jekyll"
2
+ require_relative "helpers"
3
+
4
+ module JekyllOpenSdgPlugins
5
+ class CreatePages < Jekyll::Generator
6
+ safe true
7
+ priority :normal
8
+
9
+ def generate(site)
10
+ # If site.create_pages is set, create the 4 required pages. These include:
11
+ # - the home page: /
12
+ # - the indicators json page: /indicators.json
13
+ # - the search results page: /search
14
+ # - the reporting status page: /reporting-status
15
+ #
16
+ # These can be overridden though, with a create_pages.pages setting in
17
+ # _config.yml, like so:
18
+ #
19
+ # create_pages:
20
+ # pages:
21
+ # - folder: ''
22
+ # layout: frontpage
23
+ # - filename: my-json-file.json
24
+ # folder: my-subfolder
25
+ # layout: indicator-json
26
+ #
27
+ # Note the optional "filename" setting for when the page needs a specific
28
+ # filename (as opposed to being "index.html" inside a named folder).
29
+ #
30
+ # To use the default 4 pages, simply put:
31
+ #
32
+ # create_pages: true
33
+ if site.config['languages'] and site.config['create_pages']
34
+
35
+ default_pages = [
36
+ {
37
+ 'folder' => '/',
38
+ 'layout' => 'frontpage'
39
+ },
40
+ {
41
+ 'folder' => '/reporting-status',
42
+ 'layout' => 'reportingstatus',
43
+ 'title' => 'status.reporting_status',
44
+ },
45
+ {
46
+ 'filename' => 'indicators.json',
47
+ 'folder' => '/',
48
+ 'layout' => 'indicator-json',
49
+ },
50
+ {
51
+ 'folder' => '/search',
52
+ 'layout' => 'search',
53
+ 'title' => 'search.search',
54
+ }
55
+ ]
56
+ pages = default_pages
57
+ if site.config['create_pages'].is_a?(Hash) and site.config['create_pages'].key?('pages')
58
+ # Backwards compatability to support the deprecated "pages" key.
59
+ pages = site.config['create_pages']['pages']
60
+ elsif site.config['create_pages'].is_a?(Array)
61
+ pages = site.config['create_pages']
62
+ end
63
+
64
+ # Clone pages so that we don't edit the original.
65
+ pages = pages.clone
66
+
67
+ # Hardcode the site configuration page if it's not already there.
68
+ config_page = pages.find { |page| page['layout'] == 'config-builder' }
69
+ if config_page == nil
70
+ pages.push({
71
+ 'folder' => '/config',
72
+ 'layout' => 'config-builder',
73
+ 'title' => 'Open SDG site configuration',
74
+ 'config_type' => 'site',
75
+ 'config_filename' => 'site_config.yml'
76
+ })
77
+ end
78
+
79
+ # See if we need to "map" any language codes.
80
+ languages_public = Hash.new
81
+ if site.config['languages_public']
82
+ languages_public = opensdg_languages_public(site)
83
+ end
84
+
85
+ # Loop through the languages.
86
+ site.config['languages'].each_with_index do |language, index|
87
+ # Get the "public language" (for URLs) which may be different.
88
+ language_public = language
89
+ if languages_public[language]
90
+ language_public = languages_public[language]
91
+ end
92
+ # Loop through the pages.
93
+ pages.each do |page|
94
+ # Add the language subfolder for all except the default (first) language.
95
+ dir = index == 0 ? page['folder'] : File.join(language_public, page['folder'])
96
+ # Create the page.
97
+ site.collections['pages'].docs << OpenSdgPage.new(site, site.source, dir, page, language)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ # A Page subclass used in the `CreatePages` class.
105
+ class OpenSdgPage < Jekyll::Page
106
+ def initialize(site, base, dir, page, language)
107
+ @site = site
108
+ @base = base
109
+
110
+ index_files = (!page.key?('filename') or page['filename'] == 'index.html')
111
+ @dir = index_files ? File.join(dir, '/') : dir
112
+ @name = index_files ? 'index.html' : page['filename']
113
+
114
+ self.process(@name)
115
+ self.data = {}
116
+ self.data['language'] = language
117
+
118
+ # Add anything else besides "folder" and "filename". This will catch
119
+ # things like "layout" and "title", and anything else.
120
+ page.each do |key, value|
121
+ if key != 'folder' && key != 'filename'
122
+ self.data[key] = value
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -1,167 +1,187 @@
1
- require "jekyll"
2
- require 'json'
3
- require 'deep_merge'
4
- require 'open-uri'
5
- require_relative "helpers"
6
-
7
- module JekyllOpenSdgPlugins
8
- class FetchRemoteData < Jekyll::Generator
9
- safe true
10
- priority :highest
11
-
12
- # Fix a Unix path in case we are on Windows.
13
- def fix_path(path)
14
- path_parts = path.split('/')
15
- return path_parts.join(File::SEPARATOR)
16
- end
17
-
18
- # Our hardcoded list of pieces of the build that we expect.
19
- def get_endpoints()
20
- return {
21
- 'meta' => 'meta/all.json',
22
- 'headlines' => 'headline/all.json',
23
- 'schema' => 'meta/schema.json',
24
- 'reporting' => 'stats/reporting.json',
25
- 'translations' => 'translations/translations.json',
26
- 'zip' => 'zip/all_indicators.json'
27
- }
28
- end
29
-
30
- # Is this path a remote path?
31
- def is_path_remote(path)
32
- return path.start_with?('http')
33
- end
34
-
35
- # Get a build from a local folder on disk or a remote URL on the Internet.
36
- def fetch_build(path)
37
-
38
- is_remote = is_path_remote(path)
39
- build = {}
40
- get_endpoints().each do |key, value|
41
- endpoint = is_remote ? path + '/' + value : File.join(path, fix_path(value))
42
-
43
- begin
44
- json_file = is_remote ? open(endpoint) : File.open(endpoint)
45
- build[key] = JSON.load(json_file)
46
- rescue StandardError => e
47
- # For backwards compatibility, we allow 'translations' to be missing.
48
- if key != 'translations'
49
- puts e.message
50
- abort 'Unable to read data from: ' + endpoint
51
- end
52
- end
53
- end
54
-
55
- return build
56
- end
57
-
58
- # Predict (before data has been fetched) whether the site is using
59
- # translated builds or not.
60
- def site_uses_translated_builds(path)
61
-
62
- is_remote = is_path_remote(path)
63
- endpoints = get_endpoints()
64
- # For a quick test, we just use 'meta'.
65
- meta = endpoints['meta']
66
- endpoint = is_remote ? path + '/' + meta : File.join(path, fix_path(meta))
67
-
68
- begin
69
- json_file = is_remote ? open(endpoint) : File.open(endpoint)
70
- rescue StandardError => e
71
- # If we didn't find an untranslated 'meta', we assume translated builds.
72
- return true
73
- end
74
-
75
- # Other wise assume untranslated builds.
76
- return false
77
- end
78
-
79
- def generate(site)
80
-
81
- # For below, make sure there is at least an empty hash at
82
- # site.data.translations.
83
- if !site.data.has_key?('translations')
84
- site.data['translations'] = {}
85
- end
86
-
87
- remote = site.config['remote_data_prefix']
88
- local = site.config['local_data_folder']
89
-
90
- if !remote && !local
91
- abort 'Site config must include either "remote_data_prefix" or "local_data_folder".'
92
- end
93
-
94
- build_location = remote ? remote : File.join(Dir.pwd, local)
95
- translated_builds = site_uses_translated_builds(build_location)
96
-
97
- if translated_builds
98
- # For translated builds, we get a build for each language, and
99
- # place them in "subfolders" (so to speak) of site.data.
100
- site.config['languages'].each do |language|
101
- data_target = site.data[language]
102
- translated_build = remote ? build_location + '/' + language : File.join(build_location, language)
103
- data_source = fetch_build(translated_build)
104
- if data_target
105
- data_target.deep_merge(data_source)
106
- else
107
- site.data[language] = data_source
108
- end
109
- end
110
- # We move the language-specific translations to the
111
- # site.data.translations location, where all translations are kept.
112
- site.config['languages'].each do |language|
113
- translation_target = site.data['translations'][language]
114
- translation_source = site.data[language]['translations']
115
- if translation_target
116
- translation_target.deep_merge(translation_source)
117
- else
118
- site.data['translations'][language] = translation_source
119
- end
120
- end
121
- # And there are some parts of the build that don't need to be translated
122
- # and should be moved to the top level.
123
- first_language = site.config['languages'][0]
124
- site.data['reporting'] = site.data[first_language]['reporting']
125
- site.data['schema'] = site.data[first_language]['schema']
126
- site.data['zip'] = site.data[first_language]['zip']
127
- else
128
- # For untranslated builds, we download one build only, and place it
129
- # in the "root" (so to speak) of site.data. Nothing else is needed.
130
- target = site.data
131
- source = fetch_build(build_location)
132
- target.deep_merge(source)
133
- end
134
-
135
- # Finally support the deprecated 'remote_translations' option.
136
- # This is deprecated because translations should now be in the
137
- # data repository, where they will be fetched in fetch_build().
138
- if site.config['remote_translations']
139
- key = 'translations'
140
- target = site.data[key]
141
- site.config['remote_translations'].each do |endpoint|
142
- begin
143
- source = JSON.load(open(endpoint))
144
- if target
145
- target.deep_merge(source)
146
- else
147
- site.data[key] = source
148
- end
149
- rescue StandardError => e
150
- puts e.message
151
- abort 'Unable to fetch remote translation from: ' + endpoint
152
- end
153
- end
154
- end
155
- end
156
- end
157
-
158
- # This makes sure that the contents of the "local_data_folder" get copied
159
- # into the Jekyll build, so that they can be served from the website.
160
- Jekyll::Hooks.register :site, :post_write do |site|
161
- if site.config['local_data_folder']
162
- source = File.join(Dir.pwd, site.config['local_data_folder'], '.')
163
- destination = site.config['destination']
164
- FileUtils.cp_r(source, destination)
165
- end
166
- end
167
- end
1
+ require "jekyll"
2
+ require 'json'
3
+ require 'deep_merge'
4
+ require 'open-uri'
5
+ require_relative "helpers"
6
+
7
+ module JekyllOpenSdgPlugins
8
+ class FetchRemoteData < Jekyll::Generator
9
+ safe true
10
+ priority :highest
11
+
12
+ # Fix a Unix path in case we are on Windows.
13
+ def fix_path(path)
14
+ path_parts = path.split('/')
15
+ return path_parts.join(File::SEPARATOR)
16
+ end
17
+
18
+ # Our hardcoded list of pieces of the build that we expect.
19
+ def get_endpoints()
20
+ return {
21
+ 'meta' => 'meta/all.json',
22
+ 'headlines' => 'headline/all.json',
23
+ 'schema' => 'meta/schema.json',
24
+ 'reporting' => 'stats/reporting.json',
25
+ 'disaggregation' => 'stats/disaggregation.json',
26
+ 'translations' => 'translations/translations.json',
27
+ 'zip' => 'zip/all_indicators.json',
28
+ 'indicator_downloads' => 'downloads/indicator-downloads.json'
29
+ }
30
+ end
31
+
32
+ # Get a build from a local folder on disk or a remote URL on the Internet.
33
+ def fetch_build(path)
34
+
35
+ is_remote = opensdg_is_path_remote(path)
36
+ build = {}
37
+ get_endpoints().each do |key, value|
38
+ endpoint = is_remote ? path + '/' + value : File.join(path, fix_path(value))
39
+
40
+ begin
41
+ json_file = is_remote ? open(endpoint) : File.open(endpoint)
42
+ build[key] = JSON.load(json_file)
43
+ rescue StandardError => e
44
+ # For backwards compatibility, forego the exception in some cases.
45
+ abort_build = true
46
+ if ['translations', 'indicator_downloads', 'disaggregation'].include? key
47
+ abort_build = false
48
+ elsif endpoint.include? '/untranslated/'
49
+ abort_build = false
50
+ end
51
+ if abort_build
52
+ puts e.message
53
+ abort 'Unable to read data from: ' + endpoint
54
+ end
55
+ end
56
+ end
57
+
58
+ return build
59
+ end
60
+
61
+ # Predict (before data has been fetched) whether the site is using
62
+ # translated builds or not.
63
+ def site_uses_translated_builds(path)
64
+
65
+ is_remote = opensdg_is_path_remote(path)
66
+ endpoints = get_endpoints()
67
+ # For a quick test, we just use 'meta'.
68
+ meta = endpoints['meta']
69
+ endpoint = is_remote ? path + '/' + meta : File.join(path, fix_path(meta))
70
+
71
+ begin
72
+ json_file = is_remote ? open(endpoint) : File.open(endpoint)
73
+ rescue StandardError => e
74
+ # If we didn't find an untranslated 'meta', we assume translated builds.
75
+ return true
76
+ end
77
+
78
+ # Other wise assume untranslated builds.
79
+ return false
80
+ end
81
+
82
+ def generate(site)
83
+
84
+ # For below, make sure there is at least an empty hash at
85
+ # site.data.translations.
86
+ if !site.data.has_key?('translations')
87
+ site.data['translations'] = {}
88
+ end
89
+
90
+ remote = site.config['remote_data_prefix']
91
+ local = site.config['local_data_folder']
92
+
93
+ if !remote && !local
94
+ abort 'Site config must include "remote_data_prefix".'
95
+ end
96
+
97
+ build_location = remote ? remote : local
98
+ is_remote = opensdg_is_path_remote(build_location)
99
+
100
+ build_location = is_remote ? build_location : File.join(Dir.pwd, build_location)
101
+ translated_builds = site_uses_translated_builds(build_location)
102
+
103
+ if translated_builds
104
+ # For translated builds, we get a build for each language, and
105
+ # place them in "subfolders" (so to speak) of site.data.
106
+ subfolders = site.config['languages'].clone
107
+ subfolders.append('untranslated')
108
+ subfolders.each do |language|
109
+ data_target = site.data[language]
110
+ translated_build = is_remote ? build_location + '/' + language : File.join(build_location, language)
111
+ data_source = fetch_build(translated_build)
112
+ if !data_source.empty?
113
+ if data_target
114
+ data_target.deep_merge(data_source)
115
+ else
116
+ site.data[language] = data_source
117
+ end
118
+ end
119
+ end
120
+ # We move the language-specific translations to the
121
+ # site.data.translations location, where all translations are kept.
122
+ site.config['languages'].each do |language|
123
+ translation_target = site.data['translations'][language]
124
+ translation_source = site.data[language]['translations']
125
+ if translation_target
126
+ translation_target.deep_merge(translation_source)
127
+ else
128
+ site.data['translations'][language] = translation_source
129
+ end
130
+ end
131
+ # And there are some parts of the build that don't need to be translated
132
+ # and should be moved to the top level.
133
+ first_language = site.config['languages'][0]
134
+ site.data['reporting'] = site.data[first_language]['reporting']
135
+ site.data['schema'] = site.data[first_language]['schema']
136
+ site.data['zip'] = site.data[first_language]['zip']
137
+ else
138
+ # For untranslated builds, we download one build only, and place it
139
+ # in the "root" (so to speak) of site.data. Nothing else is needed.
140
+ target = site.data
141
+ source = fetch_build(build_location)
142
+ if !source.empty?
143
+ target.deep_merge(source)
144
+ end
145
+ end
146
+
147
+ # Finally support the deprecated 'remote_translations' option.
148
+ # This is deprecated because translations should now be in the
149
+ # data repository, where they will be fetched in fetch_build().
150
+ if site.config['remote_translations']
151
+ key = 'translations'
152
+ target = site.data[key]
153
+ site.config['remote_translations'].each do |endpoint|
154
+ begin
155
+ source = JSON.load(open(endpoint))
156
+ if target
157
+ target.deep_merge(source)
158
+ else
159
+ site.data[key] = source
160
+ end
161
+ rescue StandardError => e
162
+ puts e.message
163
+ abort 'Unable to fetch remote translation from: ' + endpoint
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ # This makes sure that the contents of the "local_data_folder" get copied
171
+ # into the Jekyll build, so that they can be served from the website.
172
+ Jekyll::Hooks.register :site, :post_write do |site|
173
+ if site.config['local_data_folder']
174
+ source = File.join(Dir.pwd, site.config['local_data_folder'], '.')
175
+ destination = site.config['destination']
176
+ FileUtils.cp_r(source, destination)
177
+ # Do the same in the case that "remote_data_prefix" is being used for a local
178
+ # data folder (since "local_data_folder" is deprecated and undocumented).
179
+ elsif site.config['remote_data_prefix']
180
+ if !opensdg_is_path_remote(site.config['remote_data_prefix'])
181
+ source = File.join(Dir.pwd, site.config['remote_data_prefix'], '.')
182
+ destination = site.config['destination']
183
+ FileUtils.cp_r(source, destination)
184
+ end
185
+ end
186
+ end
187
+ end