jekyll-open-sdg-plugins 1.6.1 → 1.8.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.
- checksums.yaml +4 -4
- data/.editorconfig +16 -16
- data/.github/workflows/test-pull-requests.yml +17 -17
- data/.gitignore +6 -6
- data/LICENSE +21 -21
- data/Makefile +33 -33
- data/README.md +7 -7
- data/jekyll-open-sdg-plugins.gemspec +18 -18
- data/lib/jekyll-open-sdg-plugins/backwards_compatibility.rb +97 -64
- data/lib/jekyll-open-sdg-plugins/create_goals.rb +88 -85
- data/lib/jekyll-open-sdg-plugins/create_indicators.rb +209 -206
- data/lib/jekyll-open-sdg-plugins/create_pages.rb +150 -135
- data/lib/jekyll-open-sdg-plugins/fetch_remote_data.rb +188 -188
- data/lib/jekyll-open-sdg-plugins/helpers.rb +132 -132
- data/lib/jekyll-open-sdg-plugins/metadata_schema_to_config.rb +72 -72
- data/lib/jekyll-open-sdg-plugins/schema-indicator-config.json +787 -709
- data/lib/jekyll-open-sdg-plugins/schema-site-config.json +1712 -1607
- data/lib/jekyll-open-sdg-plugins/sdg_variables.rb +614 -549
- data/lib/jekyll-open-sdg-plugins/search_index.rb +102 -102
- data/lib/jekyll-open-sdg-plugins/site_configuration.rb +87 -73
- data/lib/jekyll-open-sdg-plugins/translate_date.rb +122 -122
- data/lib/jekyll-open-sdg-plugins/translate_key.rb +20 -20
- data/lib/jekyll-open-sdg-plugins/translate_metadata_field.rb +111 -111
- data/lib/jekyll-open-sdg-plugins/validate_indicator_config.rb +52 -52
- data/lib/jekyll-open-sdg-plugins/validate_site_config.rb +34 -34
- data/lib/jekyll-open-sdg-plugins/version.rb +3 -3
- data/lib/jekyll-open-sdg-plugins.rb +18 -18
- data/tests/Gemfile +7 -7
- data/tests/_config.yml +168 -168
- metadata +5 -5
@@ -1,188 +1,188 @@
|
|
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
|
-
'data_packages' => 'data-packages/all.json',
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
33
|
-
# Get a build from a local folder on disk or a remote URL on the Internet.
|
34
|
-
def fetch_build(path)
|
35
|
-
|
36
|
-
is_remote = opensdg_is_path_remote(path)
|
37
|
-
build = {}
|
38
|
-
get_endpoints().each do |key, value|
|
39
|
-
endpoint = is_remote ? path + '/' + value : File.join(path, fix_path(value))
|
40
|
-
|
41
|
-
begin
|
42
|
-
json_file = is_remote ? open(endpoint) : File.open(endpoint)
|
43
|
-
build[key] = JSON.load(json_file)
|
44
|
-
rescue StandardError => e
|
45
|
-
# For backwards compatibility, forego the exception in some cases.
|
46
|
-
abort_build = true
|
47
|
-
if ['translations', 'indicator_downloads', 'disaggregation', 'data_packages'].include? key
|
48
|
-
abort_build = false
|
49
|
-
elsif endpoint.include? '/untranslated/'
|
50
|
-
abort_build = false
|
51
|
-
end
|
52
|
-
if abort_build
|
53
|
-
puts e.message
|
54
|
-
abort 'Unable to read data from: ' + endpoint
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
return build
|
60
|
-
end
|
61
|
-
|
62
|
-
# Predict (before data has been fetched) whether the site is using
|
63
|
-
# translated builds or not.
|
64
|
-
def site_uses_translated_builds(path)
|
65
|
-
|
66
|
-
is_remote = opensdg_is_path_remote(path)
|
67
|
-
endpoints = get_endpoints()
|
68
|
-
# For a quick test, we just use 'meta'.
|
69
|
-
meta = endpoints['meta']
|
70
|
-
endpoint = is_remote ? path + '/' + meta : File.join(path, fix_path(meta))
|
71
|
-
|
72
|
-
begin
|
73
|
-
json_file = is_remote ? open(endpoint) : File.open(endpoint)
|
74
|
-
rescue StandardError => e
|
75
|
-
# If we didn't find an untranslated 'meta', we assume translated builds.
|
76
|
-
return true
|
77
|
-
end
|
78
|
-
|
79
|
-
# Other wise assume untranslated builds.
|
80
|
-
return false
|
81
|
-
end
|
82
|
-
|
83
|
-
def generate(site)
|
84
|
-
|
85
|
-
# For below, make sure there is at least an empty hash at
|
86
|
-
# site.data.translations.
|
87
|
-
if !site.data.has_key?('translations')
|
88
|
-
site.data['translations'] = {}
|
89
|
-
end
|
90
|
-
|
91
|
-
remote = site.config['remote_data_prefix']
|
92
|
-
local = site.config['local_data_folder']
|
93
|
-
|
94
|
-
if !remote && !local
|
95
|
-
abort 'Site config must include "remote_data_prefix".'
|
96
|
-
end
|
97
|
-
|
98
|
-
build_location = remote ? remote : local
|
99
|
-
is_remote = opensdg_is_path_remote(build_location)
|
100
|
-
|
101
|
-
build_location = is_remote ? build_location : File.join(Dir.pwd, build_location)
|
102
|
-
translated_builds = site_uses_translated_builds(build_location)
|
103
|
-
|
104
|
-
if translated_builds
|
105
|
-
# For translated builds, we get a build for each language, and
|
106
|
-
# place them in "subfolders" (so to speak) of site.data.
|
107
|
-
subfolders = site.config['languages'].clone
|
108
|
-
subfolders.append('untranslated')
|
109
|
-
subfolders.each do |language|
|
110
|
-
data_target = site.data[language]
|
111
|
-
translated_build = is_remote ? build_location + '/' + language : File.join(build_location, language)
|
112
|
-
data_source = fetch_build(translated_build)
|
113
|
-
if !data_source.empty?
|
114
|
-
if data_target
|
115
|
-
data_target.deep_merge(data_source)
|
116
|
-
else
|
117
|
-
site.data[language] = data_source
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
# We move the language-specific translations to the
|
122
|
-
# site.data.translations location, where all translations are kept.
|
123
|
-
site.config['languages'].each do |language|
|
124
|
-
translation_target = site.data['translations'][language]
|
125
|
-
translation_source = site.data[language]['translations']
|
126
|
-
if translation_target
|
127
|
-
translation_target.deep_merge(translation_source)
|
128
|
-
else
|
129
|
-
site.data['translations'][language] = translation_source
|
130
|
-
end
|
131
|
-
end
|
132
|
-
# And there are some parts of the build that don't need to be translated
|
133
|
-
# and should be moved to the top level.
|
134
|
-
first_language = site.config['languages'][0]
|
135
|
-
site.data['reporting'] = site.data[first_language]['reporting']
|
136
|
-
site.data['schema'] = site.data[first_language]['schema']
|
137
|
-
site.data['zip'] = site.data[first_language]['zip']
|
138
|
-
else
|
139
|
-
# For untranslated builds, we download one build only, and place it
|
140
|
-
# in the "root" (so to speak) of site.data. Nothing else is needed.
|
141
|
-
target = site.data
|
142
|
-
source = fetch_build(build_location)
|
143
|
-
if !source.empty?
|
144
|
-
target.deep_merge(source)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Finally support the deprecated 'remote_translations' option.
|
149
|
-
# This is deprecated because translations should now be in the
|
150
|
-
# data repository, where they will be fetched in fetch_build().
|
151
|
-
if site.config['remote_translations']
|
152
|
-
key = 'translations'
|
153
|
-
target = site.data[key]
|
154
|
-
site.config['remote_translations'].each do |endpoint|
|
155
|
-
begin
|
156
|
-
source = JSON.load(open(endpoint))
|
157
|
-
if target
|
158
|
-
target.deep_merge(source)
|
159
|
-
else
|
160
|
-
site.data[key] = source
|
161
|
-
end
|
162
|
-
rescue StandardError => e
|
163
|
-
puts e.message
|
164
|
-
abort 'Unable to fetch remote translation from: ' + endpoint
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
# This makes sure that the contents of the "local_data_folder" get copied
|
172
|
-
# into the Jekyll build, so that they can be served from the website.
|
173
|
-
Jekyll::Hooks.register :site, :post_write do |site|
|
174
|
-
if site.config['local_data_folder']
|
175
|
-
source = File.join(Dir.pwd, site.config['local_data_folder'], '.')
|
176
|
-
destination = site.config['destination']
|
177
|
-
FileUtils.cp_r(source, destination)
|
178
|
-
# Do the same in the case that "remote_data_prefix" is being used for a local
|
179
|
-
# data folder (since "local_data_folder" is deprecated and undocumented).
|
180
|
-
elsif site.config['remote_data_prefix']
|
181
|
-
if !opensdg_is_path_remote(site.config['remote_data_prefix'])
|
182
|
-
source = File.join(Dir.pwd, site.config['remote_data_prefix'], '.')
|
183
|
-
destination = site.config['destination']
|
184
|
-
FileUtils.cp_r(source, destination)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
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
|
+
'data_packages' => 'data-packages/all.json',
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Get a build from a local folder on disk or a remote URL on the Internet.
|
34
|
+
def fetch_build(path)
|
35
|
+
|
36
|
+
is_remote = opensdg_is_path_remote(path)
|
37
|
+
build = {}
|
38
|
+
get_endpoints().each do |key, value|
|
39
|
+
endpoint = is_remote ? path + '/' + value : File.join(path, fix_path(value))
|
40
|
+
|
41
|
+
begin
|
42
|
+
json_file = is_remote ? open(endpoint) : File.open(endpoint)
|
43
|
+
build[key] = JSON.load(json_file)
|
44
|
+
rescue StandardError => e
|
45
|
+
# For backwards compatibility, forego the exception in some cases.
|
46
|
+
abort_build = true
|
47
|
+
if ['translations', 'indicator_downloads', 'disaggregation', 'data_packages'].include? key
|
48
|
+
abort_build = false
|
49
|
+
elsif endpoint.include? '/untranslated/'
|
50
|
+
abort_build = false
|
51
|
+
end
|
52
|
+
if abort_build
|
53
|
+
puts e.message
|
54
|
+
abort 'Unable to read data from: ' + endpoint
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
return build
|
60
|
+
end
|
61
|
+
|
62
|
+
# Predict (before data has been fetched) whether the site is using
|
63
|
+
# translated builds or not.
|
64
|
+
def site_uses_translated_builds(path)
|
65
|
+
|
66
|
+
is_remote = opensdg_is_path_remote(path)
|
67
|
+
endpoints = get_endpoints()
|
68
|
+
# For a quick test, we just use 'meta'.
|
69
|
+
meta = endpoints['meta']
|
70
|
+
endpoint = is_remote ? path + '/' + meta : File.join(path, fix_path(meta))
|
71
|
+
|
72
|
+
begin
|
73
|
+
json_file = is_remote ? open(endpoint) : File.open(endpoint)
|
74
|
+
rescue StandardError => e
|
75
|
+
# If we didn't find an untranslated 'meta', we assume translated builds.
|
76
|
+
return true
|
77
|
+
end
|
78
|
+
|
79
|
+
# Other wise assume untranslated builds.
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate(site)
|
84
|
+
|
85
|
+
# For below, make sure there is at least an empty hash at
|
86
|
+
# site.data.translations.
|
87
|
+
if !site.data.has_key?('translations')
|
88
|
+
site.data['translations'] = {}
|
89
|
+
end
|
90
|
+
|
91
|
+
remote = site.config['remote_data_prefix']
|
92
|
+
local = site.config['local_data_folder']
|
93
|
+
|
94
|
+
if !remote && !local
|
95
|
+
abort 'Site config must include "remote_data_prefix".'
|
96
|
+
end
|
97
|
+
|
98
|
+
build_location = remote ? remote : local
|
99
|
+
is_remote = opensdg_is_path_remote(build_location)
|
100
|
+
|
101
|
+
build_location = is_remote ? build_location : File.join(Dir.pwd, build_location)
|
102
|
+
translated_builds = site_uses_translated_builds(build_location)
|
103
|
+
|
104
|
+
if translated_builds
|
105
|
+
# For translated builds, we get a build for each language, and
|
106
|
+
# place them in "subfolders" (so to speak) of site.data.
|
107
|
+
subfolders = site.config['languages'].clone
|
108
|
+
subfolders.append('untranslated')
|
109
|
+
subfolders.each do |language|
|
110
|
+
data_target = site.data[language]
|
111
|
+
translated_build = is_remote ? build_location + '/' + language : File.join(build_location, language)
|
112
|
+
data_source = fetch_build(translated_build)
|
113
|
+
if !data_source.empty?
|
114
|
+
if data_target
|
115
|
+
data_target.deep_merge(data_source)
|
116
|
+
else
|
117
|
+
site.data[language] = data_source
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
# We move the language-specific translations to the
|
122
|
+
# site.data.translations location, where all translations are kept.
|
123
|
+
site.config['languages'].each do |language|
|
124
|
+
translation_target = site.data['translations'][language]
|
125
|
+
translation_source = site.data[language]['translations']
|
126
|
+
if translation_target
|
127
|
+
translation_target.deep_merge(translation_source)
|
128
|
+
else
|
129
|
+
site.data['translations'][language] = translation_source
|
130
|
+
end
|
131
|
+
end
|
132
|
+
# And there are some parts of the build that don't need to be translated
|
133
|
+
# and should be moved to the top level.
|
134
|
+
first_language = site.config['languages'][0]
|
135
|
+
site.data['reporting'] = site.data[first_language]['reporting']
|
136
|
+
site.data['schema'] = site.data[first_language]['schema']
|
137
|
+
site.data['zip'] = site.data[first_language]['zip']
|
138
|
+
else
|
139
|
+
# For untranslated builds, we download one build only, and place it
|
140
|
+
# in the "root" (so to speak) of site.data. Nothing else is needed.
|
141
|
+
target = site.data
|
142
|
+
source = fetch_build(build_location)
|
143
|
+
if !source.empty?
|
144
|
+
target.deep_merge(source)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Finally support the deprecated 'remote_translations' option.
|
149
|
+
# This is deprecated because translations should now be in the
|
150
|
+
# data repository, where they will be fetched in fetch_build().
|
151
|
+
if site.config['remote_translations']
|
152
|
+
key = 'translations'
|
153
|
+
target = site.data[key]
|
154
|
+
site.config['remote_translations'].each do |endpoint|
|
155
|
+
begin
|
156
|
+
source = JSON.load(open(endpoint))
|
157
|
+
if target
|
158
|
+
target.deep_merge(source)
|
159
|
+
else
|
160
|
+
site.data[key] = source
|
161
|
+
end
|
162
|
+
rescue StandardError => e
|
163
|
+
puts e.message
|
164
|
+
abort 'Unable to fetch remote translation from: ' + endpoint
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# This makes sure that the contents of the "local_data_folder" get copied
|
172
|
+
# into the Jekyll build, so that they can be served from the website.
|
173
|
+
Jekyll::Hooks.register :site, :post_write do |site|
|
174
|
+
if site.config['local_data_folder']
|
175
|
+
source = File.join(Dir.pwd, site.config['local_data_folder'], '.')
|
176
|
+
destination = site.config['destination']
|
177
|
+
FileUtils.cp_r(source, destination)
|
178
|
+
# Do the same in the case that "remote_data_prefix" is being used for a local
|
179
|
+
# data folder (since "local_data_folder" is deprecated and undocumented).
|
180
|
+
elsif site.config['remote_data_prefix']
|
181
|
+
if !opensdg_is_path_remote(site.config['remote_data_prefix'])
|
182
|
+
source = File.join(Dir.pwd, site.config['remote_data_prefix'], '.')
|
183
|
+
destination = site.config['destination']
|
184
|
+
FileUtils.cp_r(source, destination)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -1,132 +1,132 @@
|
|
1
|
-
# Simple collection of helper functions for use in these plugins.
|
2
|
-
|
3
|
-
require "jekyll"
|
4
|
-
|
5
|
-
# Takes a translation key and returns a translated string according to the
|
6
|
-
# language of the current page. Or if none is found, returns the original
|
7
|
-
# key.
|
8
|
-
def opensdg_translate_key(key, translations, language)
|
9
|
-
|
10
|
-
# Safety code - abort now if key is nil.
|
11
|
-
if key.nil?
|
12
|
-
return ""
|
13
|
-
end
|
14
|
-
|
15
|
-
# Also make sure it is a string, and other just return it.
|
16
|
-
if not key.is_a? String
|
17
|
-
return key
|
18
|
-
end
|
19
|
-
|
20
|
-
# More safety code - abort now if key is empty.
|
21
|
-
if key.empty?
|
22
|
-
return ""
|
23
|
-
end
|
24
|
-
|
25
|
-
# Keep track of the last thing we drilled to.
|
26
|
-
drilled = translations[language]
|
27
|
-
|
28
|
-
# Keep track of how many levels we have drilled.
|
29
|
-
levels_drilled = 0
|
30
|
-
levels = key.split('.')
|
31
|
-
|
32
|
-
# Loop through each level.
|
33
|
-
levels.each do |level|
|
34
|
-
|
35
|
-
# If we have drilled down to a scalar value too soon, abort.
|
36
|
-
break if drilled.class != Hash
|
37
|
-
|
38
|
-
if drilled.has_key? level
|
39
|
-
# If we find something, continue drilling.
|
40
|
-
drilled = drilled[level]
|
41
|
-
levels_drilled += 1
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
# If we didn't drill the right number of levels, return the
|
47
|
-
# original string.
|
48
|
-
if levels.length != levels_drilled
|
49
|
-
return key
|
50
|
-
end
|
51
|
-
|
52
|
-
# Otherwise we must have drilled all they way.
|
53
|
-
return drilled
|
54
|
-
end
|
55
|
-
|
56
|
-
# Takes a site object and decides whether it is using translated builds.
|
57
|
-
def opensdg_translated_builds(site)
|
58
|
-
# Assume the site is using translated builds.
|
59
|
-
translated_builds = true
|
60
|
-
site.config['languages'].each do |language|
|
61
|
-
# If any languages don't have a key in site.data, the site is not using
|
62
|
-
# translated builds.
|
63
|
-
if !site.data.has_key? language
|
64
|
-
translated_builds = false
|
65
|
-
end
|
66
|
-
end
|
67
|
-
return translated_builds
|
68
|
-
end
|
69
|
-
|
70
|
-
# Print a notice during compilation.
|
71
|
-
def opensdg_notice(message)
|
72
|
-
Jekyll.logger.warn message.yellow
|
73
|
-
end
|
74
|
-
|
75
|
-
# Get the public language codes for a site, keyed by the actual language codes.
|
76
|
-
def opensdg_languages_public(site)
|
77
|
-
languages_public = site.config['languages_public']
|
78
|
-
|
79
|
-
# The current structure of the setting is an array of hashes, each containing
|
80
|
-
# keys for "language" and "language_public".
|
81
|
-
if languages_public.is_a?(Array)
|
82
|
-
converted_languages_public = Hash.new
|
83
|
-
languages_public.each do |language_public|
|
84
|
-
language_code = language_public['language']
|
85
|
-
language_code_public = language_public['language_public']
|
86
|
-
converted_languages_public[language_code] = language_code_public
|
87
|
-
end
|
88
|
-
return converted_languages_public
|
89
|
-
end
|
90
|
-
|
91
|
-
# Fallback to exactly what was retrieved from site.confg['languages_public'],
|
92
|
-
# since the deprecated structure is exactly what this function wants.
|
93
|
-
return languages_public
|
94
|
-
end
|
95
|
-
|
96
|
-
# Print notices about a validation error.
|
97
|
-
def opensdg_validation_error(error)
|
98
|
-
if error['type'] == 'required'
|
99
|
-
missing = []
|
100
|
-
error['schema']['required'].each do |required_property|
|
101
|
-
unless error['data'].has_key?(required_property)
|
102
|
-
message = 'Missing configuration setting: ' + required_property
|
103
|
-
if error['schema'].has_key?('title')
|
104
|
-
message += ' (' + error['schema']['title'] + ')'
|
105
|
-
end
|
106
|
-
opensdg_notice(message)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
else
|
110
|
-
message = 'Validation error of type: ' + error['type']
|
111
|
-
if error['schema'] && error['schema'].has_key?('title')
|
112
|
-
message += ' (' + error['schema']['title'] + ')'
|
113
|
-
end
|
114
|
-
opensdg_notice(message)
|
115
|
-
if error['schema']
|
116
|
-
opensdg_notice('Expected schema:')
|
117
|
-
puts error['schema'].inspect
|
118
|
-
end
|
119
|
-
if error['data']
|
120
|
-
opensdg_notice('Actual data:')
|
121
|
-
puts error['data'].inspect
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Is this path a remote path?
|
127
|
-
def opensdg_is_path_remote(path)
|
128
|
-
if path.nil?
|
129
|
-
return false
|
130
|
-
end
|
131
|
-
return path.start_with?('http')
|
132
|
-
end
|
1
|
+
# Simple collection of helper functions for use in these plugins.
|
2
|
+
|
3
|
+
require "jekyll"
|
4
|
+
|
5
|
+
# Takes a translation key and returns a translated string according to the
|
6
|
+
# language of the current page. Or if none is found, returns the original
|
7
|
+
# key.
|
8
|
+
def opensdg_translate_key(key, translations, language)
|
9
|
+
|
10
|
+
# Safety code - abort now if key is nil.
|
11
|
+
if key.nil?
|
12
|
+
return ""
|
13
|
+
end
|
14
|
+
|
15
|
+
# Also make sure it is a string, and other just return it.
|
16
|
+
if not key.is_a? String
|
17
|
+
return key
|
18
|
+
end
|
19
|
+
|
20
|
+
# More safety code - abort now if key is empty.
|
21
|
+
if key.empty?
|
22
|
+
return ""
|
23
|
+
end
|
24
|
+
|
25
|
+
# Keep track of the last thing we drilled to.
|
26
|
+
drilled = translations[language]
|
27
|
+
|
28
|
+
# Keep track of how many levels we have drilled.
|
29
|
+
levels_drilled = 0
|
30
|
+
levels = key.split('.')
|
31
|
+
|
32
|
+
# Loop through each level.
|
33
|
+
levels.each do |level|
|
34
|
+
|
35
|
+
# If we have drilled down to a scalar value too soon, abort.
|
36
|
+
break if drilled.class != Hash
|
37
|
+
|
38
|
+
if drilled.has_key? level
|
39
|
+
# If we find something, continue drilling.
|
40
|
+
drilled = drilled[level]
|
41
|
+
levels_drilled += 1
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# If we didn't drill the right number of levels, return the
|
47
|
+
# original string.
|
48
|
+
if levels.length != levels_drilled
|
49
|
+
return key
|
50
|
+
end
|
51
|
+
|
52
|
+
# Otherwise we must have drilled all they way.
|
53
|
+
return drilled
|
54
|
+
end
|
55
|
+
|
56
|
+
# Takes a site object and decides whether it is using translated builds.
|
57
|
+
def opensdg_translated_builds(site)
|
58
|
+
# Assume the site is using translated builds.
|
59
|
+
translated_builds = true
|
60
|
+
site.config['languages'].each do |language|
|
61
|
+
# If any languages don't have a key in site.data, the site is not using
|
62
|
+
# translated builds.
|
63
|
+
if !site.data.has_key? language
|
64
|
+
translated_builds = false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return translated_builds
|
68
|
+
end
|
69
|
+
|
70
|
+
# Print a notice during compilation.
|
71
|
+
def opensdg_notice(message)
|
72
|
+
Jekyll.logger.warn message.yellow
|
73
|
+
end
|
74
|
+
|
75
|
+
# Get the public language codes for a site, keyed by the actual language codes.
|
76
|
+
def opensdg_languages_public(site)
|
77
|
+
languages_public = site.config['languages_public']
|
78
|
+
|
79
|
+
# The current structure of the setting is an array of hashes, each containing
|
80
|
+
# keys for "language" and "language_public".
|
81
|
+
if languages_public.is_a?(Array)
|
82
|
+
converted_languages_public = Hash.new
|
83
|
+
languages_public.each do |language_public|
|
84
|
+
language_code = language_public['language']
|
85
|
+
language_code_public = language_public['language_public']
|
86
|
+
converted_languages_public[language_code] = language_code_public
|
87
|
+
end
|
88
|
+
return converted_languages_public
|
89
|
+
end
|
90
|
+
|
91
|
+
# Fallback to exactly what was retrieved from site.confg['languages_public'],
|
92
|
+
# since the deprecated structure is exactly what this function wants.
|
93
|
+
return languages_public
|
94
|
+
end
|
95
|
+
|
96
|
+
# Print notices about a validation error.
|
97
|
+
def opensdg_validation_error(error)
|
98
|
+
if error['type'] == 'required'
|
99
|
+
missing = []
|
100
|
+
error['schema']['required'].each do |required_property|
|
101
|
+
unless error['data'].has_key?(required_property)
|
102
|
+
message = 'Missing configuration setting: ' + required_property
|
103
|
+
if error['schema'].has_key?('title')
|
104
|
+
message += ' (' + error['schema']['title'] + ')'
|
105
|
+
end
|
106
|
+
opensdg_notice(message)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
else
|
110
|
+
message = 'Validation error of type: ' + error['type']
|
111
|
+
if error['schema'] && error['schema'].has_key?('title')
|
112
|
+
message += ' (' + error['schema']['title'] + ')'
|
113
|
+
end
|
114
|
+
opensdg_notice(message)
|
115
|
+
if error['schema']
|
116
|
+
opensdg_notice('Expected schema:')
|
117
|
+
puts error['schema'].inspect
|
118
|
+
end
|
119
|
+
if error['data']
|
120
|
+
opensdg_notice('Actual data:')
|
121
|
+
puts error['data'].inspect
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Is this path a remote path?
|
127
|
+
def opensdg_is_path_remote(path)
|
128
|
+
if path.nil?
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
return path.start_with?('http')
|
132
|
+
end
|