diff --git a/_layouts/v1_all_products.json b/_layouts/v1_all_products.json new file mode 100644 index 000000000000..91eb36313ff3 --- /dev/null +++ b/_layouts/v1_all_products.json @@ -0,0 +1,12 @@ +{ + "total": "{{ page.products | size }}", + "products": [ +{% for p in page.products %} + { + "name": "{{ p.id }}", + "category": "{{ p.category }}", + "permalink": "{{ site.url }}/{{ p.id }}" + }{% unless forloop.last %},{% endunless -%} +{%- endfor %} + ] +} diff --git a/_layouts/v1_product.json b/_layouts/v1_product.json new file mode 100644 index 000000000000..b51ed7400a29 --- /dev/null +++ b/_layouts/v1_product.json @@ -0,0 +1,25 @@ +{ + "title": "{{ page.title }}", + "category": "{{ page.category }}", + "iconSlug": "{{ page.iconSlug | default: page.id }}", + "permalink": "{{ site.url }}/{{ p.id }}", + "versionCommand": "{{ page.versionCommand }}", + "releasePolicyLink": "{{ page.releasePolicyLink }}", + "auto": {% if page.auto %}true{% else %}false{% endif %}, + "releases": [ +{% for r in page.releases %} + { + "cycle": "{{ r.releaseCycle }}", + "codename": {% if r.codename %}"{{ r.codename }}"{% else %}null{% endif %}, + "releaseDate": "{{ r.releaseDate }}", + "support": {% if r.support %}"{{ r.support }}"{% else %}null{% endif %}, + "eol": {% if r.eol %}"{{ r.eol }}"{% else %}null{% endif %}, + "latest": {% if r.latest %}"{{ r.latest }}"{% else %}null{% endif %}, + "latestReleaseDate": {% if r.latestReleaseDate %}"{{ r.latestReleaseDate }}"{% else %}null{% endif %}, + "lts": {% if r.lts %}{{ r.lts }}{% else %}false{% endif %}, + "discontinued": {% if r.diconstinued %}{{ r.discontinued }}{% else %}false{% endif %}, + "link": {% if r.link %}"{{ r.link }}"{% else %}null{% endif %} + }{% unless forloop.last %},{% endunless -%} +{%- endfor %} + ] +} diff --git a/_plugins/generate-api-v1.rb b/_plugins/generate-api-v1.rb index 2f93923af10f..5dacafc0090b 100755 --- a/_plugins/generate-api-v1.rb +++ b/_plugins/generate-api-v1.rb @@ -1,89 +1,68 @@ -#!/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. -# - .json: contains a given product data ()including releases data). -# - /.json: contains a given product release data. +# There are two kind of generated files : +# - all.json: contains endoflife metadata, such as the list of all the products and the product count. +# - .json: contains a given product data (including releases data). -require 'fileutils' -require 'json' -require 'yaml' -require 'date' +require 'jekyll' module ApiV1 - # This API path - DIR = 'api/v1' + class ApiGenerator < Jekyll::Generator + safe true + priority :lowest - # Returns the path of a file inside the API namespace. - def self.file(name, *args) - File.join(DIR, name, *args) - end + def generate(site) + all_products = [] - # Holds information about a product. - Product = Class.new do - attr_accessor :data + 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) - # 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 + if is_product_page + product_page = ProductJson.new(site, page) + site.pages << product_page + all_products << product_page + end end - end - def name - data["name"] + site.pages << AllProductsJson.new(site, all_products) end end -end -product_names = [] -FileUtils.mkdir_p(ApiV1::file('.')) + class ProductJson < Jekyll::Page + def initialize(site, product) + id = product.data['permalink'][1..product.data['permalink'].length] -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) + @site = site + @base = site.source + @dir = 'api/v1' + @name = "#{id}.json" - # Write /.json - product_file = ApiV1::file("#{product.name}.json") - File.open(product_file, 'w') { |f| f.puts product.data.to_json } + @data = {}.merge(product.data) + @data.delete('permalink') # path already configured above, must not be overridden + @data.delete('alternate_urls') # no need for API + @data['layout'] = 'v1_product' + @data['id'] = id # name is already a page attribute - # Write all //.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 } + self.process(@name) + 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 } + class AllProductsJson < Jekyll::Page + def initialize(site, all_products) + @site = site + @base = site.source + @dir = 'api/v1' + @name = "all.json" + + @data = {} + @data['layout'] = 'v1_all_products' + @data['products'] = all_products ? all_products : [] + + self.process(@name) + end + end +end