asciidoctor-foodogsquared-extensions 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/asciidoctor-foodogsquared-extensions.gemspec +22 -0
- data/lib/asciidoctor/chat-block-processor/README.adoc +115 -0
- data/lib/asciidoctor/chat-block-processor/extension.rb +56 -0
- data/lib/asciidoctor/fdroid-link-inline-macro/README.adoc +36 -0
- data/lib/asciidoctor/fdroid-link-inline-macro/extension.rb +28 -0
- data/lib/asciidoctor/flathub-link-inline-macro/README.adoc +28 -0
- data/lib/asciidoctor/flathub-link-inline-macro/extension.rb +35 -0
- data/lib/asciidoctor/foodogsquared-extensions.rb +56 -0
- data/lib/asciidoctor/git-blob-include-processor/README.adoc +68 -0
- data/lib/asciidoctor/git-blob-include-processor/extension.rb +79 -0
- data/lib/asciidoctor/github-link-inline-macro/README.adoc +49 -0
- data/lib/asciidoctor/github-link-inline-macro/extension.rb +36 -0
- data/lib/asciidoctor/github-raw-content-include-processor/README.adoc +40 -0
- data/lib/asciidoctor/github-raw-content-include-processor/extension.rb +68 -0
- data/lib/asciidoctor/gitlab-link-inline-macro/README.adoc +37 -0
- data/lib/asciidoctor/gitlab-link-inline-macro/extension.rb +31 -0
- data/lib/asciidoctor/gitlab-raw-content-include-processor/README.adoc +44 -0
- data/lib/asciidoctor/gitlab-raw-content-include-processor/extension.rb +66 -0
- data/lib/asciidoctor/helpers.rb +20 -0
- data/lib/asciidoctor/ietf-rfc-link-inline-macro/README.adoc +27 -0
- data/lib/asciidoctor/ietf-rfc-link-inline-macro/extension.rb +16 -0
- data/lib/asciidoctor/man-inline-macro/README.adoc +51 -0
- data/lib/asciidoctor/man-inline-macro/extension.rb +45 -0
- data/lib/asciidoctor/musicbrainz-link-inline-macro/README.adoc +45 -0
- data/lib/asciidoctor/musicbrainz-link-inline-macro/extension.rb +47 -0
- data/lib/asciidoctor/package-indices-link-macro/extension.rb +56 -0
- data/lib/asciidoctor/repology-link-inline-macro/README.adoc +27 -0
- data/lib/asciidoctor/repology-link-inline-macro/extension.rb +18 -0
- data/lib/asciidoctor/swhid-include-processor/README.adoc +44 -0
- data/lib/asciidoctor/swhid-include-processor/extension.rb +53 -0
- data/lib/asciidoctor/swhid-inline-macro/README.adoc +54 -0
- data/lib/asciidoctor/swhid-inline-macro/extension.rb +26 -0
- data/lib/asciidoctor/wikipedia-inline-macro/README.adoc +30 -0
- data/lib/asciidoctor/wikipedia-inline-macro/extension.rb +21 -0
- data/lib/asciidoctor-foodogsquared-extensions.rb +3 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f9f519d0ae3e0ac0e73c26e85acb925d53b9b937019d0361ee82b47fa4f8466a
|
4
|
+
data.tar.gz: b25430e1aeb1dee8b2563dc859a45879ed283698e4cdadef73f534a9a9876aaa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 307b4db3e7bc66f0ea323344fb177d90c65c3141aa714891277b76cfb656fc501f7ca7e9788e7dbeee7141637e2ec0cea2d0f13b409679f854840ae1b76c0163
|
7
|
+
data.tar.gz: 63dfa05bd984ea781cb53791a155303e162c1b6b6f582140b28f1804bc20c86fdeee7aaae523c5ec410266417130dba8852801b50d2cc5cc1e727e656a530b9a
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'asciidoctor-foodogsquared-extensions'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.licenses = ['MIT']
|
5
|
+
s.summary = "foo-dogsquared's custom Asciidoctor extensions"
|
6
|
+
s.description = <<-DESC
|
7
|
+
foo-dogsquared's custom Asciidoctor extensions as a Gem. This is not meant
|
8
|
+
to be used in production or as a public Gem. This is used since Hugo
|
9
|
+
doesn't allow loading Asciidoctor extensions with path separators.
|
10
|
+
DESC
|
11
|
+
|
12
|
+
s.required_ruby_version = '>= 3.0.0'
|
13
|
+
|
14
|
+
s.authors = ['Gabriel Arazas']
|
15
|
+
s.email = 'foodogsquared@foodogsquared.one'
|
16
|
+
s.metadata = { 'source_code_uri' => 'https://github.com/foo-dogsquared/foo-dogsquared.github.io' }
|
17
|
+
|
18
|
+
s.files = Dir['lib/**/*', '*.gemspec']
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'asciidoctor', '~> 2.0'
|
21
|
+
s.add_runtime_dependency 'rugged', '~> 1.0'
|
22
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
= Chat block processor
|
2
|
+
:toc:
|
3
|
+
|
4
|
+
|
5
|
+
A link:https://docs.asciidoctor.org/asciidoctor/latest/extensions/block-processor/[block processor] that adds a a dialog box style to the block.
|
6
|
+
Exclusive to the HTML backend.
|
7
|
+
|
8
|
+
|
9
|
+
== Synopsis
|
10
|
+
|
11
|
+
....
|
12
|
+
[chat, $AVATARNAME, $AVATARSTATE, $ATTRS...]
|
13
|
+
====
|
14
|
+
$CONTENT
|
15
|
+
====
|
16
|
+
....
|
17
|
+
|
18
|
+
The avatar name is the name of the folder to be retrieved from the `avatarsdir` attribute.
|
19
|
+
The directory enforces a certain structure which can be seen in <<extra-notes>>.
|
20
|
+
|
21
|
+
Both the avatar name and the state are to be converted to snake case (e.g., `El Pablo` to `el_pablo`) for the image path.
|
22
|
+
|
23
|
+
|
24
|
+
== Attributes
|
25
|
+
|
26
|
+
* `avatarsdir` is the folder containing the avatars' stickers.
|
27
|
+
This is explained in detail from the <<extra-notes>> section.
|
28
|
+
|
29
|
+
* `avatarstype` is similar to `icontype` attribute except this is used for the avatar stickers.
|
30
|
+
The default value is `webp`.
|
31
|
+
|
32
|
+
* `state` is the sticker to be retrieved from the avatars directory.
|
33
|
+
It has a default value of `default`.
|
34
|
+
You could also use this attribute instead of the `$AVATARSTATE` positional argument for whatever reason.
|
35
|
+
|
36
|
+
* `name` is the canonical name of the avatar.
|
37
|
+
This is used for titles and alts in the internal image block.
|
38
|
+
By default, this is the same as the given avatar.
|
39
|
+
|
40
|
+
|
41
|
+
[#extra-notes]
|
42
|
+
== Extra notes
|
43
|
+
|
44
|
+
This component has some prerequisites for this to fully work specifically with `avatarsdir` attribute that contains a list of avatars and their stickers.
|
45
|
+
By default, this value is at the `avatars` subdirectory of the `iconsdir` attribute.
|
46
|
+
It is recommended to set this value yourself.
|
47
|
+
+
|
48
|
+
--
|
49
|
+
This enforces a certain structure where the root directory contains a list of folders representing the avatar with each of the folder containing stickers which represents their state.
|
50
|
+
For example, here's what `avatarsdir` could contain following the expected structure.
|
51
|
+
|
52
|
+
[source]
|
53
|
+
----
|
54
|
+
./static/icons/avatars/
|
55
|
+
├── ezran/
|
56
|
+
│ ├── crisis.webp
|
57
|
+
│ ├── default.webp
|
58
|
+
│ ├── sad.webp
|
59
|
+
│ └── shocked.webp
|
60
|
+
└── foodogsquared/
|
61
|
+
├── crisis.webp
|
62
|
+
├── default.webp
|
63
|
+
├── sad.webp
|
64
|
+
└── shocked.webp
|
65
|
+
----
|
66
|
+
--
|
67
|
+
|
68
|
+
|
69
|
+
== Example usage
|
70
|
+
|
71
|
+
Let's assume `avatarsdir` is set to the `static/icons/avatars` with the following file structure.
|
72
|
+
|
73
|
+
[source]
|
74
|
+
----
|
75
|
+
./static/icons/avatars/
|
76
|
+
├── ezran/
|
77
|
+
│ ├── crisis.webp
|
78
|
+
│ ├── default.webp
|
79
|
+
│ ├── sad.webp
|
80
|
+
│ └── shocked.webp
|
81
|
+
├── el-pablo/
|
82
|
+
│ ├── crisis.webp
|
83
|
+
│ ├── default.webp
|
84
|
+
│ ├── ghastly.webp
|
85
|
+
│ ├── melodramatic.webp
|
86
|
+
│ ├── sad.webp
|
87
|
+
│ └── shocked.webp
|
88
|
+
└── foodogsquared/
|
89
|
+
├── crisis.webp
|
90
|
+
├── default.webp
|
91
|
+
├── sad.webp
|
92
|
+
└── shocked.webp
|
93
|
+
----
|
94
|
+
|
95
|
+
- The following block should get the default image for `foodogsquared` which is in `./static/icons/avatars/foodogsquared/default.webp`.
|
96
|
+
+
|
97
|
+
....
|
98
|
+
[chat, foodogsquared]
|
99
|
+
====
|
100
|
+
Hello there!
|
101
|
+
====
|
102
|
+
....
|
103
|
+
|
104
|
+
- The following block should contain El Pablo's melodramatic dialog state.
|
105
|
+
Take note of the resulting path for the image which is in kebab-case.
|
106
|
+
+
|
107
|
+
....
|
108
|
+
[chat, El Pablo, state=melodramatic]
|
109
|
+
====
|
110
|
+
What tragedy is happening here!
|
111
|
+
I couldn't take it.
|
112
|
+
|
113
|
+
__Please__.
|
114
|
+
====
|
115
|
+
....
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ChatBlock < Asciidoctor::Extensions::BlockProcessor
|
4
|
+
use_dsl
|
5
|
+
|
6
|
+
named :chat
|
7
|
+
on_context :example
|
8
|
+
name_positional_attributes 'avatar', 'state'
|
9
|
+
default_attributes 'state' => 'default', 'avatarstype' => 'avif'
|
10
|
+
|
11
|
+
def process(parent, reader, attrs)
|
12
|
+
block = create_block parent, :pass, nil, attrs, content_model: :compound
|
13
|
+
block.add_role('dialogblock')
|
14
|
+
|
15
|
+
# You can think of this section as a pipeline constructing the HTML
|
16
|
+
# component for this block. Specifically, we're building one component that
|
17
|
+
# contains two output: the dialog image of our avatar and its content.
|
18
|
+
attrs['name'] ||= attrs['avatar']
|
19
|
+
|
20
|
+
block << (create_html_fragment block, %(
|
21
|
+
<div role="figure" class="dialogblock dialogblock__box dialogblock__avatar--#{attrs['avatar']} #{attrs['role']}">
|
22
|
+
<div class="dialogblock dialogblock__avatar">
|
23
|
+
))
|
24
|
+
|
25
|
+
attrs['avatarsdir'] ||= File.expand_path('./avatars', attrs['iconsdir'])
|
26
|
+
|
27
|
+
avatar_sticker = "#{attrs['avatar'].to_kebab}/#{attrs['state'].to_kebab}.#{attrs['avatarstype']}"
|
28
|
+
avatar_img_attrs = {
|
29
|
+
'target' => parent.image_uri(avatar_sticker, 'avatarsdir'),
|
30
|
+
'alt' => attrs['name']
|
31
|
+
}
|
32
|
+
avatar_imgblock = create_image_block block, avatar_img_attrs
|
33
|
+
|
34
|
+
block << avatar_imgblock
|
35
|
+
block << (create_html_fragment block, %(
|
36
|
+
</div>
|
37
|
+
<div class="dialogblock dialogblock__text">
|
38
|
+
<small class="dialogblock dialogblock__avatar-name">#{attrs['name']}</small>
|
39
|
+
))
|
40
|
+
|
41
|
+
parse_content block, reader
|
42
|
+
|
43
|
+
block << (create_html_fragment block, %(
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
))
|
47
|
+
|
48
|
+
block
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def create_html_fragment(parent, html, attributes = nil)
|
54
|
+
create_block parent, :pass, html, attributes
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
= F-droid link inline macro
|
2
|
+
:toc:
|
3
|
+
|
4
|
+
|
5
|
+
An inline macro as a shorthand for F-droid links.
|
6
|
+
|
7
|
+
|
8
|
+
== Synopsis
|
9
|
+
|
10
|
+
[source, asciidoc]
|
11
|
+
----
|
12
|
+
fdroid:$APP_ID[$CAPTION]
|
13
|
+
----
|
14
|
+
|
15
|
+
Where...
|
16
|
+
|
17
|
+
- `$APP_ID` is the application ID of the program (e.g., `org.moire.ultrasonic`).
|
18
|
+
|
19
|
+
- `$CAPTION` is the link text.
|
20
|
+
By default, it will use the display name of the application from its link:https://gitlab.com/fdroid/fdroiddata/[metadata repository].
|
21
|
+
In other words, it will create an additional network request.
|
22
|
+
|
23
|
+
|
24
|
+
== Attributes
|
25
|
+
|
26
|
+
- `lang` is the language page to be linked.
|
27
|
+
By default, it links to the English page of `en`.
|
28
|
+
|
29
|
+
|
30
|
+
== Example usage
|
31
|
+
|
32
|
+
- `fdroid:org.moire.ultrasonic[]` should link to the link:https://f-droid.org/en/packages/org.moire.ultrasonic/[F-Droid page for Ultrasonic] with the link text 'Ultrasonic'.
|
33
|
+
|
34
|
+
- `fdroid:org.moire.ultrasonic[Hello there]` is the same as previous item but with the link text replaced with 'Hello there'.
|
35
|
+
|
36
|
+
- `fdroid:org.moire.ultrasonic[lang=it]` is the same as the first list item but links to the link:https://f-droid.org/it/packages/org.moire.ultrasonic/[Italian page].
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open-uri'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
class FDroidLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
7
|
+
use_dsl
|
8
|
+
|
9
|
+
named :fdroid
|
10
|
+
name_positional_attributes 'caption'
|
11
|
+
default_attributes 'lang' => 'en'
|
12
|
+
|
13
|
+
def process(parent, target, attrs)
|
14
|
+
doc = parent.document
|
15
|
+
|
16
|
+
app_id = target
|
17
|
+
app_metadata_uri = %(https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/#{app_id}.yml)
|
18
|
+
|
19
|
+
if attrs['caption'].nil?
|
20
|
+
metadata = OpenURI.open_uri(app_metadata_uri) { |f| YAML.safe_load(f.read) }
|
21
|
+
attrs['caption'] = metadata['AutoName']
|
22
|
+
end
|
23
|
+
|
24
|
+
url = %(https://f-droid.org/#{attrs['lang']}/packages/#{app_id})
|
25
|
+
doc.register :links, url
|
26
|
+
create_anchor parent, attrs['caption'], type: :link, target: url
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
= Flathub link inline macro
|
2
|
+
:toc:
|
3
|
+
|
4
|
+
|
5
|
+
A shorthand for linking applications from link:https://flathub.org[FlatHub].
|
6
|
+
|
7
|
+
|
8
|
+
== Synopsis
|
9
|
+
|
10
|
+
[source, asciidoc]
|
11
|
+
----
|
12
|
+
flathub:$APP_ID[$CAPTION]
|
13
|
+
----
|
14
|
+
|
15
|
+
Where...
|
16
|
+
|
17
|
+
- `$APP_ID` is the application ID of the program on Flathub.
|
18
|
+
|
19
|
+
- `$CAPTION` is the link text to be used.
|
20
|
+
By default, it will get the appstream metadata from FlatHub and use the display name.
|
21
|
+
Take note it creates an additional network request to get the name.
|
22
|
+
|
23
|
+
|
24
|
+
== Example usage
|
25
|
+
|
26
|
+
- `flathub:org.gnome.design.IconLibrary[]` links to the link:https://flathub.org/apps/org.gnome.design.IconLibrary[FlatHub page of GNOME Icon Library] with `Icon Library` as the link text.
|
27
|
+
|
28
|
+
- `flathub:org.gnome.design.IconLibrary[GNOME Icon Library]` is the same as the previous list item but with its link text replaced with `GNOME Icon Library`.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'open-uri'
|
5
|
+
|
6
|
+
class FlathubLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
7
|
+
use_dsl
|
8
|
+
|
9
|
+
named :flathub
|
10
|
+
name_positional_attributes 'caption'
|
11
|
+
|
12
|
+
def process(parent, target, attrs)
|
13
|
+
doc = parent.document
|
14
|
+
|
15
|
+
# FlatHub API seems to have no documentation aside from the source code.
|
16
|
+
# You can easily infer the API with its source code at
|
17
|
+
# https://github.com/flathub/website.
|
18
|
+
app_id = target
|
19
|
+
app_metadata_uri = %(https://flathub.org/api/v2/appstream/#{app_id})
|
20
|
+
|
21
|
+
headers = {
|
22
|
+
'Accept' => 'application/json',
|
23
|
+
'User-Agent' => ::Asciidoctor::FoodogsquaredCustomExtensions::USER_AGENT
|
24
|
+
}
|
25
|
+
|
26
|
+
if attrs['caption'].nil?
|
27
|
+
metadata = OpenURI.open_uri(app_metadata_uri, headers) { |f| JSON.parse(f.read) }
|
28
|
+
attrs['caption'] = metadata['name']
|
29
|
+
end
|
30
|
+
|
31
|
+
url = %(https://flathub.org/apps/#{app_id})
|
32
|
+
doc.register :links, url
|
33
|
+
create_anchor parent, attrs['caption'], type: :link, target: url
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'asciidoctor'
|
4
|
+
require 'asciidoctor/extensions'
|
5
|
+
|
6
|
+
require_relative 'helpers'
|
7
|
+
|
8
|
+
require_relative 'man-inline-macro/extension'
|
9
|
+
require_relative 'swhid-inline-macro/extension'
|
10
|
+
require_relative 'swhid-include-processor/extension'
|
11
|
+
require_relative 'github-link-inline-macro/extension'
|
12
|
+
require_relative 'github-raw-content-include-processor/extension'
|
13
|
+
require_relative 'gitlab-link-inline-macro/extension'
|
14
|
+
require_relative 'gitlab-raw-content-include-processor/extension'
|
15
|
+
require_relative 'chat-block-processor/extension'
|
16
|
+
require_relative 'git-blob-include-processor/extension'
|
17
|
+
require_relative 'wikipedia-inline-macro/extension'
|
18
|
+
require_relative 'package-indices-link-macro/extension'
|
19
|
+
require_relative 'fdroid-link-inline-macro/extension'
|
20
|
+
require_relative 'musicbrainz-link-inline-macro/extension'
|
21
|
+
require_relative 'flathub-link-inline-macro/extension'
|
22
|
+
require_relative 'repology-link-inline-macro/extension'
|
23
|
+
require_relative 'ietf-rfc-link-inline-macro/extension'
|
24
|
+
|
25
|
+
Asciidoctor::Extensions.register do
|
26
|
+
inline_macro ManInlineMacro
|
27
|
+
inline_macro IETFRFCLinkInlineMacro
|
28
|
+
block ChatBlock if @document.basebackend? 'html'
|
29
|
+
|
30
|
+
inline_macro SWHInlineMacro
|
31
|
+
include_processor SWHIDIncludeProcessor
|
32
|
+
|
33
|
+
inline_macro GitHubLinkInlineMacro
|
34
|
+
include_processor GitHubRawIncludeProcessor
|
35
|
+
|
36
|
+
inline_macro GitLabLinkInlineMacro
|
37
|
+
include_processor GitLabRawIncludeProcessor
|
38
|
+
|
39
|
+
include_processor GitBlobIncludeProcessor
|
40
|
+
preprocessor GitContentBranchAttributePreprocessor
|
41
|
+
|
42
|
+
inline_macro WikipediaInlineMacro
|
43
|
+
|
44
|
+
# Package indices
|
45
|
+
inline_macro CtanLinkInlineMacro
|
46
|
+
inline_macro PypiLinkInlineMacro
|
47
|
+
inline_macro CratesIOLinkInlineMacro
|
48
|
+
|
49
|
+
# App stores
|
50
|
+
inline_macro FDroidLinkInlineMacro
|
51
|
+
inline_macro FlathubLinkInlineMacro
|
52
|
+
|
53
|
+
# Databases
|
54
|
+
inline_macro MusicBrainzLinkInlineMacro
|
55
|
+
inline_macro RepologyLinkInlineMacro
|
56
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
= Git blob include processor
|
2
|
+
:toc:
|
3
|
+
|
4
|
+
|
5
|
+
An include processor that includes content from the current Git repo.
|
6
|
+
The use case for this is specifically for creating dedicated branches for certain content.
|
7
|
+
|
8
|
+
|
9
|
+
== Synopsis
|
10
|
+
|
11
|
+
[source, asciidoc]
|
12
|
+
----
|
13
|
+
include::git:$REVSPEC[]
|
14
|
+
----
|
15
|
+
|
16
|
+
Where `$REVSPEC` is a revision as specified in link:https://manpages.debian.org/gitrevisions.7[gitrevisions.7].
|
17
|
+
Take note this include processor only accepts a blob object's content to be extracted.
|
18
|
+
This is meant to be used with other attributes.
|
19
|
+
See <<Attributes>> for more details.
|
20
|
+
|
21
|
+
If the resulting operation ends in an error (i.e., non-existing revision, file, something went wrong), it should log a warning and transclude an error.
|
22
|
+
|
23
|
+
|
24
|
+
== Attributes
|
25
|
+
|
26
|
+
- `path` is the filepath to be retrieved from the revision.
|
27
|
+
When used with `diff`, it changes into a semicolon-delimited (`;`) list of files to make diffs with multiple files.
|
28
|
+
|
29
|
+
- `context-lines` is the number of surrounding lines for the diff.
|
30
|
+
This is only effective if `diff` option is given.
|
31
|
+
|
32
|
+
- `other` is the other commit to be compared with.
|
33
|
+
This is only effective if `diff` option is given.
|
34
|
+
|
35
|
+
- `lines` get the specified lines from the path.
|
36
|
+
It uses the same parser as the line specifier from link:https://docs.asciidoctor.org/asciidoc/latest/verbatim/highlight-lines/[highlighting select lines] so the syntax is the same.
|
37
|
+
|
38
|
+
There's also a couple of link:https://docs.asciidoctor.org/asciidoc/latest/attributes/options/[options] for this component.
|
39
|
+
You can give the following options through `opts` attribute (i.e., `opts="diff,reverse"`).
|
40
|
+
|
41
|
+
- `diff` will show the difference in link:https://en.wikipedia.org/wiki/Diff[diff] format.
|
42
|
+
|
43
|
+
- `reverse` reverses the sides to be compared.
|
44
|
+
|
45
|
+
|
46
|
+
== Extra notes
|
47
|
+
|
48
|
+
The extension is composed of two parts: an include processor and a preprocessor.
|
49
|
+
|
50
|
+
The preprocessor add a document attribute, `doccontentref`, which it gives the Git reference for that content.
|
51
|
+
`doccontentref` is the difference between the process working directory (`Dir.pwd`) and the base directory of the content to be converted.
|
52
|
+
In case the process working directory is not entirely consistent for several reasons, you could give the attribute `rootdir` as the basis for the comparison.
|
53
|
+
As another option, you could also manually set `doccontentref` in case it isn't applicable (i.e., for multilingual sites in Hugo projects).
|
54
|
+
|
55
|
+
The include processor also accepts an empty target with the prefix (i.e., `include::git:[]`) as a shorthand for `include::git:{doccontentref}`.
|
56
|
+
|
57
|
+
|
58
|
+
== Example usage
|
59
|
+
|
60
|
+
The following examples assume that `doccontentref` points to `content/posts/sample`.
|
61
|
+
|
62
|
+
- `include::git:HEAD[path=shell.nix]` should transclude the current iteration of `shell.nix`.
|
63
|
+
|
64
|
+
- `include::git:{doccontentref}[opts="diff", path=Gemfile]` should include a diff of the Gemfile from `content/posts/sample` branch (assuming that Gemfile has changed).
|
65
|
+
|
66
|
+
- `include::git:non-existing-rev[opts="diff"]` should result in a warning with the non-existing revision.
|
67
|
+
|
68
|
+
- `include::git:{doccontentref}[path=README, lines=2..5]` should transclude the README file from lines 2-5.
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rugged'
|
4
|
+
|
5
|
+
class GitBlobIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
|
6
|
+
def handles?(target)
|
7
|
+
target.start_with? 'git:'
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(doc, reader, target, attrs)
|
11
|
+
repo = Rugged::Repository.discover(__dir__)
|
12
|
+
|
13
|
+
git_object_ref = target.delete_prefix 'git:'
|
14
|
+
git_object_ref = doc.attributes['doccontentref'] if git_object_ref.empty?
|
15
|
+
|
16
|
+
begin
|
17
|
+
git_object = repo.rev_parse git_object_ref
|
18
|
+
|
19
|
+
if attrs.key? 'diff-option'
|
20
|
+
options = {}
|
21
|
+
|
22
|
+
options[:paths] = attrs['path'].split(';') if attrs.key? 'path'
|
23
|
+
options[:context_lines] = attrs['context-lines'] if attrs.key? 'context-lines'
|
24
|
+
options[:reverse] = true if attrs.key? 'reverse-option'
|
25
|
+
|
26
|
+
if attrs.key? 'other'
|
27
|
+
other = repo.rev_parse attrs['other'] || nil
|
28
|
+
reader.push_include git_object.diff(other, **options).patch
|
29
|
+
else
|
30
|
+
reader.push_include git_object.diff(**options).patch
|
31
|
+
end
|
32
|
+
else
|
33
|
+
inner_entry = case git_object.type
|
34
|
+
when :blob
|
35
|
+
git_object
|
36
|
+
when :commit
|
37
|
+
git_object.tree.path attrs['path']
|
38
|
+
when :tree
|
39
|
+
git_object.path attrs['path']
|
40
|
+
when :tag
|
41
|
+
git_object.target.tree.path attrs['path']
|
42
|
+
end
|
43
|
+
|
44
|
+
content = repo.lookup(inner_entry[:oid]).content
|
45
|
+
|
46
|
+
if attrs.key? 'lines'
|
47
|
+
content_lines = content.lines
|
48
|
+
new_content = +''
|
49
|
+
doc.resolve_lines_to_highlight(content, attrs['lines']).each do |line_no|
|
50
|
+
new_content << content_lines.at(line_no - 1)
|
51
|
+
end
|
52
|
+
|
53
|
+
content = new_content
|
54
|
+
end
|
55
|
+
|
56
|
+
reader.push_include content
|
57
|
+
end
|
58
|
+
rescue StandardError => e
|
59
|
+
reader.push_include "Unresolved directive for '#{target}' with the following error:\n#{e}"
|
60
|
+
warn e
|
61
|
+
end
|
62
|
+
|
63
|
+
reader
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class GitContentBranchAttributePreprocessor < Asciidoctor::Extensions::Preprocessor
|
68
|
+
def process(document, reader)
|
69
|
+
base_dir = Pathname.new(document.base_dir)
|
70
|
+
rootdir = if document.attributes['rootdir'].nil?
|
71
|
+
Dir.pwd
|
72
|
+
else
|
73
|
+
document.attributes['rootdir']
|
74
|
+
end
|
75
|
+
|
76
|
+
document.attributes['doccontentref'] = base_dir.relative_path_from(rootdir).to_s
|
77
|
+
reader
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
= GitHub link inline macro
|
2
|
+
:toc:
|
3
|
+
|
4
|
+
|
5
|
+
An inline macro that easily links repositories from GitHub.
|
6
|
+
|
7
|
+
|
8
|
+
== Synopsis
|
9
|
+
|
10
|
+
[source, asciidoc]
|
11
|
+
----
|
12
|
+
github:$OWNER/$REPO[$CAPTION]
|
13
|
+
----
|
14
|
+
|
15
|
+
If caption is missing, the link text will be the namespace (i.e., `$OWNER/$REPO`) of the repo.
|
16
|
+
|
17
|
+
|
18
|
+
== Attributes
|
19
|
+
|
20
|
+
There are optional attributes for this macro.
|
21
|
+
|
22
|
+
- `rev` is the commit/branch/tag of the repo to be linked.
|
23
|
+
When given no caption, it will update the default caption with `$OWNER/$REPO@$REV`.
|
24
|
+
|
25
|
+
- `path` is the filepath to be linked within the repo.
|
26
|
+
|
27
|
+
- `issue` accepts the issue number to be linked in the GitHub repo.
|
28
|
+
Take note `issue` is exclusive to other attributes and has more precedence.
|
29
|
+
For example, if `issue` and `rev` are both present, the link for issue will be the result.
|
30
|
+
+
|
31
|
+
When given no caption, it will update the default caption with `$OWNER/$REPO#$ISSUE`.
|
32
|
+
|
33
|
+
You can also change certain behaviors with the link:https://docs.asciidoctor.org/asciidoc/latest/attributes/options/[options attribute].
|
34
|
+
|
35
|
+
- `repo` sets the default link text with only the repo.
|
36
|
+
Pretty useful to quickly refer to the name of the software.
|
37
|
+
|
38
|
+
|
39
|
+
== Example usage
|
40
|
+
|
41
|
+
- `github:foo-dogsquared/website[]` will link to link:https://github.com/foo-dogsquared/website[my website repository] with the link text `foo-dogsquared/website`.
|
42
|
+
|
43
|
+
- `github:NixOS/nixpkgs[nixpkgs nixos-unstable branch, rev=nixos-unstable]` should link to the link:https://github.com/NixOS/nixpkgs/tree/nixos-unstable[NixOS unstable branch of nixpkgs] with a caption of `nixpkgs nixos-unstable branch`.
|
44
|
+
|
45
|
+
- `github:errata-ai/vale[Vale v2.3.0 README, path=README.md, rev=v2.3.0]` should link to the link:https://github.com/errata-ai/vale/blob/v2.3.0/README.md[README of Vale v2.3.0].
|
46
|
+
|
47
|
+
- `github:neovim/neovim[Neovim cannot open large files properly, issue=614]` should link to https://github.com/neovim/neovim/issues/614[an issue of Neovim] with `Neovim cannot open large files properly` as the link text.
|
48
|
+
|
49
|
+
- `github:neovim/neovim[Neovim cannot open large files properly, issue=614, rev=master]` should still link to https://github.com/neovim/neovim/issues/614[an issue of Neovim] since `issue` has more precedence over `rev`.
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
class GitHubLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
6
|
+
use_dsl
|
7
|
+
|
8
|
+
named :github
|
9
|
+
name_positional_attributes 'caption'
|
10
|
+
|
11
|
+
def process(parent, target, attrs)
|
12
|
+
doc = parent.document
|
13
|
+
|
14
|
+
default_caption = if attrs.key?('repo-option')
|
15
|
+
target.split('/').at(1)
|
16
|
+
else
|
17
|
+
target
|
18
|
+
end
|
19
|
+
text = attrs['caption'] || default_caption
|
20
|
+
uri = URI.parse %(https://github.com/#{target})
|
21
|
+
|
22
|
+
if attrs.key? 'issue'
|
23
|
+
uri.path += %(/issues/#{attrs['issue']})
|
24
|
+
text << "##{attrs['issue']}" if text == target
|
25
|
+
else
|
26
|
+
uri.path += %(/tree/#{attrs['rev']}) if attrs.key? 'rev'
|
27
|
+
uri.path += %(/#{attrs['path']}) if attrs.key? 'path'
|
28
|
+
text << "@#{attrs['rev']}" if attrs.key?('rev') && text == target
|
29
|
+
end
|
30
|
+
|
31
|
+
target = uri.to_s
|
32
|
+
|
33
|
+
doc.register :links, target
|
34
|
+
create_anchor parent, text, type: :link, target: target
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
= GitHub raw content include processor
|
2
|
+
:toc:
|
3
|
+
|
4
|
+
|
5
|
+
This is a link:https://docs.asciidoctor.org/asciidoctor/latest/extensions/include-processor/[include processor] for easily including files from GitHub.
|
6
|
+
Take note this will only include files.
|
7
|
+
For directories, submodules, or symlinks: they will not be processed and a warning will be issued.
|
8
|
+
|
9
|
+
This extension honors the link:https://docs.asciidoctor.org/asciidoctor/latest/safe-modes/[safe mode setting] and link:https://docs.asciidoctor.org/asciidoc/latest/directives/include-uri/[the prerequisites for permitting includes with URI].
|
10
|
+
|
11
|
+
The following is the basic form of using this include processor.
|
12
|
+
|
13
|
+
[source, asciidoc]
|
14
|
+
----
|
15
|
+
\include::github:$OWNER/$REPO[]
|
16
|
+
----
|
17
|
+
|
18
|
+
|
19
|
+
== Extra notes
|
20
|
+
|
21
|
+
The include processor will use GitHub API.
|
22
|
+
It can create authorized requests by setting a token in `GITHUB_API_BEARER_TOKEN` environment variable.
|
23
|
+
For instructions on how to get a token, you can refer to link:https://docs.github.com/en/rest/guides/getting-started-with-the-rest-api?apiVersion=2022-11-28#authenticating[respective documentation].
|
24
|
+
|
25
|
+
|
26
|
+
== Attributes
|
27
|
+
|
28
|
+
- `path` for the path of the file to be included.
|
29
|
+
This is practically required as the root entry of the repository is a directory.
|
30
|
+
|
31
|
+
- `rev` is the name of the commit/tag/branch to be checked out.
|
32
|
+
|
33
|
+
|
34
|
+
== Example usage
|
35
|
+
|
36
|
+
- `include::github:asciidoctor/asciidoctor[path=README.adoc, rev=v2.0.0]` will include the Asciidoc file from the link:https://github.com/asciidoctor/asciidoctor/[Asciidoctor GitHub repo] from the point of `v2.0.0`.
|
37
|
+
|
38
|
+
- `include::github:NixOS/nixpkgs[path=shell.nix]` will get the latest revision of `shell.nix` from link:https://github.com/NixOS/nixpkgs[nixpkgs repository].
|
39
|
+
|
40
|
+
- `include::github:foo-dogsquared/nixos-config[]` should not be processed considering it points to the root directory of the repository.
|