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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/asciidoctor-foodogsquared-extensions.gemspec +22 -0
  3. data/lib/asciidoctor/chat-block-processor/README.adoc +115 -0
  4. data/lib/asciidoctor/chat-block-processor/extension.rb +56 -0
  5. data/lib/asciidoctor/fdroid-link-inline-macro/README.adoc +36 -0
  6. data/lib/asciidoctor/fdroid-link-inline-macro/extension.rb +28 -0
  7. data/lib/asciidoctor/flathub-link-inline-macro/README.adoc +28 -0
  8. data/lib/asciidoctor/flathub-link-inline-macro/extension.rb +35 -0
  9. data/lib/asciidoctor/foodogsquared-extensions.rb +56 -0
  10. data/lib/asciidoctor/git-blob-include-processor/README.adoc +68 -0
  11. data/lib/asciidoctor/git-blob-include-processor/extension.rb +79 -0
  12. data/lib/asciidoctor/github-link-inline-macro/README.adoc +49 -0
  13. data/lib/asciidoctor/github-link-inline-macro/extension.rb +36 -0
  14. data/lib/asciidoctor/github-raw-content-include-processor/README.adoc +40 -0
  15. data/lib/asciidoctor/github-raw-content-include-processor/extension.rb +68 -0
  16. data/lib/asciidoctor/gitlab-link-inline-macro/README.adoc +37 -0
  17. data/lib/asciidoctor/gitlab-link-inline-macro/extension.rb +31 -0
  18. data/lib/asciidoctor/gitlab-raw-content-include-processor/README.adoc +44 -0
  19. data/lib/asciidoctor/gitlab-raw-content-include-processor/extension.rb +66 -0
  20. data/lib/asciidoctor/helpers.rb +20 -0
  21. data/lib/asciidoctor/ietf-rfc-link-inline-macro/README.adoc +27 -0
  22. data/lib/asciidoctor/ietf-rfc-link-inline-macro/extension.rb +16 -0
  23. data/lib/asciidoctor/man-inline-macro/README.adoc +51 -0
  24. data/lib/asciidoctor/man-inline-macro/extension.rb +45 -0
  25. data/lib/asciidoctor/musicbrainz-link-inline-macro/README.adoc +45 -0
  26. data/lib/asciidoctor/musicbrainz-link-inline-macro/extension.rb +47 -0
  27. data/lib/asciidoctor/package-indices-link-macro/extension.rb +56 -0
  28. data/lib/asciidoctor/repology-link-inline-macro/README.adoc +27 -0
  29. data/lib/asciidoctor/repology-link-inline-macro/extension.rb +18 -0
  30. data/lib/asciidoctor/swhid-include-processor/README.adoc +44 -0
  31. data/lib/asciidoctor/swhid-include-processor/extension.rb +53 -0
  32. data/lib/asciidoctor/swhid-inline-macro/README.adoc +54 -0
  33. data/lib/asciidoctor/swhid-inline-macro/extension.rb +26 -0
  34. data/lib/asciidoctor/wikipedia-inline-macro/README.adoc +30 -0
  35. data/lib/asciidoctor/wikipedia-inline-macro/extension.rb +21 -0
  36. data/lib/asciidoctor-foodogsquared-extensions.rb +3 -0
  37. 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.