# frozen_string_literal: true require 'base64' require 'json' require 'open-uri' require 'uri' class GitLabRawIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor def handles?(target) target.start_with? 'gitlab:' end def warn_or_raise(doc, warning) if (doc.safe > Asciidoctor::SafeMode::SERVER) && !(doc.attr? 'allow-uri-read') raise warning else warn warning end end def process(doc, reader, target, attrs) src = target.delete_prefix('gitlab:').split('/', 2) owner = src.at 0 repo = src.at 1 namespaced_repo = "#{owner}/#{repo}" raise %(there is no 'path' attribute given for GitLab repo '#{namespaced_repo}') unless attrs.key? 'path' raise %(no given ref for getting file in '#{namespaced_repo}') unless attrs.key? 'rev' path = attrs['path'] rev = attrs['rev'] domain = attrs['domain'] || 'gitlab.com' version = attrs['version'] || 'v4' uri = URI.parse %(https://#{domain}/api/#{version}) # Set the project. uri += %(/projects/#{URI.encode_www_form_component namespaced_repo}) # Then the filename. uri += %(/repository/files/#{URI.encode_www_form_component path}) # Then the revision. query = { ref: rev } uri.query = URI.encode_www_form query content = begin headers = { 'Content-Type' => 'application-json' } header['PRIVATE-TOKEN'] = ENV['GITLAB_API_PERSONAL_ACCESS_TOKEN'] if ENV['GITLAB_API_PERSONAL_ACCESS_TOKEN'] OpenURI.open_uri(uri, headers) do |f| response = JSON.parse(f.read) Base64.decode64 response['content'] if response['content'] && response['encoding'] == 'base64' end rescue OpenURI::HTTPError => e warning = %(error while getting '#{path}' in GitLab repo '#{repo}': #{e}) warn_or_raise doc, warning warning end reader.push_include content, target, target, 1, attrs reader end end