Skip to content

Commit

Permalink
Using Jekyll generator
Browse files Browse the repository at this point in the history
  • Loading branch information
marcwrobel committed Dec 17, 2022
1 parent 56a4267 commit f8e238b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 73 deletions.
16 changes: 16 additions & 0 deletions _layouts/product_v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"title": "{{ page.title }}",
"category": "{{ page.category }}",
"iconSlug": {% if page.iconSlug %}"{{ page.iconSlug }}"{% else %}null{% endif %},
"versionCommand": "{{ page.versionCommand }}",
"releasePolicyLink": "{{ page.releasePolicyLink }}",
"releases": [
{% for r in page.releases -%}
{
"cycle": "{{ r.releaseCycle }}",
"codename": {% if r.codename %}"{{r.codename}}"{% else %}null{% endif %},
"releaseDate": "{{ r.releaseDate }}"
}{% unless forloop.last %},{% endunless -%}
{%- endfor %}
]
}
99 changes: 26 additions & 73 deletions _plugins/generate-api-v1.rb
Original file line number Diff line number Diff line change
@@ -1,89 +1,42 @@
#!/usr/bin/env ruby

# This script creates API files for version 1 of the endoflife.date API.
#
# There are three kind of generated files :
# - all.json: contains the list of all the product names.
# - <product>.json: contains a given product data ()including releases data).
# - <product>/<release>.json: contains a given product release data.

require 'fileutils'
require 'json'
require 'yaml'
require 'date'
require 'jekyll'

module ApiV1

# This API path
DIR = 'api/v1'

# Returns the path of a file inside the API namespace.
def self.file(name, *args)
File.join(DIR, name, *args)
end

# Holds information about a product.
Product = Class.new do
attr_accessor :data

# Initializes the product with the given product's markdown file.
# The markdown file is expected to contain a YAML front-matter with the appropriate properties.
#
# Copying the data makes it easier to process it.
def initialize(data)
@data = Hash.new
# The product name is derived from the product's permalink (ex. /debian => debian).
@data["name"] = data['permalink'][1..data['permalink'].length]
@data["title"] = data['title']
@data["category"] = data['category']
@data["iconSlug"] = data['iconSlug']
@data["permalink"] = data['permalink']
@data["versionCommand"] = data['versionCommand']
@data["auto"] = data.has_key? 'auto'
@data["releasePolicyLink"] = data['releasePolicyLink']
@data["releases"] = data['releases'].map do |release|
release_data = Hash.new
release_data["name"] = release['releaseCycle']
release_data["codename"] = release['codename']
release_data["releaseDate"] = release['releaseDate']
release_data["support"] = release['support']
release_data["eol"] = release['eol']
release_data["discontinued"] = release['discontinued']
release_data["lts"] = release['lts'] || false # lts is optional, make sure it always has a value
release_data["latest"] = release['latest']
release_data["latestReleaseDate"] = release['latestReleaseDate']
release_data
class ApiGenerator < Jekyll::Generator
safe true
priority :lowest

def generate(site)
site.pages.each do |page|
is_markdown = (page.name.end_with?("md"))
has_permalink = (page.data.has_key? 'permalink')
has_releases = (page.data.has_key? 'releases')
is_product_page = (is_markdown and has_permalink and has_releases)
site.pages << ProductJson.new(site, page) if is_product_page
end
end

def name
data["name"]
end
end
end

product_names = []
FileUtils.mkdir_p(ApiV1::file('.'))

Dir['products/*.md'].each do |file|
# Load and prepare data
raw_data = YAML.safe_load(File.open(file), permitted_classes: [Date])
product = ApiV1::Product.new(raw_data)
product_names.append(product.name)

# Write /<product>.json
product_file = ApiV1::file("#{product.name}.json")
File.open(product_file, 'w') { |f| f.puts product.data.to_json }

# Write all /<product>/<release>.json
FileUtils.mkdir_p(ApiV1::file(product.name))
product.data["releases"].each do |release|
# Any / characters in the name are replaced with - to avoid file errors.
release_file = ApiV1::file(product.name, "#{release['name'].to_s.tr('/', '-')}.json")
File.open(release_file, 'w') { |f| f.puts release.to_json }
class ProductJson < Jekyll::Page
def initialize(site, product)
@site = site
@base = site.source
@dir = 'api/v1'
@name = product.data['permalink'][1..product.data['permalink'].length] + '.json'
@data = {}.merge(product.data)
@data['layout'] = 'product_v1'
@data.delete('permalink') # path already configured above, must not be overridden
@data.delete('alternate_urls') # TODO

self.process(@name)
self.read_yaml(File.join(site.source, '_layouts'), 'product_v1.json')
end
end
end

# Write /all.json
all_products_file = ApiV1::file('all.json')
File.open(all_products_file, 'w') { |f| f.puts product_names.sort.to_json }

0 comments on commit f8e238b

Please sign in to comment.