From e5ee9b46fde43f96061eee518f7c3c18330b4711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= Date: Sat, 30 Nov 2024 17:03:22 +0100 Subject: [PATCH 1/2] stylesheet: remove background and border from code spans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new style makes the code spans lighter and more integrated into the text and also makes the code spans more readable and less intrusive. A synopsis class is added for the code spans that are synopsis. Signed-off-by: Jean-Noël Avila --- assets/sass/application.scss | 2 +- assets/sass/man-pages.scss | 2 -- assets/sass/typography.scss | 9 +++++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/assets/sass/application.scss b/assets/sass/application.scss index e3c8833f09..176ac7f90d 100644 --- a/assets/sass/application.scss +++ b/assets/sass/application.scss @@ -32,7 +32,7 @@ $baseurl: "{{ .Site.BaseURL }}{{ if (and (ne .Site.BaseURL "/") (ne .Site.BaseUR code { display: inline; - padding: 0 5px; + padding: 0 0; } pre { diff --git a/assets/sass/man-pages.scss b/assets/sass/man-pages.scss index b3999b92a8..01b7edb836 100644 --- a/assets/sass/man-pages.scss +++ b/assets/sass/man-pages.scss @@ -51,7 +51,6 @@ word-wrap: break-word; /* Internet Explorer 5.5+ */ white-space: pre; white-space: pre-wrap; /* css-3 */ - background-color: #e8e7dd; em { font-weight: bold; @@ -59,7 +58,6 @@ } code { - background-color: #e8e7dd; margin-bottom: 0; border: none; padding-left: 0; diff --git a/assets/sass/typography.scss b/assets/sass/typography.scss index f9f7634276..74674aa594 100644 --- a/assets/sass/typography.scss +++ b/assets/sass/typography.scss @@ -260,8 +260,13 @@ code { line-height: $fixed-width-line-height; font-variant-ligatures: none; color: var(--orange); - background-color: var(--main-bg); - border: solid 1px var(--pre-border); +} + +p { + .synopsis { + @include border-radius(3px); + border: solid 1px var(--pre-border); + } } // Quotes From 9f228378c7be87ca9eecfb68ef67d2ae8a66d5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= Date: Sun, 17 Nov 2024 22:24:18 +0100 Subject: [PATCH 2/2] manpages: prepare for new manpage format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds a upcoming manpage format to the AsciiDoc backend. The new format changes are: * The synopsis is now a section with a dedicated style. This "synopsis" style allows to automatically format the keywords as monospaced and as italic. * the backticks are now used to format synopsis-like syntax in inline elements. The parsing of synopsis is done with a new AsciiDoc extension that makes use of the PEG parser parslet. All the asciidoc manpages sources are processed with this extension. It may upset the formatting for older manpages, making it not consistent across a page, but this will be a mild side effect, as this was not really consistent before. Signed-off-by: Jean-Noël Avila --- Gemfile | 2 +- Gemfile.lock | 3 + script/asciidoctor-extensions.rb | 124 +++++++++++++++++++++++++++++++ script/update-docs.rb | 1 + 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 script/asciidoctor-extensions.rb diff --git a/Gemfile b/Gemfile index 980ffe5c19..bfcb1bca7a 100644 --- a/Gemfile +++ b/Gemfile @@ -8,5 +8,5 @@ gem "rss" gem "asciidoctor", "~> 2.0.0" gem "nokogiri" gem "diffy" - gem "base64", "~> 0.2.0" +gem "parslet" diff --git a/Gemfile.lock b/Gemfile.lock index 5a050cc9e1..e7a7fba913 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -37,6 +37,7 @@ GEM octokit (9.2.0) faraday (>= 1, < 3) sawyer (~> 0.9) + parslet (2.0.0) public_suffix (6.0.1) racc (1.8.1) rexml (3.4.1) @@ -64,6 +65,7 @@ DEPENDENCIES faraday-retry nokogiri octokit + parslet rss CHECKSUMS @@ -86,6 +88,7 @@ CHECKSUMS nokogiri (1.18.8-x86_64-linux-gnu) sha256=4a747875db873d18a2985ee2c320a6070c4a414ad629da625fbc58d1a20e5ecc nokogiri (1.18.8-x86_64-linux-musl) sha256=ddd735fba49475a395b9ea793bb6474e3a3125b89960339604d08a5397de1165 octokit (9.2.0) sha256=4fa47ff35ce654127edf2c836ab9269bcc8829f5542dc1e86871f697ce7f4316 + parslet (2.0.0) sha256=d45130695d39b43d7e6a91f4d2ec66b388a8d822bae38de9b4de9a5fbde1f606 public_suffix (6.0.1) sha256=61d44e1cab5cbbbe5b31068481cf16976dd0dc1b6b07bd95617ef8c5e3e00c6f racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f rexml (3.4.1) sha256=c74527a9a0a04b4ec31dbe0dc4ed6004b960af943d8db42e539edde3a871abca diff --git a/script/asciidoctor-extensions.rb b/script/asciidoctor-extensions.rb new file mode 100644 index 0000000000..0362e665b1 --- /dev/null +++ b/script/asciidoctor-extensions.rb @@ -0,0 +1,124 @@ +require 'asciidoctor' +require 'asciidoctor/extensions' +require 'asciidoctor/converter/html5' +require 'parslet' +# for parslet, see https://kschiess.github.io/parslet/parser.html + +module Git + module Documentation + class AdocSynopsisQuote < Parslet::Parser + # parse a string like "git add -p [--root=]" as series of + # tokens keywords, grammar signs and placeholders where + # placeholders are UTF-8 words separated by '-', enclosed in '<' + # and '>'. The >> indicates a "simple sequence", for example + # str('...') >> match('\]|$').present? means "first match three + # periods, then ensure that they are either followed by a + # closing bracket or they are at the end. + rule(:space) { match('[\s\t\n ]').repeat(1) } + rule(:space?) { space.maybe } + rule(:keyword) { match('[-a-zA-Z0-9:+=~@,\./_\^\$\'"\*%!{}#]').repeat(1) } + rule(:placeholder) { str('<') >> match('[[:word:]]|-').repeat(1) >> str('>') } + rule(:opt_or_alt) { match('[\[\] |()]') >> space? } + rule(:ellipsis) { str('...') >> match('\]|$').present? } + rule(:grammar) { opt_or_alt | ellipsis } + rule(:ignore) { match('[\'`]') } + + rule(:token) do + grammar.as(:grammar) | placeholder.as(:placeholder) | space.as(:space) | + ignore.as(:ignore) | keyword.as(:keyword) + end + rule(:tokens) { token.repeat(1) } + root(:tokens) + end + + class EscapedSynopsisQuote < AdocSynopsisQuote + rule(:placeholder) { str('<') >> match('[[:word:]]|-').repeat(1) >> str('>') } + end + + class SynopsisQuoteBase < Parslet::Transform + rule(grammar: simple(:grammar)) { grammar.to_s } + rule(space: simple(:space)) { space.to_s } + rule(ignore: simple(:ignore)) { '' } + end + + class SynopsisQuoteToAdoc < SynopsisQuoteBase + rule(keyword: simple(:keyword)) { "{empty}`#{keyword}`{empty}" } + rule(placeholder: simple(:placeholder)) { "__#{placeholder}__" } + end + + class SynopsisQuoteToHtml5 < SynopsisQuoteBase + rule(keyword: simple(:keyword)) { "#{keyword}" } + rule(placeholder: simple(:placeholder)) { "#{placeholder}" } + end + + class SynopsisConverter + def convert(parslet_parser, parslet_transform, reader, logger = nil) + reader.lines.map do |l| + parslet_transform.apply(parslet_parser.parse(l)).join + end.join("\n") + rescue Parslet::ParseFailed + logger&.info "synopsis parsing failed for '#{reader.lines.join(' ')}'" + reader.lines.map do |l| + parslet_transform.apply(placeholder: l) + end.join("\n") + end + end + + class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor + use_dsl + named :synopsis + parse_content_as :simple + + def process(parent, reader, attrs) + outlines = SynopsisConverter.new.convert( + AdocSynopsisQuote.new, + SynopsisQuoteToAdoc.new, + reader, + parent.document.logger + ) + create_block parent, :verse, outlines, attrs + end + end + + # register a html5 converter that takes in charge + # to convert monospaced text into Git style synopsis + class GitHTMLConverter < Asciidoctor::Converter::Html5Converter + extend Asciidoctor::Converter::Config + register_for 'html5' + + def convert_inline_quoted(node) + if node.type == :monospaced + t = SynopsisConverter.new.convert( + EscapedSynopsisQuote.new, + SynopsisQuoteToHtml5.new, + node.text, + node.document.logger + ) + "#{t}" + else + open, close, tag = QUOTE_TAGS[node.type] + if node.id + class_attr = node.role ? %( class="#{node.role}") : '' + if tag + %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close}) + else + %(#{open}#{node.text}#{close}) + end + elsif node.role + if tag + %(#{open.chop} class="#{node.role}">#{node.text}#{close}) + else + %(#{open}#{node.text}#{close}) + end + else + %(#{open}#{node.text}#{close}) + end + end + end + end + end +end + +Asciidoctor::Extensions.register do + block Git::Documentation::SynopsisBlock +end diff --git a/script/update-docs.rb b/script/update-docs.rb index 1c5c17b424..37ca95f2ae 100644 --- a/script/update-docs.rb +++ b/script/update-docs.rb @@ -9,6 +9,7 @@ require 'yaml' require 'diffy' require_relative "version" +require_relative 'asciidoctor-extensions' SITE_ROOT = File.join(File.expand_path(File.dirname(__FILE__)), '../') DOCS_INDEX_FILE = "#{SITE_ROOT}external/docs/content/docs/_index.html"