# frozen_string_literal: true require 'intranet/abstract_responder' require 'intranet/core/haml_wrapper' require 'mimemagic' require 'pandoc-ruby' require_relative 'version' module Intranet module Pandoc # The responder for the Pandoc module of the Intranet. class Responder < AbstractResponder include Core::HamlWrapper # 'inherits' from methods of HamlWrapper # Returns the name of the module. # @return [String] The name of the module. def self.module_name NAME end # The version of the module, according to semantic versionning. # @return [String] The version of the module. def self.module_version VERSION end # The homepage of the module. # @return [String] The homepage URL of the module. def self.module_homepage HOMEPAGE_URL end # Initializes a new Pandoc responder instance. # @param title [String] The title of the module instance. # @param rootdir [String] The root directory of the module instance. # @param in_menu [Boolean] Whether the module instance should be displayed in the main # navigation menu or not. def initialize(logger, title, rootdir, template = nil, in_menu = true) @logger = logger @title = title @rootdir = rootdir @template = template @in_menu = in_menu end # Specifies if the responder instance should be displayed in the main navigation menu or not. # @return [Boolean] True if the responder instance should be added to the main navigation # menu, False otherwise. def in_menu? @in_menu end # Specifies the absolute path to the resources directory for that module. # @return [String] The absolute path to the resources directory for the module. def resources_dir File.absolute_path(File.join('..', 'resources'), __dir__) end # Generates the HTML content associated to the given +path+ and +query+. # @param path [String] The requested URI, relative to that module root URI. # @param query [Hash] The URI variable/value pairs, if any. # @return [Integer, String, String] The HTTP return code, the MIME type and the answer body. def generate_page(path, query) case path when %r{^/.+\.html$} then serve_page(path.gsub(%r{^/(.+)\.html$}, '\\1')) when %r{^/.+\.(jpg|png)$} then serve_media(path.gsub(%r{^/(.+)$}, '\\1')) else super(path, query) end end # The title of the module instance, as displayed on the web page. # @return [String] The title of the module instance. attr_reader :title private # Provides the list of required stylesheets. # @return [Array] The list of required stylesheets. def stylesheets ['design/style.css'] end # Provides the list of required script files. # @return [Array>] The list of required scripts. def scripts [] end # Provides the list of Lua filters to be passed to Pandoc when converting mardown to HTML. # @return [Array] The list of Lua filters, relative to the . def lua_filters [ File.join(resources_dir, 'filters', 'titles-shift-levels.lua'), File.join(resources_dir, 'filters', 'links-open-external-in-new-tab.lua') ] end ########################################################################## ### Servicing of the HTML "display-able" content ### ########################################################################## # Convert a single markdown file to HTML format and returns the markup. # @param path [String] The path to the markdown file, relative to the module root directory # and without extension. # @raise [RuntimeError] If pandoc fails for whatever reason. def convert_to_html(path) input = "\"#{File.join(@rootdir, "#{path}.md")}\"" filters = lua_filters.map { |filter| "--lua-filter=\"#{filter}\"" } options = ['--standalone', "--template=\"#{@template}\""] unless @template.to_s.empty? PandocRuby.new([input], filters, options).to_html end def serve_page(path) content = "
#{convert_to_html(path)}
" [206, 'text/html', { content: content, title: @title, stylesheets: stylesheets, scripts: scripts }] rescue RuntimeError => e @logger.debug(e.message.chomp) [404, '', ''] end ########################################################################## ### Servicing of the media (pictures) ### ########################################################################## def serve_media(path) media_path = File.join(@rootdir, path) [200, MimeMagic.by_path(media_path).type, File.read(media_path)] rescue Errno::ENOENT [404, '', ''] end end end end