Path: blob/main/_plugins/gtn/shortlinks.rb
1677 views
# frozen_string_literal: true12module Gtn3# This module is responsible for generating shortlinks for tutorials and FAQs and any other pages we add.4#5# Every category gets its own prefix letter.6module Shortlinks7CATEGORY_TUTORIAL = 'T'8CATEGORY_SLIDES = 'S'9CATEGORY_FAQ = 'F'10CATEGORY_NEWS = 'N'11CATEGORY_PATHWAYS = 'P'12CATEGORY_EVENTS = 'E'13CATEGORY_WORKFLOW = 'W'1415REDIRECT_TEMPLATE = <<~REDIR16<!DOCTYPE html>17<html lang="en-US">18<meta charset="utf-8">19<title>Redirecting…</title>20<link rel="canonical" href="REDIRECT_URL">21<script>location="REDIRECT_URL"</script>22<meta http-equiv="refresh" content="0; url=REDIRECT_URL">23<meta name="robots" content="noindex">24<h1>Redirecting…</h1>25<a href="REDIRECT_URL">Click here if you are not redirected.</a>26</html>27REDIR2829def self.mapped?(tutorial, current_mapping)30current_mapping['id'].values.include? tutorial31end3233##34# Duplicate of the jekyll-redirect-from plugin template.35# We can't use that for, reasons.36def self.html_redirect(target)37REDIRECT_TEMPLATE.gsub('REDIRECT_URL', target)38end3940##41# Fix missing symlinks (usually exist because the target file has been42# renamed and doesn't exist anymore.) However, a redirect *will* be present43# for the original filename so we just fix the missing symlink.44#45# Params:46# +site+:: The Jekyll site object47def self.fix_missing_redirs(site)48missing_redirs = site.data['shortlinks']['id'].select do |id, target|49short_link = "short/#{id}.html"50! File.exist?(site.in_dest_dir(short_link))51end5253missing_redirs.each do |id, target|54short_link = "short/#{id}.html"55Jekyll.logger.warn "[GTN/Shortlink]" "Shortlink target #{target} does not exist for shortlink #{short_link}, fixing."56File.write(site.in_dest_dir(short_link), Gtn::Shortlinks.html_redirect(target))57end58end5960def self.update(current_mapping)61current_mapping['id'] = {} if !current_mapping.key? 'id'6263current_mapping['name'] = {} if !current_mapping.key? 'name'6465# Discover tutorials66num_tutorials = current_mapping['id'].select { |x| x[0] == CATEGORY_TUTORIAL }.length67Dir.glob('topics/*/tutorials/*/tutorial.md').each do |tutorial|68html_path = "/#{tutorial.gsub(/md$/, 'html')}"69# If it's not already mapped by a key, add it.70if !mapped?(html_path, current_mapping)71# Generate a short code72short_code_number = num_tutorials.to_s.rjust(5, '0')73short_code = CATEGORY_TUTORIAL + short_code_number74puts "Discovered tutorial #{short_code} (#{html_path})"75# If the target of this flavour of short code isn't already in here, then add it76current_mapping['id'][short_code] = html_path77num_tutorials += 178end7980# Also generate one from topic/tutorial name81# These are idempotent and safe82short_code2 = tutorial.split('/')[1..3].join('/').gsub(%r{/tutorials}, '')83current_mapping['name'][short_code2] = "/#{tutorial.gsub(/md$/, 'html')}"84end8586# Discover slides87num_slides = current_mapping['id'].select { |x| x[0] == CATEGORY_SLIDES }.length88Dir.glob('topics/*/tutorials/*/slides.html').each do |tutorial|89html_path = "/#{tutorial}"90# If it's not already mapped by a key, add it.91if !mapped?(html_path, current_mapping)92# Generate a short code93short_code_number = num_slides.to_s.rjust(5, '0')94short_code = CATEGORY_SLIDES + short_code_number95puts "Discovered slides #{short_code}"96# If the target of this flavour of short code isn't already in here, then add it97current_mapping['id'][short_code] = html_path98num_slides += 199end100101# Also generate one from topic/tutorial name102# These are idempotent and safe103short_code2 = "#{tutorial.split('/')[1..3].join('/').gsub(%r{/tutorials}, '')}/slides"104current_mapping['name'][short_code2] = "/#{tutorial.gsub(/md$/, 'html')}"105end106107# Discover FAQs108all_faqs = Dir.glob('faqs/**/*.md') + Dir.glob('topics/*/faqs/**/*.md') + \109Dir.glob('topics/*/tutorials/*/faqs/*.md')110# Remove symlinked files111all_faqs = all_faqs.reject { |x| File.symlink?(x) }112# Reject indexes, readme, etc.113all_faqs = all_faqs.grep_v(/index.md$/)114all_faqs = all_faqs.grep_v(/README.md$/)115116num_faqs = current_mapping['id'].select { |x| x[0] == CATEGORY_FAQ }.length117all_faqs.each do |tutorial|118html_path = "/#{tutorial.gsub(/md$/, 'html')}"119# If it's not already mapped by a key, add it.120if !mapped?(html_path, current_mapping)121# Generate a short code122short_code_number = num_faqs.to_s.rjust(5, '0')123short_code = CATEGORY_FAQ + short_code_number124puts "Discovered FAQ #{short_code}"125# If the target of this flavour of short code isn't already in here, then add it126current_mapping['id'][short_code] = html_path127num_faqs += 1128end129end130131# Discover news132num_news = current_mapping['id'].select { |x| x[0] == CATEGORY_NEWS }.length133Dir.glob('news/_posts/*.md').each do |material|134m = material.match(%r{news/_posts/(?<year>\d\d\d\d)-(?<month>\d\d)-(?<day>\d\d)-(?<title>.*)\.md})135html_path = "/news/#{m[:year]}/#{m[:month]}/#{m[:day]}/#{m[:title]}.html"136# If it's not already mapped by a key, add it.137if !mapped?(html_path, current_mapping)138# Generate a short code139short_code_number = num_news.to_s.rjust(5, '0')140short_code = CATEGORY_NEWS + short_code_number141puts "Discovered news #{short_code}"142# If the target of this flavour of short code isn't already in here, then add it143current_mapping['id'][short_code] = html_path144num_news += 1145end146end147148# Discover learning pathways149lps = Dir.glob('learning-pathways/*.md')150lps.reject! { |t| t =~ /index.md/ }151lps.reject! { |t| t =~ /pathway-example.md/ }152153num_lps = current_mapping['id'].select { |x| x[0] == CATEGORY_PATHWAYS }.length154lps.each do |tutorial|155html_path = "/#{tutorial.gsub(/md$/, 'html')}"156# If it's not already mapped by a key, add it.157if !mapped?(html_path, current_mapping)158# Generate a short code159short_code_number = num_lps.to_s.rjust(5, '0')160short_code = CATEGORY_PATHWAYS + short_code_number161puts "Discovered learning pathway #{short_code}"162# If the target of this flavour of short code isn't already in here, then add it163current_mapping['id'][short_code] = html_path164num_lps += 1165end166end167168# Discover events169events = Dir.glob('events/*.md')170events.reject! { |t| t =~ /index.md/ }171events.reject! { |t| t =~ /pathway-example.md/ }172173num_events = current_mapping['id'].select { |x| x[0] == CATEGORY_EVENTS }.length174events.each do |event|175html_path = "/#{event.gsub(/md$/, 'html')}"176# If it's not already mapped by a key, add it.177if !mapped?(html_path, current_mapping)178# Generate a short code179short_code_number = num_events.to_s.rjust(5, '0')180short_code = CATEGORY_EVENTS + short_code_number181puts "Discovered event #{short_code}"182# If the target of this flavour of short code isn't already in here, then add it183current_mapping['id'][short_code] = html_path184num_events += 1185end186end187188# Discover workflows189workflows = Dir.glob('topics/**/workflows/*.ga')190191num_workflows = current_mapping['id'].select { |x| x[0] == CATEGORY_WORKFLOW }.length192workflows.each do |workflow|193html_path = "/#{workflow.gsub(/ga$/, 'html')}"194# If it's not already mapped by a key, add it.195if !mapped?(html_path, current_mapping)196# Generate a short code197short_code_number = num_workflows.to_s.rjust(5, '0')198short_code = CATEGORY_WORKFLOW + short_code_number199puts "Discovered workflow #{short_code}"200# If the target of this flavour of short code isn't already in here, then add it201current_mapping['id'][short_code] = html_path202num_workflows += 1203end204end205206current_mapping207end208end209end210211if $PROGRAM_NAME == __FILE__212require 'yaml'213current_mapping = YAML.load_file('metadata/shortlinks.yaml')214Gtn::Shortlinks.update(current_mapping)215File.write('metadata/shortlinks.yaml', current_mapping.to_yaml)216end217218219