# frozen_string_literal: true class FAQsLoaderService PATH = Rails.root.join('doc', 'faqs').freeze ORDER = ['usager', 'instructeur', 'administrateur'].freeze attr_reader :substitutions def initialize(substitutions) @substitutions = substitutions @faqs_by_path ||= Rails.cache.fetch(["faqs_data", ApplicationVersion.current, substitutions], expires_in: 1.day) do load_faqs end end def find(path) Rails.cache.fetch(["faq", path, ApplicationVersion.current, substitutions], expires_in: 1.day) do file_path = @faqs_by_path.fetch(path).fetch(:file_path) parse_with_substitutions(file_path) end end def faqs_for_category(category) @faqs_by_path.values .filter { |faq| faq[:category] == category } .group_by { |faq| faq[:subcategory] } end def all @faqs_by_path.values .group_by { |faq| faq.fetch(:category) } .sort_by { |category, _| ORDER.index(category) || ORDER.size } .to_h .transform_values do |faqs| faqs.group_by { |faq| faq.fetch(:subcategory) } end end private def load_faqs Dir.glob("#{PATH}/**/*.md").each_with_object({}) do |file_path, faqs_by_path| parsed = parse_with_substitutions(file_path) front_matter = parsed.front_matter.symbolize_keys faq_data = front_matter.slice(:slug, :title, :category, :subcategory, :locale, :keywords).merge(file_path: file_path) path = front_matter.fetch(:category) + '/' + front_matter.fetch(:slug) faqs_by_path[path] = faq_data end end # Substitute all string before front matter parser so metadata are also substituted. # using standard ruby formatting, ie => `%{my_var} % { my_var: 'value' }` # We have to escape % chars not used for substitutions, ie. not preceeded by { def parse_with_substitutions(file_path) substituted_content = File.read(file_path).gsub(/%(?!{)/, '%%') % substitutions FrontMatterParser::Parser.new(:md).call(substituted_content) end end