mirror of
https://github.com/foo-dogsquared/asciidoctor-foodogsquared-extensions.git
synced 2025-02-07 06:19:01 +00:00
Restructure extensions with Ruby modules
Also restructured how they're named in the filesystem and the class names as well.
This commit is contained in:
parent
69c8015292
commit
de9f3a0e9c
@ -1,3 +1,3 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'asciidoctor/foodogsquared-extensions'
|
require 'asciidoctor/foodogsquared/extensions'
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class ChatBlock < Asciidoctor::Extensions::BlockProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :chat
|
|
||||||
on_context :example
|
|
||||||
name_positional_attributes 'avatar', 'state'
|
|
||||||
default_attributes 'state' => 'default'
|
|
||||||
|
|
||||||
def process(parent, reader, attrs)
|
|
||||||
block = create_block parent, :pass, nil, attrs, content_model: :compound
|
|
||||||
block.add_role('dialogblock')
|
|
||||||
|
|
||||||
# You can think of this section as a pipeline constructing the HTML
|
|
||||||
# component for this block. Specifically, we're building one component that
|
|
||||||
# contains two output: the dialog image of our avatar and its content.
|
|
||||||
attrs['name'] ||= attrs['avatar']
|
|
||||||
|
|
||||||
block << (create_html_fragment block, <<~HTML
|
|
||||||
<div role="figure" class="dialogblock dialogblock__box dialogblock__avatar--#{attrs['avatar']} #{attrs['role']}">
|
|
||||||
<div class="dialogblock dialogblock__avatar">
|
|
||||||
HTML
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
attrs['avatarsdir'] ||= File.expand_path('./avatars', attrs['iconsdir'])
|
|
||||||
attrs['avatarstype'] ||= parent.attributes['avatarstype'] || 'avif'
|
|
||||||
|
|
||||||
avatar_sticker = "#{attrs['avatar'].to_kebab}/#{attrs['state'].to_kebab}.#{attrs['avatarstype']}"
|
|
||||||
avatar_img_attrs = {
|
|
||||||
'target' => parent.image_uri(avatar_sticker, 'avatarsdir'),
|
|
||||||
'alt' => attrs['name']
|
|
||||||
}
|
|
||||||
avatar_imgblock = create_image_block block, avatar_img_attrs
|
|
||||||
|
|
||||||
block << avatar_imgblock
|
|
||||||
block << (create_html_fragment block, <<~HTML
|
|
||||||
</div>
|
|
||||||
<div class="dialogblock dialogblock__text">
|
|
||||||
<small class="dialogblock dialogblock__avatar-name">#{attrs['name']}</small>
|
|
||||||
HTML
|
|
||||||
)
|
|
||||||
|
|
||||||
parse_content block, reader
|
|
||||||
|
|
||||||
block << (create_html_fragment block, <<~HTML
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
HTML
|
|
||||||
)
|
|
||||||
|
|
||||||
block
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def create_html_fragment(parent, html, attributes = nil)
|
|
||||||
create_block parent, :pass, html, attributes
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,26 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'open-uri'
|
|
||||||
require 'yaml'
|
|
||||||
|
|
||||||
class FDroidLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :fdroid
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
default_attributes 'lang' => 'en'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
|
|
||||||
app_id = target
|
|
||||||
app_metadata_uri = %(https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/#{app_id}.yml)
|
|
||||||
|
|
||||||
metadata = OpenURI.open_uri(app_metadata_uri) { |f| YAML.safe_load(f.read) }
|
|
||||||
attrs['caption'] ||= metadata['AutoName']
|
|
||||||
|
|
||||||
url = %(https://f-droid.org/#{attrs['lang']}/packages/#{app_id})
|
|
||||||
doc.register :links, url
|
|
||||||
create_anchor parent, attrs['caption'], type: :link, target: url
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,33 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'json'
|
|
||||||
require 'open-uri'
|
|
||||||
|
|
||||||
class FlathubLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :flathub
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
|
|
||||||
# FlatHub API seems to have no documentation aside from the source code.
|
|
||||||
# You can easily infer the API with its source code at
|
|
||||||
# https://github.com/flathub/website.
|
|
||||||
app_id = target
|
|
||||||
app_metadata_uri = %(https://flathub.org/api/v2/appstream/#{app_id})
|
|
||||||
|
|
||||||
headers = {
|
|
||||||
'Accept' => 'application/json',
|
|
||||||
'User-Agent' => ::Asciidoctor::FoodogsquaredCustomExtensions::USER_AGENT
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata = OpenURI.open_uri(app_metadata_uri, headers) { |f| JSON.parse(f.read) }
|
|
||||||
attrs['caption'] ||= metadata['name']
|
|
||||||
|
|
||||||
url = %(https://flathub.org/apps/#{app_id})
|
|
||||||
doc.register :links, url
|
|
||||||
create_anchor parent, attrs['caption'], type: :link, target: url
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,55 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'asciidoctor'
|
|
||||||
require 'asciidoctor/extensions'
|
|
||||||
|
|
||||||
require_relative 'helpers'
|
|
||||||
|
|
||||||
require_relative 'man-inline-macro/extension'
|
|
||||||
require_relative 'swhid-inline-macro/extension'
|
|
||||||
require_relative 'swhid-include-processor/extension'
|
|
||||||
require_relative 'github-link-inline-macro/extension'
|
|
||||||
require_relative 'github-raw-content-include-processor/extension'
|
|
||||||
require_relative 'gitlab-link-inline-macro/extension'
|
|
||||||
require_relative 'gitlab-raw-content-include-processor/extension'
|
|
||||||
require_relative 'chat-block-processor/extension'
|
|
||||||
require_relative 'git-blob-include-processor/extension'
|
|
||||||
require_relative 'wikipedia-inline-macro/extension'
|
|
||||||
require_relative 'package-indices-link-macro/extension'
|
|
||||||
require_relative 'fdroid-link-inline-macro/extension'
|
|
||||||
require_relative 'musicbrainz-link-inline-macro/extension'
|
|
||||||
require_relative 'flathub-link-inline-macro/extension'
|
|
||||||
require_relative 'repology-link-inline-macro/extension'
|
|
||||||
require_relative 'ietf-rfc-link-inline-macro/extension'
|
|
||||||
|
|
||||||
Asciidoctor::Extensions.register do
|
|
||||||
inline_macro ManInlineMacro
|
|
||||||
inline_macro IETFRFCLinkInlineMacro
|
|
||||||
block ChatBlock if @document.basebackend? 'html'
|
|
||||||
|
|
||||||
inline_macro SWHInlineMacro
|
|
||||||
include_processor SWHIDIncludeProcessor
|
|
||||||
|
|
||||||
inline_macro GitHubLinkInlineMacro
|
|
||||||
include_processor GitHubRawIncludeProcessor
|
|
||||||
|
|
||||||
inline_macro GitLabLinkInlineMacro
|
|
||||||
include_processor GitLabRawIncludeProcessor
|
|
||||||
|
|
||||||
include_processor GitBlobIncludeProcessor
|
|
||||||
|
|
||||||
inline_macro WikipediaInlineMacro
|
|
||||||
|
|
||||||
# Package indices
|
|
||||||
inline_macro CtanLinkInlineMacro
|
|
||||||
inline_macro PypiLinkInlineMacro
|
|
||||||
inline_macro CratesIOLinkInlineMacro
|
|
||||||
|
|
||||||
# App stores
|
|
||||||
inline_macro FDroidLinkInlineMacro
|
|
||||||
inline_macro FlathubLinkInlineMacro
|
|
||||||
|
|
||||||
# Databases
|
|
||||||
inline_macro MusicBrainzLinkInlineMacro
|
|
||||||
inline_macro RepologyLinkInlineMacro
|
|
||||||
end
|
|
63
lib/asciidoctor/foodogsquared/chat-block/extension.rb
Normal file
63
lib/asciidoctor/foodogsquared/chat-block/extension.rb
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class ChatBlock < Asciidoctor::Extensions::BlockProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :chat
|
||||||
|
on_context :example
|
||||||
|
name_positional_attributes 'avatar', 'state'
|
||||||
|
default_attributes 'state' => 'default'
|
||||||
|
|
||||||
|
def process(parent, reader, attrs)
|
||||||
|
# You can think of this section as a pipeline constructing the HTML
|
||||||
|
# component for this block. Specifically, we're building one component that
|
||||||
|
# contains two output: the dialog image of our avatar and its content.
|
||||||
|
attrs['name'] ||= attrs['avatar']
|
||||||
|
|
||||||
|
block = create_block parent, :pass, nil, attrs, content_model: :compound
|
||||||
|
block.add_role('dialogblock')
|
||||||
|
|
||||||
|
block << (create_html_fragment block, <<~HTML
|
||||||
|
<div role="figure" class="dialogblock dialogblock__box dialogblock__avatar--#{attrs['avatar']} #{attrs['role']}">
|
||||||
|
<div class="dialogblock dialogblock__avatar">
|
||||||
|
HTML
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
attrs['avatarsdir'] ||= File.expand_path('./avatars', attrs['iconsdir'])
|
||||||
|
attrs['avatarstype'] ||= parent.attributes['avatarstype'] || 'avif'
|
||||||
|
|
||||||
|
avatar_sticker = "#{attrs['avatar'].to_kebab}/#{attrs['state'].to_kebab}.#{attrs['avatarstype']}"
|
||||||
|
avatar_img_attrs = {
|
||||||
|
'target' => parent.image_uri(avatar_sticker, 'avatarsdir'),
|
||||||
|
'alt' => attrs['name']
|
||||||
|
}
|
||||||
|
avatar_imgblock = create_image_block block, avatar_img_attrs
|
||||||
|
|
||||||
|
block << avatar_imgblock
|
||||||
|
block << (create_html_fragment block, <<~HTML
|
||||||
|
</div>
|
||||||
|
<div class="dialogblock dialogblock__text">
|
||||||
|
<small class="dialogblock dialogblock__avatar-name">#{attrs['name']}</small>
|
||||||
|
HTML
|
||||||
|
)
|
||||||
|
|
||||||
|
parse_content block, reader
|
||||||
|
|
||||||
|
block << (create_html_fragment block, <<~HTML
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
HTML
|
||||||
|
)
|
||||||
|
|
||||||
|
block
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_html_fragment(parent, html, attributes = nil)
|
||||||
|
create_block parent, :pass, html, attributes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
57
lib/asciidoctor/foodogsquared/extensions.rb
Normal file
57
lib/asciidoctor/foodogsquared/extensions.rb
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'asciidoctor'
|
||||||
|
require 'asciidoctor/extensions'
|
||||||
|
|
||||||
|
require_relative 'helpers'
|
||||||
|
|
||||||
|
require_relative 'man-inline-macro/extension'
|
||||||
|
require_relative 'swhid-inline-macro/extension'
|
||||||
|
require_relative 'swhid-include-processor/extension'
|
||||||
|
require_relative 'github-inline-macro/extension'
|
||||||
|
require_relative 'github-include-processor/extension'
|
||||||
|
require_relative 'gitlab-inline-macro/extension'
|
||||||
|
require_relative 'gitlab-include-processor/extension'
|
||||||
|
require_relative 'chat-block/extension'
|
||||||
|
require_relative 'git-blob-include-processor/extension'
|
||||||
|
require_relative 'wikipedia-inline-macro/extension'
|
||||||
|
require_relative 'package-indices-macro/extension'
|
||||||
|
require_relative 'fdroid-inline-macro/extension'
|
||||||
|
require_relative 'musicbrainz-inline-macro/extension'
|
||||||
|
require_relative 'flathub-inline-macro/extension'
|
||||||
|
require_relative 'repology-inline-macro/extension'
|
||||||
|
require_relative 'ietf-rfc-inline-macro/extension'
|
||||||
|
|
||||||
|
include Asciidoctor::Foodogsquared::Extensions
|
||||||
|
Asciidoctor::Extensions.register do
|
||||||
|
|
||||||
|
inline_macro ManInlineMacro
|
||||||
|
inline_macro IETFRFCInlineMacro
|
||||||
|
block ChatBlock if @document.basebackend? 'html'
|
||||||
|
|
||||||
|
inline_macro SWHInlineMacro
|
||||||
|
include_processor SWHIncludeProcessor
|
||||||
|
|
||||||
|
inline_macro GitHubInlineMacro
|
||||||
|
include_processor GitHubIncludeProcessor
|
||||||
|
|
||||||
|
inline_macro GitLabInlineMacro
|
||||||
|
include_processor GitLabIncludeProcessor
|
||||||
|
|
||||||
|
include_processor GitBlobIncludeProcessor
|
||||||
|
|
||||||
|
inline_macro WikipediaInlineMacro
|
||||||
|
|
||||||
|
# Package indices
|
||||||
|
inline_macro CtanInlineMacro
|
||||||
|
inline_macro PypiInlineMacro
|
||||||
|
inline_macro CratesIOInlineMacro
|
||||||
|
|
||||||
|
# App stores
|
||||||
|
inline_macro FDroidInlineMacro
|
||||||
|
inline_macro FlathubInlineMacro
|
||||||
|
|
||||||
|
# Databases
|
||||||
|
inline_macro MusicBrainzInlineMacro
|
||||||
|
inline_macro RepologyInlineMacro
|
||||||
|
end
|
@ -0,0 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'open-uri'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class FDroidInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :fdroid
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
default_attributes 'lang' => 'en'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
|
||||||
|
app_id = target
|
||||||
|
app_metadata_uri = %(https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/#{app_id}.yml)
|
||||||
|
|
||||||
|
metadata = OpenURI.open_uri(app_metadata_uri) { |f| YAML.safe_load(f.read) }
|
||||||
|
attrs['caption'] ||= metadata['AutoName']
|
||||||
|
|
||||||
|
url = %(https://f-droid.org/#{attrs['lang']}/packages/#{app_id})
|
||||||
|
doc.register :links, url
|
||||||
|
create_anchor parent, attrs['caption'], type: :link, target: url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,35 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require 'open-uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class FlathubInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :flathub
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
|
||||||
|
# FlatHub API seems to have no documentation aside from the source code.
|
||||||
|
# You can easily infer the API with its source code at
|
||||||
|
# https://github.com/flathub/website.
|
||||||
|
app_id = target
|
||||||
|
app_metadata_uri = %(https://flathub.org/api/v2/appstream/#{app_id})
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'User-Agent' => ::Asciidoctor::Foodogsquared::USER_AGENT
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata = OpenURI.open_uri(app_metadata_uri, headers) { |f| JSON.parse(f.read) }
|
||||||
|
attrs['caption'] ||= metadata['name']
|
||||||
|
|
||||||
|
url = %(https://flathub.org/apps/#{app_id})
|
||||||
|
doc.register :links, url
|
||||||
|
create_anchor parent, attrs['caption'], type: :link, target: url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,68 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rugged'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class GitBlobIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
||||||
|
def handles?(target)
|
||||||
|
target.start_with? 'git:'
|
||||||
|
end
|
||||||
|
|
||||||
|
def process(doc, reader, target, attrs)
|
||||||
|
attrs['gitrepo'] ||= doc.attributes['gitrepo'] || doc.base_dir
|
||||||
|
repo = Rugged::Repository.discover(attrs['gitrepo'])
|
||||||
|
|
||||||
|
git_object_ref = target.delete_prefix 'git:'
|
||||||
|
git_object_ref = doc.attributes['doccontentref'] if git_object_ref.empty?
|
||||||
|
|
||||||
|
begin
|
||||||
|
git_object = repo.rev_parse git_object_ref
|
||||||
|
|
||||||
|
if attrs.key? 'diff-option'
|
||||||
|
options = {}
|
||||||
|
|
||||||
|
options[:paths] = attrs['path'].split(';') if attrs.key? 'path'
|
||||||
|
options[:context_lines] = attrs['context-lines'] if attrs.key? 'context-lines'
|
||||||
|
options[:reverse] = true if attrs.key? 'reverse-option'
|
||||||
|
|
||||||
|
if attrs.key? 'other'
|
||||||
|
other = repo.rev_parse attrs['other'] || nil
|
||||||
|
reader.push_include git_object.diff(other, **options).patch
|
||||||
|
else
|
||||||
|
reader.push_include git_object.diff(**options).patch
|
||||||
|
end
|
||||||
|
else
|
||||||
|
inner_entry = case git_object.type
|
||||||
|
when :blob
|
||||||
|
git_object
|
||||||
|
when :commit
|
||||||
|
git_object.tree.path attrs['path']
|
||||||
|
when :tree
|
||||||
|
git_object.path attrs['path']
|
||||||
|
when :tag
|
||||||
|
git_object.target.tree.path attrs['path']
|
||||||
|
end
|
||||||
|
|
||||||
|
content = repo.lookup(inner_entry[:oid]).content
|
||||||
|
|
||||||
|
if attrs.key? 'lines'
|
||||||
|
content_lines = content.lines
|
||||||
|
new_content = +''
|
||||||
|
doc.resolve_lines_to_highlight(content, attrs['lines']).each do |line_no|
|
||||||
|
new_content << content_lines.at(line_no - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
content = new_content
|
||||||
|
end
|
||||||
|
|
||||||
|
reader.push_include content
|
||||||
|
end
|
||||||
|
rescue StandardError => e
|
||||||
|
reader.push_include "Unresolved directive for '#{target}' with the following error:\n#{e}"
|
||||||
|
warn e
|
||||||
|
end
|
||||||
|
|
||||||
|
reader
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,70 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'base64'
|
||||||
|
require 'json'
|
||||||
|
require 'open-uri'
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class GitHubIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
||||||
|
def handles?(target)
|
||||||
|
target.start_with? 'github:'
|
||||||
|
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('github:').split('/', 3)
|
||||||
|
owner = src.at 0
|
||||||
|
repo = src.at 1
|
||||||
|
namespaced_repo = "#{owner}/#{repo}"
|
||||||
|
|
||||||
|
path = attrs['path'] || ''
|
||||||
|
|
||||||
|
# For more information, see https://docs.github.com/en/rest/repos/contents.
|
||||||
|
uri = URI.parse %(https://api.github.com/repos/#{owner}/#{repo}/contents/#{path})
|
||||||
|
|
||||||
|
if attrs['rev']
|
||||||
|
query = { ref: attrs['rev'] }
|
||||||
|
uri.query = URI.encode_www_form query
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
headers = {
|
||||||
|
'Header' => 'application/vnd.github+json',
|
||||||
|
'X-GitHub-Api-Version' => '2022-11-28'
|
||||||
|
}
|
||||||
|
|
||||||
|
headers['Authorization'] = "Token #{ENV['GITHUB_API_BEARER_TOKEN']}" if ENV['GITHUB_API_BEARER_TOKEN']
|
||||||
|
|
||||||
|
OpenURI.open_uri(uri, headers) do |f|
|
||||||
|
response = JSON.parse(f.read)
|
||||||
|
|
||||||
|
# If the response is an array, it is likely to be a directory. In this
|
||||||
|
# usecase, we'll just list them.
|
||||||
|
content = if response.is_a? Array
|
||||||
|
warning = %(given path '#{path}' from GitHub repo '#{repo}' is a directory)
|
||||||
|
warn_or_raise doc, warning
|
||||||
|
warning
|
||||||
|
elsif response.is_a? Object
|
||||||
|
Base64.decode64 response['content'] if response['content'] && response['encoding'] == 'base64'
|
||||||
|
end
|
||||||
|
|
||||||
|
reader.push_include content, target, target, 1, attrs
|
||||||
|
end
|
||||||
|
rescue OpenURI::HTTPError => e
|
||||||
|
warning = %(error while getting '#{path}' in GitHub repo '#{namespaced_repo}: #{e}')
|
||||||
|
warn_or_raise doc, warning
|
||||||
|
reader.push_include warning, target, target, 1, attrs
|
||||||
|
end
|
||||||
|
|
||||||
|
reader
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,38 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class GitHubInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :github
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
|
||||||
|
default_caption = if attrs.key?('repo-option')
|
||||||
|
target.split('/').at(1)
|
||||||
|
else
|
||||||
|
target
|
||||||
|
end
|
||||||
|
text = attrs['caption'] || default_caption
|
||||||
|
uri = URI.parse %(https://github.com/#{target})
|
||||||
|
|
||||||
|
if attrs.key? 'issue'
|
||||||
|
uri.path += %(/issues/#{attrs['issue']})
|
||||||
|
text << "##{attrs['issue']}" if text == target
|
||||||
|
else
|
||||||
|
uri.path += %(/tree/#{attrs['rev']}) if attrs.key? 'rev'
|
||||||
|
uri.path += %(/#{attrs['path']}) if attrs.key? 'path'
|
||||||
|
text << "@#{attrs['rev']}" if attrs.key?('rev') && text == target
|
||||||
|
end
|
||||||
|
|
||||||
|
target = uri.to_s
|
||||||
|
|
||||||
|
doc.register :links, target
|
||||||
|
create_anchor parent, text, type: :link, target: target
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,60 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'base64'
|
||||||
|
require 'json'
|
||||||
|
require 'open-uri'
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class GitLabIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
||||||
|
def handles?(target)
|
||||||
|
target.start_with? 'gitlab:'
|
||||||
|
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
|
||||||
|
end
|
@ -0,0 +1,39 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class GitLabInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :gitlab
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
default_attributes 'domain' => 'gitlab.com'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
|
||||||
|
default_caption = if attrs.key?('repo-option')
|
||||||
|
target.split('/').at(1)
|
||||||
|
else
|
||||||
|
target
|
||||||
|
end
|
||||||
|
text = attrs['caption'] || default_caption
|
||||||
|
uri = URI.parse %(https://#{attrs['domain']}/#{target})
|
||||||
|
|
||||||
|
if attrs.key? 'issue'
|
||||||
|
uri.path += %(/-/issues/#{attrs['issue']})
|
||||||
|
text << "##{attrs['issue']}" if text == target
|
||||||
|
else
|
||||||
|
uri.path += %(/-/tree/#{attrs['rev']}) if attrs.key? 'rev'
|
||||||
|
uri.path += %(/#{attrs['path']}) if attrs.key? 'path'
|
||||||
|
text << "@#{attrs['rev']}" if attrs.key?('rev') && text == target
|
||||||
|
end
|
||||||
|
|
||||||
|
target = uri.to_s
|
||||||
|
|
||||||
|
doc.register :links, target
|
||||||
|
create_anchor parent, text, type: :link, target: target
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
26
lib/asciidoctor/foodogsquared/helpers.rb
Normal file
26
lib/asciidoctor/foodogsquared/helpers.rb
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class String
|
||||||
|
def to_kebab
|
||||||
|
self.gsub(/\s+/, '-') # Replace all spaces with dashes.
|
||||||
|
.gsub(/[^a-zA-Z0-9-]/, '') # Remove all non-alphanumerical (and dashes) characters.
|
||||||
|
.gsub(/-+/, '-') # Reduce all dashes into only one.
|
||||||
|
.gsub(/^-|-+$/, '') # Remove all leading and trailing dashes.
|
||||||
|
.downcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# The namespace for storing Asciidoctor. This is the entry point for the
|
||||||
|
# entirety of this project.
|
||||||
|
module Asciidoctor::Foodogsquared
|
||||||
|
NAME = 'asciidoctor-foodogsquared-custom-extensions'
|
||||||
|
VERSION = '1.2.0'
|
||||||
|
CONTACT_EMAIL = 'foodogsquared@foodogsquared.one'
|
||||||
|
USER_AGENT = "#{NAME}/#{VERSION} ( #{CONTACT_EMAIL} )".freeze
|
||||||
|
|
||||||
|
def warn_or_raise(doc, warning)
|
||||||
|
return raise warning if (doc.safe > Asciidoctor::SafeMode::SERVER) && !(doc.attr? 'allow-uri-read')
|
||||||
|
|
||||||
|
warn warning
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,18 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class IETFRFCInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :rfc
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
url = %(https://datatracker.ietf.org/doc/html/#{target})
|
||||||
|
attrs['caption'] ||= "RFC#{target}"
|
||||||
|
doc.register :links, url
|
||||||
|
create_anchor parent, attrs['caption'], type: :link, target: url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
53
lib/asciidoctor/foodogsquared/man-inline-macro/extension.rb
Normal file
53
lib/asciidoctor/foodogsquared/man-inline-macro/extension.rb
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class ManInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :man
|
||||||
|
name_positional_attributes 'volnum'
|
||||||
|
default_attributes 'service' => 'debian', 'subpath' => ''
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
manname = target
|
||||||
|
|
||||||
|
text = %(#{manname}(#{attrs['volnum']}))
|
||||||
|
|
||||||
|
if doc.basebackend? 'html'
|
||||||
|
domain = case attrs['service']
|
||||||
|
when 'debian'
|
||||||
|
'https://manpages.debian.org'
|
||||||
|
when 'ubuntu'
|
||||||
|
'https://manpages.ubuntu.org'
|
||||||
|
when 'arch'
|
||||||
|
'https://man.archlinux.org/man'
|
||||||
|
when 'opensuse'
|
||||||
|
'https://manpages.opensuse.org'
|
||||||
|
when 'voidlinux'
|
||||||
|
'https://man.voidlinux.org'
|
||||||
|
when 'openbsd'
|
||||||
|
'https://man.openbsd.org'
|
||||||
|
when 'none'
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
raise "no available manpage service #{attrs['service']}"
|
||||||
|
end
|
||||||
|
|
||||||
|
if !domain.nil?
|
||||||
|
target = %(#{domain}/#{attrs['subpath'].delete_prefix '/'}#{manname}.#{attrs['volnum']})
|
||||||
|
doc.register :links, target
|
||||||
|
node = create_anchor parent, text, type: :link, target: target
|
||||||
|
else
|
||||||
|
node = create_inline parent, :quoted, text
|
||||||
|
end
|
||||||
|
elsif doc.backend == 'manpage'
|
||||||
|
node = create_inline parent, :quoted, text, type: :strong
|
||||||
|
else
|
||||||
|
node = create_inline parent, :quoted, text
|
||||||
|
end
|
||||||
|
|
||||||
|
node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,47 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require 'open-uri'
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class MusicBrainzInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :musicbrainz
|
||||||
|
name_positional_attributes 'caption', 'type'
|
||||||
|
default_attributes 'type' => 'release'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
root_endpoint = 'https://musicbrainz.org/ws/2'
|
||||||
|
|
||||||
|
begin
|
||||||
|
headers = {
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'User-Agent' => ::Asciidoctor::Foodogsquared::USER_AGENT
|
||||||
|
}
|
||||||
|
|
||||||
|
uri = %(#{root_endpoint}/#{attrs['type']}/#{target})
|
||||||
|
|
||||||
|
metadata = OpenURI.open_uri(uri, headers) { |f| JSON.parse(f.read) }
|
||||||
|
attrs['caption'] ||= case attrs['type']
|
||||||
|
when 'artist', 'area', 'events', 'genre', 'instrument', 'label', 'place', 'series'
|
||||||
|
metadata['name']
|
||||||
|
when 'recording', 'release-group', 'release', 'cdstub', 'work'
|
||||||
|
metadata['title']
|
||||||
|
when 'url'
|
||||||
|
metadata['resource']
|
||||||
|
end
|
||||||
|
|
||||||
|
target = %(https://musicbrainz.org/#{attrs['type']}/#{target})
|
||||||
|
doc.register :links, target
|
||||||
|
create_anchor parent, attrs['caption'], type: :link, target: target
|
||||||
|
rescue StandardError
|
||||||
|
warning = %(error while getting Musicbrainz database object '#{target}: #{e}')
|
||||||
|
warn_or_raise doc, warning
|
||||||
|
reader.push_include warning, target, target, 1, attrs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,58 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# I'm fairly sure this could be programmed since Ruby has nice metaprogramming
|
||||||
|
# capabilities. Though, we'll be keeping it manually defining classes for now
|
||||||
|
# for initial versions since there could be additional features for each macro.
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class CtanInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :ctan
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
text = attrs['caption'] || target
|
||||||
|
url = %(https://ctan.org/pkg/#{target})
|
||||||
|
|
||||||
|
doc.register :links, url
|
||||||
|
|
||||||
|
create_anchor parent, text, type: :link, target: url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class PypiInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :pypi
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
text = attrs['caption'] || target
|
||||||
|
url = %(https://pypi.org/project/#{target})
|
||||||
|
|
||||||
|
doc.register :links, url
|
||||||
|
|
||||||
|
create_anchor parent, text, type: :link, target: url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class CratesIOInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :cratesio
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
text = attrs['caption'] || target
|
||||||
|
url = %(https://crates.io/crates/#{target})
|
||||||
|
|
||||||
|
doc.register :links, url
|
||||||
|
|
||||||
|
create_anchor parent, text, type: :link, target: url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class RepologyInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :repology
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
text = attrs['caption'] || target
|
||||||
|
url = %(https://repology.org/project/#{target})
|
||||||
|
|
||||||
|
doc.register :links, url
|
||||||
|
|
||||||
|
create_anchor parent, text, type: :link, target: url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
26
lib/asciidoctor/foodogsquared/spdx-inline-macro/README.adoc
Normal file
26
lib/asciidoctor/foodogsquared/spdx-inline-macro/README.adoc
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
= SPDX link inline macro
|
||||||
|
:toc:
|
||||||
|
|
||||||
|
It's an inline macro for easily creating licenses from SPDX license data.
|
||||||
|
|
||||||
|
|
||||||
|
== Synopsis
|
||||||
|
|
||||||
|
[source, asciidoc]
|
||||||
|
----
|
||||||
|
spdx:$LICENSE_ID[$CAPTION]
|
||||||
|
----
|
||||||
|
|
||||||
|
Where...
|
||||||
|
|
||||||
|
* `$LICENSE_ID` is the identifier for the license.
|
||||||
|
|
||||||
|
* `$CAPTION` is the link caption to be used.
|
||||||
|
By default, it will use the name of the license.
|
||||||
|
|
||||||
|
|
||||||
|
== Example usage
|
||||||
|
|
||||||
|
* `spdx:MIT[]` will result to the link:https://spdx.org/licenses/MIT.html[MIT license page on SPDX] with the caption `MIT License`.
|
||||||
|
|
||||||
|
* `spdx:MIT[the MIT license]` is the same as the previous example but with a different caption of `the MIT license`.
|
@ -0,0 +1,55 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require 'open-uri'
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class SWHIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
||||||
|
def handles?(target)
|
||||||
|
target.start_with? 'swh:'
|
||||||
|
end
|
||||||
|
|
||||||
|
def process(doc, reader, target, attributes)
|
||||||
|
swhid = target
|
||||||
|
swhid_core_identifier = swhid.split(';').at(0)
|
||||||
|
swhid_object_type = (swhid_core_identifier.split ':').at 2
|
||||||
|
|
||||||
|
unless (doc.safe <= Asciidoctor::SafeMode::SERVER) && (doc.attr? 'allow-uri-read')
|
||||||
|
raise %('swh:' include cannot be used in safe mode level > SERVER and without attribute 'allow-uri-read')
|
||||||
|
end
|
||||||
|
|
||||||
|
# We're already going to throw out anything that is not content object type
|
||||||
|
# just to make the later pipelines easier to construct.
|
||||||
|
if swhid_object_type != 'cnt'
|
||||||
|
warn %(SWHID '#{swhid_core_identifier}' is not of 'cnt' type; ignoring)
|
||||||
|
return reader
|
||||||
|
end
|
||||||
|
|
||||||
|
version = '1'
|
||||||
|
|
||||||
|
content = begin
|
||||||
|
uri = URI.parse %(https://archive.softwareheritage.org/api/#{version}/resolve/#{target}/)
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Accept' => 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
headers['Authorization'] = "Bearer #{ENV['SWH_API_BEARER_TOKEN']}" if ENV['SWH_API_BEARER_TOKEN']
|
||||||
|
|
||||||
|
metadata = OpenURI.open_uri(uri, headers) { |f| JSON.parse(f.read) }
|
||||||
|
object_hash = metadata['object_id']
|
||||||
|
|
||||||
|
uri = URI.parse %(https://archive.softwareheritage.org/api/#{version}/content/sha1_git:#{object_hash}/raw/)
|
||||||
|
OpenURI.open_uri(uri, headers, &:read)
|
||||||
|
rescue OpenURI::HTTPError => e
|
||||||
|
warning = %(error while getting '#{swhid_core_identifier}': #{e})
|
||||||
|
warn warning
|
||||||
|
warning
|
||||||
|
end
|
||||||
|
|
||||||
|
reader.push_include content, target, target, 1, attributes
|
||||||
|
reader
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class SWHInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :swh
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
doc = parent.document
|
||||||
|
|
||||||
|
# We're only considering `swh:` starting with the scheme version. Also, it
|
||||||
|
# looks nice aesthetically.
|
||||||
|
swhid = target.start_with?('swh:') ? target : %(swh:#{target})
|
||||||
|
default_caption = if attrs.key? 'full-option'
|
||||||
|
swhid
|
||||||
|
else
|
||||||
|
swhid.split(';').at(0)
|
||||||
|
end
|
||||||
|
text = attrs['caption'] || default_caption
|
||||||
|
target = %(https://archive.softwareheritage.org/#{swhid})
|
||||||
|
|
||||||
|
doc.register :links, target
|
||||||
|
create_anchor parent, text, type: :link, target: target
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,23 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
|
module Asciidoctor::Foodogsquared::Extensions
|
||||||
|
class WikipediaInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
||||||
|
use_dsl
|
||||||
|
|
||||||
|
named :wikipedia
|
||||||
|
name_positional_attributes 'caption'
|
||||||
|
default_attributes 'lang' => 'en'
|
||||||
|
|
||||||
|
def process(parent, target, attrs)
|
||||||
|
caption = attrs['caption'] || target
|
||||||
|
parser = URI::Parser.new
|
||||||
|
page = parser.escape target
|
||||||
|
link = %(https://#{attrs['lang']}.wikipedia.org/wiki/#{page})
|
||||||
|
node = create_anchor parent, caption, type: :link, target: link
|
||||||
|
|
||||||
|
create_inline parent, :quoted, node.convert
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,66 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rugged'
|
|
||||||
|
|
||||||
class GitBlobIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
|
||||||
def handles?(target)
|
|
||||||
target.start_with? 'git:'
|
|
||||||
end
|
|
||||||
|
|
||||||
def process(doc, reader, target, attrs)
|
|
||||||
attrs['gitrepo'] ||= doc.attributes['gitrepo'] || doc.base_dir
|
|
||||||
repo = Rugged::Repository.discover(attrs['gitrepo'])
|
|
||||||
|
|
||||||
git_object_ref = target.delete_prefix 'git:'
|
|
||||||
git_object_ref = doc.attributes['doccontentref'] if git_object_ref.empty?
|
|
||||||
|
|
||||||
begin
|
|
||||||
git_object = repo.rev_parse git_object_ref
|
|
||||||
|
|
||||||
if attrs.key? 'diff-option'
|
|
||||||
options = {}
|
|
||||||
|
|
||||||
options[:paths] = attrs['path'].split(';') if attrs.key? 'path'
|
|
||||||
options[:context_lines] = attrs['context-lines'] if attrs.key? 'context-lines'
|
|
||||||
options[:reverse] = true if attrs.key? 'reverse-option'
|
|
||||||
|
|
||||||
if attrs.key? 'other'
|
|
||||||
other = repo.rev_parse attrs['other'] || nil
|
|
||||||
reader.push_include git_object.diff(other, **options).patch
|
|
||||||
else
|
|
||||||
reader.push_include git_object.diff(**options).patch
|
|
||||||
end
|
|
||||||
else
|
|
||||||
inner_entry = case git_object.type
|
|
||||||
when :blob
|
|
||||||
git_object
|
|
||||||
when :commit
|
|
||||||
git_object.tree.path attrs['path']
|
|
||||||
when :tree
|
|
||||||
git_object.path attrs['path']
|
|
||||||
when :tag
|
|
||||||
git_object.target.tree.path attrs['path']
|
|
||||||
end
|
|
||||||
|
|
||||||
content = repo.lookup(inner_entry[:oid]).content
|
|
||||||
|
|
||||||
if attrs.key? 'lines'
|
|
||||||
content_lines = content.lines
|
|
||||||
new_content = +''
|
|
||||||
doc.resolve_lines_to_highlight(content, attrs['lines']).each do |line_no|
|
|
||||||
new_content << content_lines.at(line_no - 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
content = new_content
|
|
||||||
end
|
|
||||||
|
|
||||||
reader.push_include content
|
|
||||||
end
|
|
||||||
rescue StandardError => e
|
|
||||||
reader.push_include "Unresolved directive for '#{target}' with the following error:\n#{e}"
|
|
||||||
warn e
|
|
||||||
end
|
|
||||||
|
|
||||||
reader
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,36 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'uri'
|
|
||||||
|
|
||||||
class GitHubLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :github
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
|
|
||||||
default_caption = if attrs.key?('repo-option')
|
|
||||||
target.split('/').at(1)
|
|
||||||
else
|
|
||||||
target
|
|
||||||
end
|
|
||||||
text = attrs['caption'] || default_caption
|
|
||||||
uri = URI.parse %(https://github.com/#{target})
|
|
||||||
|
|
||||||
if attrs.key? 'issue'
|
|
||||||
uri.path += %(/issues/#{attrs['issue']})
|
|
||||||
text << "##{attrs['issue']}" if text == target
|
|
||||||
else
|
|
||||||
uri.path += %(/tree/#{attrs['rev']}) if attrs.key? 'rev'
|
|
||||||
uri.path += %(/#{attrs['path']}) if attrs.key? 'path'
|
|
||||||
text << "@#{attrs['rev']}" if attrs.key?('rev') && text == target
|
|
||||||
end
|
|
||||||
|
|
||||||
target = uri.to_s
|
|
||||||
|
|
||||||
doc.register :links, target
|
|
||||||
create_anchor parent, text, type: :link, target: target
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,68 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'base64'
|
|
||||||
require 'json'
|
|
||||||
require 'open-uri'
|
|
||||||
require 'uri'
|
|
||||||
|
|
||||||
class GitHubRawIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
|
||||||
def handles?(target)
|
|
||||||
target.start_with? 'github:'
|
|
||||||
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('github:').split('/', 3)
|
|
||||||
owner = src.at 0
|
|
||||||
repo = src.at 1
|
|
||||||
namespaced_repo = "#{owner}/#{repo}"
|
|
||||||
|
|
||||||
path = attrs['path'] || ''
|
|
||||||
|
|
||||||
# For more information, see https://docs.github.com/en/rest/repos/contents.
|
|
||||||
uri = URI.parse %(https://api.github.com/repos/#{owner}/#{repo}/contents/#{path})
|
|
||||||
|
|
||||||
if attrs['rev']
|
|
||||||
query = { ref: attrs['rev'] }
|
|
||||||
uri.query = URI.encode_www_form query
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
headers = {
|
|
||||||
'Header' => 'application/vnd.github+json',
|
|
||||||
'X-GitHub-Api-Version' => '2022-11-28'
|
|
||||||
}
|
|
||||||
|
|
||||||
headers['Authorization'] = "Token #{ENV['GITHUB_API_BEARER_TOKEN']}" if ENV['GITHUB_API_BEARER_TOKEN']
|
|
||||||
|
|
||||||
OpenURI.open_uri(uri, headers) do |f|
|
|
||||||
response = JSON.parse(f.read)
|
|
||||||
|
|
||||||
# If the response is an array, it is likely to be a directory. In this
|
|
||||||
# usecase, we'll just list them.
|
|
||||||
content = if response.is_a? Array
|
|
||||||
warning = %(given path '#{path}' from GitHub repo '#{repo}' is a directory)
|
|
||||||
warn_or_raise doc, warning
|
|
||||||
warning
|
|
||||||
elsif response.is_a? Object
|
|
||||||
Base64.decode64 response['content'] if response['content'] && response['encoding'] == 'base64'
|
|
||||||
end
|
|
||||||
|
|
||||||
reader.push_include content, target, target, 1, attrs
|
|
||||||
end
|
|
||||||
rescue OpenURI::HTTPError => e
|
|
||||||
warning = %(error while getting '#{path}' in GitHub repo '#{namespaced_repo}: #{e}')
|
|
||||||
warn_or_raise doc, warning
|
|
||||||
reader.push_include warning, target, target, 1, attrs
|
|
||||||
end
|
|
||||||
|
|
||||||
reader
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,37 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'uri'
|
|
||||||
|
|
||||||
class GitLabLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :gitlab
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
default_attributes 'domain' => 'gitlab.com'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
|
|
||||||
default_caption = if attrs.key?('repo-option')
|
|
||||||
target.split('/').at(1)
|
|
||||||
else
|
|
||||||
target
|
|
||||||
end
|
|
||||||
text = attrs['caption'] || default_caption
|
|
||||||
uri = URI.parse %(https://#{attrs['domain']}/#{target})
|
|
||||||
|
|
||||||
if attrs.key? 'issue'
|
|
||||||
uri.path += %(/-/issues/#{attrs['issue']})
|
|
||||||
text << "##{attrs['issue']}" if text == target
|
|
||||||
else
|
|
||||||
uri.path += %(/-/tree/#{attrs['rev']}) if attrs.key? 'rev'
|
|
||||||
uri.path += %(/#{attrs['path']}) if attrs.key? 'path'
|
|
||||||
text << "@#{attrs['rev']}" if attrs.key?('rev') && text == target
|
|
||||||
end
|
|
||||||
|
|
||||||
target = uri.to_s
|
|
||||||
|
|
||||||
doc.register :links, target
|
|
||||||
create_anchor parent, text, type: :link, target: target
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,66 +0,0 @@
|
|||||||
# 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
|
|
@ -1,20 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class String
|
|
||||||
def to_kebab
|
|
||||||
self.gsub(/\s+/, '-') # Replace all spaces with dashes.
|
|
||||||
.gsub(/[^a-zA-Z0-9-]/, '') # Remove all non-alphanumerical (and dashes) characters.
|
|
||||||
.gsub(/-+/, '-') # Reduce all dashes into only one.
|
|
||||||
.gsub(/^-|-+$/, '') # Remove all leading and trailing dashes.
|
|
||||||
.downcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module Asciidoctor
|
|
||||||
module FoodogsquaredCustomExtensions
|
|
||||||
NAME = 'asciidoctor-foodogsquared-custom-extensions'
|
|
||||||
VERSION = '1.0.0'
|
|
||||||
CONTACT_EMAIL = 'foodogsquared@foodogsquared.one'
|
|
||||||
USER_AGENT = "#{NAME}/#{VERSION} ( #{CONTACT_EMAIL} )"
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,16 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class IETFRFCLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :rfc
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
url = %(https://datatracker.ietf.org/doc/html/#{target})
|
|
||||||
attrs['caption'] ||= "RFC#{target}"
|
|
||||||
doc.register :links, url
|
|
||||||
create_anchor parent, attrs['caption'], type: :link, target: url
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,51 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class ManInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :man
|
|
||||||
name_positional_attributes 'volnum'
|
|
||||||
default_attributes 'service' => 'debian', 'subpath' => ''
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
manname = target
|
|
||||||
|
|
||||||
text = %(#{manname}(#{attrs['volnum']}))
|
|
||||||
|
|
||||||
if doc.basebackend? 'html'
|
|
||||||
domain = case attrs['service']
|
|
||||||
when 'debian'
|
|
||||||
'https://manpages.debian.org'
|
|
||||||
when 'ubuntu'
|
|
||||||
'https://manpages.ubuntu.org'
|
|
||||||
when 'arch'
|
|
||||||
'https://man.archlinux.org/man'
|
|
||||||
when 'opensuse'
|
|
||||||
'https://manpages.opensuse.org'
|
|
||||||
when 'voidlinux'
|
|
||||||
'https://man.voidlinux.org'
|
|
||||||
when 'openbsd'
|
|
||||||
'https://man.openbsd.org'
|
|
||||||
when 'none'
|
|
||||||
nil
|
|
||||||
else
|
|
||||||
raise "no available manpage service #{attrs['service']}"
|
|
||||||
end
|
|
||||||
|
|
||||||
if !domain.nil?
|
|
||||||
target = %(#{domain}/#{attrs['subpath'].delete_prefix '/'}#{manname}.#{attrs['volnum']})
|
|
||||||
doc.register :links, target
|
|
||||||
node = create_anchor parent, text, type: :link, target: target
|
|
||||||
else
|
|
||||||
node = create_inline parent, :quoted, text
|
|
||||||
end
|
|
||||||
elsif doc.backend == 'manpage'
|
|
||||||
node = create_inline parent, :quoted, text, type: :strong
|
|
||||||
else
|
|
||||||
node = create_inline parent, :quoted, text
|
|
||||||
end
|
|
||||||
|
|
||||||
node
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,45 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'json'
|
|
||||||
require 'open-uri'
|
|
||||||
require 'uri'
|
|
||||||
|
|
||||||
class MusicBrainzLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :musicbrainz
|
|
||||||
name_positional_attributes 'caption', 'type'
|
|
||||||
default_attributes 'type' => 'release'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
root_endpoint = 'https://musicbrainz.org/ws/2'
|
|
||||||
|
|
||||||
begin
|
|
||||||
headers = {
|
|
||||||
'Accept' => 'application/json',
|
|
||||||
'User-Agent' => ::Asciidoctor::FoodogsquaredCustomExtensions::USER_AGENT
|
|
||||||
}
|
|
||||||
|
|
||||||
uri = %(#{root_endpoint}/#{attrs['type']}/#{target})
|
|
||||||
|
|
||||||
metadata = OpenURI.open_uri(uri, headers) { |f| JSON.parse(f.read) }
|
|
||||||
attrs['caption'] ||= case attrs['type']
|
|
||||||
when 'artist', 'area', 'events', 'genre', 'instrument', 'label', 'place', 'series'
|
|
||||||
metadata['name']
|
|
||||||
when 'recording', 'release-group', 'release', 'cdstub', 'work'
|
|
||||||
metadata['title']
|
|
||||||
when 'url'
|
|
||||||
metadata['resource']
|
|
||||||
end
|
|
||||||
|
|
||||||
target = %(https://musicbrainz.org/#{attrs['type']}/#{target})
|
|
||||||
doc.register :links, target
|
|
||||||
create_anchor parent, attrs['caption'], type: :link, target: target
|
|
||||||
rescue
|
|
||||||
warning = %(error while getting Musicbrainz database object '#{target}: #{e}')
|
|
||||||
warn_or_raise doc, warning
|
|
||||||
reader.push_include warning, target, target, 1, attrs
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,56 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# I'm fairly sure this could be programmed since Ruby has nice metaprogramming
|
|
||||||
# capabilities. Though, we'll be keeping it manually defining classes for now
|
|
||||||
# for initial versions since there could be additional features for each macro.
|
|
||||||
|
|
||||||
class CtanLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :ctan
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
text = attrs['caption'] || target
|
|
||||||
url = %(https://ctan.org/pkg/#{target})
|
|
||||||
|
|
||||||
doc.register :links, url
|
|
||||||
|
|
||||||
create_anchor parent, text, type: :link, target: url
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class PypiLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :pypi
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
text = attrs['caption'] || target
|
|
||||||
url = %(https://pypi.org/project/#{target})
|
|
||||||
|
|
||||||
doc.register :links, url
|
|
||||||
|
|
||||||
create_anchor parent, text, type: :link, target: url
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class CratesIOLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :cratesio
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
text = attrs['caption'] || target
|
|
||||||
url = %(https://crates.io/crates/#{target})
|
|
||||||
|
|
||||||
doc.register :links, url
|
|
||||||
|
|
||||||
create_anchor parent, text, type: :link, target: url
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,18 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class RepologyLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :repology
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
text = attrs['caption'] || target
|
|
||||||
url = %(https://repology.org/project/#{target})
|
|
||||||
|
|
||||||
doc.register :links, url
|
|
||||||
|
|
||||||
create_anchor parent, text, type: :link, target: url
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,53 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'json'
|
|
||||||
require 'open-uri'
|
|
||||||
require 'uri'
|
|
||||||
|
|
||||||
class SWHIDIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
|
||||||
def handles?(target)
|
|
||||||
target.start_with? 'swh:'
|
|
||||||
end
|
|
||||||
|
|
||||||
def process(doc, reader, target, attributes)
|
|
||||||
swhid = target
|
|
||||||
swhid_core_identifier = swhid.split(';').at(0)
|
|
||||||
swhid_object_type = (swhid_core_identifier.split ':').at 2
|
|
||||||
|
|
||||||
unless (doc.safe <= Asciidoctor::SafeMode::SERVER) && (doc.attr? 'allow-uri-read')
|
|
||||||
raise %('swh:' include cannot be used in safe mode level > SERVER and without attribute 'allow-uri-read')
|
|
||||||
end
|
|
||||||
|
|
||||||
# We're already going to throw out anything that is not content object type
|
|
||||||
# just to make the later pipelines easier to construct.
|
|
||||||
if swhid_object_type != 'cnt'
|
|
||||||
warn %(SWHID '#{swhid_core_identifier}' is not of 'cnt' type; ignoring)
|
|
||||||
return reader
|
|
||||||
end
|
|
||||||
|
|
||||||
version = '1'
|
|
||||||
|
|
||||||
content = begin
|
|
||||||
uri = URI.parse %(https://archive.softwareheritage.org/api/#{version}/resolve/#{target}/)
|
|
||||||
|
|
||||||
headers = {
|
|
||||||
'Accept' => 'application/json'
|
|
||||||
}
|
|
||||||
|
|
||||||
headers['Authorization'] = "Bearer #{ENV['SWH_API_BEARER_TOKEN']}" if ENV['SWH_API_BEARER_TOKEN']
|
|
||||||
|
|
||||||
metadata = OpenURI.open_uri(uri, headers) { |f| JSON.parse(f.read) }
|
|
||||||
object_hash = metadata['object_id']
|
|
||||||
|
|
||||||
uri = URI.parse %(https://archive.softwareheritage.org/api/#{version}/content/sha1_git:#{object_hash}/raw/)
|
|
||||||
OpenURI.open_uri(uri, headers, &:read)
|
|
||||||
rescue OpenURI::HTTPError => e
|
|
||||||
warning = %(error while getting '#{swhid_core_identifier}': #{e})
|
|
||||||
warn warning
|
|
||||||
warning
|
|
||||||
end
|
|
||||||
|
|
||||||
reader.push_include content, target, target, 1, attributes
|
|
||||||
reader
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,26 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class SWHInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :swh
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
doc = parent.document
|
|
||||||
|
|
||||||
# We're only considering `swh:` starting with the scheme version. Also, it
|
|
||||||
# looks nice aesthetically.
|
|
||||||
swhid = target.start_with?('swh:') ? target : %(swh:#{target})
|
|
||||||
default_caption = if attrs.key? 'full-option'
|
|
||||||
swhid
|
|
||||||
else
|
|
||||||
swhid.split(';').at(0)
|
|
||||||
end
|
|
||||||
text = attrs['caption'] || default_caption
|
|
||||||
target = %(https://archive.softwareheritage.org/#{swhid})
|
|
||||||
|
|
||||||
doc.register :links, target
|
|
||||||
create_anchor parent, text, type: :link, target: target
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,21 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'uri'
|
|
||||||
|
|
||||||
class WikipediaInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
|
||||||
use_dsl
|
|
||||||
|
|
||||||
named :wikipedia
|
|
||||||
name_positional_attributes 'caption'
|
|
||||||
default_attributes 'lang' => 'en'
|
|
||||||
|
|
||||||
def process(parent, target, attrs)
|
|
||||||
caption = attrs['caption'] || target
|
|
||||||
parser = URI::Parser.new
|
|
||||||
page = parser.escape target
|
|
||||||
link = %(https://#{attrs['lang']}.wikipedia.org/wiki/#{page})
|
|
||||||
node = create_anchor parent, caption, type: :link, target: link
|
|
||||||
|
|
||||||
create_inline parent, :quoted, node.convert
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe FDroidLinkInlineMacro do
|
describe FDroidInlineMacro do
|
||||||
it 'should create a FDroid link' do
|
it 'should create a FDroid link' do
|
||||||
input = 'fdroid:org.moire.ultrasonic[]'
|
input = 'fdroid:org.moire.ultrasonic[]'
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe FlathubLinkInlineMacro do
|
describe FlathubInlineMacro do
|
||||||
it 'should create a Flathub link to Icon Library app' do
|
it 'should create a Flathub link to Icon Library app' do
|
||||||
input = 'flathub:org.gnome.design.IconLibrary[]'
|
input = 'flathub:org.gnome.design.IconLibrary[]'
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe GitHubLinkInlineMacro do
|
describe GitHubInlineMacro do
|
||||||
it 'should create a GitHub link with the caption being the target' do
|
it 'should create a GitHub link with the caption being the target' do
|
||||||
input = <<~INPUT
|
input = <<~INPUT
|
||||||
github:foo-dogsquared/foobarbazxyz[]
|
github:foo-dogsquared/foobarbazxyz[]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe GitHubRawIncludeProcessor do
|
describe GitHubIncludeProcessor do
|
||||||
it 'should include the raw content of a GitHub file successfully' do
|
it 'should include the raw content of a GitHub file successfully' do
|
||||||
input = <<~INPUT
|
input = <<~INPUT
|
||||||
[literal]
|
[literal]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe GitLabLinkInlineMacro do
|
describe GitLabInlineMacro do
|
||||||
it 'should link to the GitLab page for GitLab project' do
|
it 'should link to the GitLab page for GitLab project' do
|
||||||
input = 'gitlab:gitlab-org/gitlab[]'
|
input = 'gitlab:gitlab-org/gitlab[]'
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe GitLabRawIncludeProcessor, if: ENV['GITLAB_API_PERSONAL_ACCESS_TOKEN'] do
|
describe GitLabIncludeProcessor, if: ENV['GITLAB_API_PERSONAL_ACCESS_TOKEN'] do
|
||||||
it 'should include the GitLab CI configuration from freedesktop-sdk/freedesktop-sdk from the default instance' do
|
it 'should include the GitLab CI configuration from freedesktop-sdk/freedesktop-sdk from the default instance' do
|
||||||
commit = 'bcb3e0de957519e87a4c7b8c0e40af9876e531e7'
|
commit = 'bcb3e0de957519e87a4c7b8c0e40af9876e531e7'
|
||||||
input = <<~INPUT
|
input = <<~INPUT
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe MusicBrainzLinkInlineMacro do
|
describe MusicBrainzInlineMacro do
|
||||||
it 'should create a MusicBrainz release object with the right captions' do
|
it 'should create a MusicBrainz release object with the right captions' do
|
||||||
input = 'musicbrainz:9adcff14-7dba-4ccf-a6a6-298bcde3dd46[]'
|
input = 'musicbrainz:9adcff14-7dba-4ccf-a6a6-298bcde3dd46[]'
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe RepologyLinkInlineMacro do
|
describe RepologyInlineMacro do
|
||||||
it 'should link to the Repology page for beets' do
|
it 'should link to the Repology page for beets' do
|
||||||
input = 'repology:beets[]'
|
input = 'repology:beets[]'
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'asciidoctor'
|
require 'asciidoctor'
|
||||||
require 'asciidoctor/foodogsquared-extensions'
|
require 'asciidoctor-foodogsquared-extensions'
|
||||||
|
|
||||||
|
include Asciidoctor::Foodogsquared::Extensions
|
||||||
RSpec.configure do
|
RSpec.configure do
|
||||||
def fixtures_dir
|
def fixtures_dir
|
||||||
File.join __dir__, 'fixtures'
|
File.join __dir__, 'fixtures'
|
||||||
|
Loading…
Reference in New Issue
Block a user