asciidoctor-foodogsquared-extensions 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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.