asciidoctor-foodogsquared-extensions 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|