From d03f1ca7008bb8928de0ec8538d8c110516b68f7 Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Sun, 5 Mar 2023 13:48:40 +0800 Subject: [PATCH] Add GitLab raw content include processor --- lib/asciidoctor/foodogsquared-extensions.rb | 2 + .../README.adoc | 40 +++++++++++ .../extension.rb | 70 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 lib/asciidoctor/gitlab-raw-content-include-processor/README.adoc create mode 100644 lib/asciidoctor/gitlab-raw-content-include-processor/extension.rb diff --git a/lib/asciidoctor/foodogsquared-extensions.rb b/lib/asciidoctor/foodogsquared-extensions.rb index ed9c274..d98ce3d 100644 --- a/lib/asciidoctor/foodogsquared-extensions.rb +++ b/lib/asciidoctor/foodogsquared-extensions.rb @@ -3,9 +3,11 @@ require 'asciidoctor/extensions' require_relative 'man-inline-macro/extension' require_relative 'swhid-inline-macro/extension' require_relative 'github-raw-content-include-processor/extension' +require_relative 'gitlab-raw-content-include-processor/extension' Asciidoctor::Extensions.register do inline_macro ManInlineMacro inline_macro SWHInlineMacro include_processor GitHubRawIncludeProcessor + include_processor GitLabRawIncludeProcessor end diff --git a/lib/asciidoctor/gitlab-raw-content-include-processor/README.adoc b/lib/asciidoctor/gitlab-raw-content-include-processor/README.adoc new file mode 100644 index 0000000..8f84a26 --- /dev/null +++ b/lib/asciidoctor/gitlab-raw-content-include-processor/README.adoc @@ -0,0 +1,40 @@ += GitLab raw content include processor +:toc: + + +It's a link:https://docs.asciidoctor.org/asciidoctor/latest/extensions/include-processor/[include processor] for easily including raw content from GitLab repositories. + + +== Synopsis + +[source, asciidoc] +---- +include::gitlab/$OWNER/$REPO[rev=$COMMIT, path=$FILEPATH] +---- + + +== Extra notes + +A link:https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-tokens[personal access token] is most likely required. +Get one and place the value in an environment variable `GITLAB_API_PERSONAL_ACCESS_TOKEN`. + + +== Attributes + +There are some attributes required to be passed. + +- `rev` is the commit to be checked out. +- `path` is the file path to be included. + +Aside from the required attributes, there are optional attributes to configured further. + +- `domain` is the domain of the GitLab instance. +By default, it points to the `gitlab.com` official instance. + +- `version` is the version string of the API to be used. +By default, it uses version `v4`. + + +== Example usage + +- `include::gitlab:gitlab-org/gitlab[rev=master, path=README.md]` should diff --git a/lib/asciidoctor/gitlab-raw-content-include-processor/extension.rb b/lib/asciidoctor/gitlab-raw-content-include-processor/extension.rb new file mode 100644 index 0000000..d6422b9 --- /dev/null +++ b/lib/asciidoctor/gitlab-raw-content-include-processor/extension.rb @@ -0,0 +1,70 @@ +require 'base64' +require 'json' +require 'open-uri' +require 'uri' + +class GitLabRawIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor + @@prefix = 'gitlab:' + + def handles? target + target.start_with? @@prefix + 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(@@prefix).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 + + begin + OpenURI.open_uri( + uri, + 'Content-Type' => 'application/json', + 'PRIVATE-TOKEN' => ENV['GITLAB_API_PERSONAL_ACCESS_TOKEN'], + ) do |f| + response = JSON.parse(f.read) + + if response['content'] && response['encoding'] == 'base64' + Base64.decode64 response['content'] + end + + reader.push_include content, target, target, 1, attrs + end + rescue OpenURI::HTTPError => e + warning = %(error while getting '#{path}' in GitLab repo '#{repo}': #{e}) + warn_or_raise doc, warning + reader.push_include warning, target, target, 1, attrs + end + + reader + end +end