[PATCH 0/9] Improve docs web reference checker

Improve the checker tool to also track orphaned pages and check presence and usage of images. In addition to that this series fixes handful of instances of the problems that the script caught. This series adds two documents: - docs/logos/README.rst (converted into docs/logos/index.html) The page shows all logos which libvirt has. It's now linked from the docs page. https://pipo.sk.gitlab.io/-/libvirt/-/jobs/3770134533/artifacts/website/logo... - docs/golang.rst The page ties together the 4 go module pages we have which were not linked and is linked from docs.html https://pipo.sk.gitlab.io/-/libvirt/-/jobs/3770134533/artifacts/website/gola... Peter Krempa (9): docs: XSL: Add source document name as custom data attribute for <html> scripts: check-html-references: Rename --prefix to --webroot and make it mandatory scripts: check-html-references: Improve error messages and don't mess with relative paths docs: manpages: Add missing manpages to index docs: Add sub-page for all golang modules scripts: check-html-references: Detect pages that are not linked to kbase: eventloop: Fix path to referenced images docs: logos: Turn 'README' into rST, generate an index and link to images scripts: check-html-refernces: Add checking for image file usage docs/docs.rst | 5 +- docs/golang.rst | 21 +++ docs/kbase/internals/eventloop.rst | 4 +- docs/logos/README | 98 -------------- docs/logos/README.rst | 166 ++++++++++++++++++++++++ docs/logos/meson.build | 47 +++++++ docs/manpages/index.rst | 3 + docs/meson.build | 3 +- docs/page.xsl | 2 +- scripts/check-html-references.py | 198 +++++++++++++++++++++++------ 10 files changed, 406 insertions(+), 141 deletions(-) create mode 100644 docs/golang.rst delete mode 100644 docs/logos/README create mode 100644 docs/logos/README.rst -- 2.39.1

The html standard allows custom data attributes on any element in the format of 'data-*' which are not interpreted. We can use it to embed the name of the source document used to generate the page so that our checker tools can use the friendly name. https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible... Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/page.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/page.xsl b/docs/page.xsl index 548d5a11c4..20b49d1afd 100644 --- a/docs/page.xsl +++ b/docs/page.xsl @@ -80,7 +80,7 @@ <xsl:param name="timestamp"/> <xsl:text disable-output-escaping="yes"><!DOCTYPE html> </xsl:text> - <html> + <html data-sourcedoc="{$pagesrc}"> <xsl:comment> This file is autogenerated from <xsl:value-of select="$pagesrc"/> Do not edit this file. Changes will be lost. -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:09PM +0100, Peter Krempa wrote:
The html standard allows custom data attributes on any element in the format of 'data-*' which are not interpreted. We can use it to embed the name of the source document used to generate the page so that our checker tools can use the friendly name.
https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible...
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/page.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Force users to pass the path to the root of the webpage the script should check. The script lives in a different subdirectory so the default of the current directory doesn't make much sense. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/meson.build | 2 +- scripts/check-html-references.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/meson.build b/docs/meson.build index 5c0c762db1..5ffd39c01b 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -359,7 +359,7 @@ test( python3_prog, args: [ check_html_references_prog.full_path(), - '--prefix', + '--webroot', meson.project_build_root() / 'docs' ], env: runutf8, diff --git a/scripts/check-html-references.py b/scripts/check-html-references.py index 95a61a6bb4..6d9116585e 100755 --- a/scripts/check-html-references.py +++ b/scripts/check-html-references.py @@ -127,14 +127,14 @@ def check_targets(targets, anchors): parser = argparse.ArgumentParser(description='HTML reference checker') -parser.add_argument('--prefix', default='.', - help='build tree prefix') +parser.add_argument('--webroot', required=True, + help='path to the web root') parser.add_argument('--external', action="store_true", help='print external references instead') args = parser.parse_args() -files = get_file_list(args.prefix) +files = get_file_list(args.webroot) targets, anchors = process_all(files) -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:10PM +0100, Peter Krempa wrote:
Force users to pass the path to the root of the webpage the script should check. The script lives in a different subdirectory so the default of the current directory doesn't make much sense.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/meson.build | 2 +- scripts/check-html-references.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Now that we have the source file name as a custom attribute we can use it to report which file actually needs to be edited to fix the error: ERROR: 'docs/uri.rst': broken link to: 'drvqemu.html#exaple' rather than: broken link targets: docs/uri.html broken link: drvqemu.html#exaple which pointed to file which does not exist in the source directory. This also allows us to delete all the relative path handling needed to report at least somewhat user-legible errors before. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- scripts/check-html-references.py | 46 +++++++++++++------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/scripts/check-html-references.py b/scripts/check-html-references.py index 6d9116585e..8e726928e0 100755 --- a/scripts/check-html-references.py +++ b/scripts/check-html-references.py @@ -30,13 +30,6 @@ def get_file_list(prefix): filelist = [] for root, dir, files in os.walk(prefix): - prefixbase = os.path.dirname(prefix) - - if root.startswith(prefixbase): - relroot = root[len(prefixbase):] - else: - relroot = root - for file in files: if not re.search('\\.html$', file): continue @@ -45,20 +38,21 @@ def get_file_list(prefix): if '404.html' in file: continue - fullfilename = os.path.join(root, file) - relfilename = os.path.join(relroot, file) - filelist.append((fullfilename, relfilename)) + filelist.append(os.path.join(root, file)) return filelist # loads an XHTML and extracts all anchors, local and remote links for the one file -def process_file(filetuple): - filename, relfilename = filetuple +def process_file(filename): tree = ET.parse(filename) root = tree.getroot() + docname = root.get('data-sourcedoc') - anchors = [relfilename] + if not docname: + docname = filename + + anchors = [filename] targets = [] for elem in root.findall('.//html:a', ns): @@ -66,30 +60,30 @@ def process_file(filetuple): an = elem.get('id') if an: - anchors.append(relfilename + '#' + an) + anchors.append(filename + '#' + an) if target: if re.search('://', target): externallinks.append(target) elif target[0] != '#' and 'mailto:' not in target: - dirname = os.path.dirname(relfilename) - targetname = os.path.normpath(os.path.join(dirname, target)) + dirname = os.path.dirname(filename) + targetfull = os.path.normpath(os.path.join(dirname, target)) - targets.append((targetname, filename, target)) + targets.append((filename, docname, targetfull, target)) # older docutils generate "<div class='section'" for elem in root.findall('.//html:div/[@class=\'section\']', ns): an = elem.get('id') if an: - anchors.append(relfilename + '#' + an) + anchors.append(filename + '#' + an) # modern docutils generate a <section element for elem in root.findall('.//html:section', ns): an = elem.get('id') if an: - anchors.append(relfilename + '#' + an) + anchors.append(filename + '#' + an) return (anchors, targets) @@ -98,8 +92,8 @@ def process_all(filelist): anchors = [] targets = [] - for filetuple in filelist: - anchor, target = process_file(filetuple) + for file in filelist: + anchor, target = process_file(file) targets = targets + target anchors = anchors + anchor @@ -109,17 +103,15 @@ def process_all(filelist): def check_targets(targets, anchors): errors = [] - for target, targetfrom, targetorig in targets: + for _, docname, target, targetorig in targets: if target not in anchors: - errors.append((targetfrom, targetorig)) + errors.append((docname, targetorig)) if errors: errors.sort() - print('broken link targets:') - for file, target in errors: - print(file + " broken link: " + target) + print(f'ERROR: \'{file}\': broken link to: \'{target}\'') return True @@ -134,7 +126,7 @@ parser.add_argument('--external', action="store_true", args = parser.parse_args() -files = get_file_list(args.webroot) +files = get_file_list(os.path.abspath(args.webroot)) targets, anchors = process_all(files) -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:11PM +0100, Peter Krempa wrote:
Now that we have the source file name as a custom attribute we can use it to report which file actually needs to be edited to fix the error:
ERROR: 'docs/uri.rst': broken link to: 'drvqemu.html#exaple'
rather than:
broken link targets: docs/uri.html broken link: drvqemu.html#exaple
which pointed to file which does not exist in the source directory.
This also allows us to delete all the relative path handling needed to report at least somewhat user-legible errors before.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- scripts/check-html-references.py | 46 +++++++++++++------------------- 1 file changed, 19 insertions(+), 27 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

The manpages for 'virt-pki-query-dn', 'virt-qemu-qmp-proxy' and 'virt-ssh-helper.rst' were not referenced from the manpage index or any other place. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/manpages/index.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/manpages/index.rst b/docs/manpages/index.rst index 8fd0d90041..e28c8e2f54 100644 --- a/docs/manpages/index.rst +++ b/docs/manpages/index.rst @@ -42,6 +42,9 @@ Tools * `virsh(1) <virsh.html>`__ - management user interface * `virt-qemu-run(1) <virt-qemu-run.html>`__ - run standalone QEMU instances * `libvirt-guests(8) <libvirt-guests.html>`__ - suspend/resume running libvirt guests +* `virt-pki-query-dn(1) <virt-pki-query-dn.html>`__ - extract Distinguished Name from a PEM certificate +* `virt-ssh-helper(8) <virt-ssh-helper.html>`__ - libvirt socket proxy (internal helper tool) +* `virt-qemu-qmp-proxy(1) <virt-qemu-qmp-proxy.html>`__ - Expose a QMP proxy server for a libvirt QEMU guest Key codes ========= -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:12PM +0100, Peter Krempa wrote:
The manpages for 'virt-pki-query-dn', 'virt-qemu-qmp-proxy' and 'virt-ssh-helper.rst' were not referenced from the manpage index or any other place.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/manpages/index.rst | 3 +++ 1 file changed, 3 insertions(+)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Our documentation has pages for 4 go modules, 2 current and 2 obsolete ones, but points only to one of them and directly to golang's docs page. Add a sub-page where all 4 sub-pages for the modules are linked. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/docs.rst | 2 +- docs/golang.rst | 21 +++++++++++++++++++++ docs/meson.build | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 docs/golang.rst diff --git a/docs/docs.rst b/docs/docs.rst index a826bd128c..855ce6a069 100644 --- a/docs/docs.rst +++ b/docs/docs.rst @@ -79,7 +79,7 @@ Application development `Language bindings and API modules <bindings.html>`__ Bindings of the libvirt API for `c# <csharp.html>`__, - `go <https://pkg.go.dev/libvirt.org/go/libvirt>`__, + `go <https://pkg.go.dev/libvirt.org/go/libvirt>`__ (`all go modules <golang.html>`__), `java <java.html>`__, `ocaml <https://libvirt.org/ocaml/>`__, `perl <https://search.cpan.org/dist/Sys-Virt/>`__, diff --git a/docs/golang.rst b/docs/golang.rst new file mode 100644 index 0000000000..77821cee24 --- /dev/null +++ b/docs/golang.rst @@ -0,0 +1,21 @@ +==================== +Go Language bindings +==================== + +Modern libvirt API bindings with Go modules +------------------------------------------- + +The libvirt API bindings package and module for XML manipulation: + + - `libvirt.org/go/libvirt <go/libvirt.html>`__ package https://pkg.go.dev/libvirt.org/go/libvirt + - `libvirt.org/go/libvirtxml <go/libvirtxml.html>`__ package https://pkg.go.dev/libvirt.org/go/libvirtxml + + +Obsolete libvirt language bindings +---------------------------------- + +The following two go packages were superseded, but software currently using them +No further development will take place. + + - `libvirt.org/libvirt-go <libvirt-go.html>`__ - CGo binding to the native API + - `libvirt.org/libvirt-go-xml <libvirt-go-xml.html>`)) - annotated Go struct definitions for XML handling diff --git a/docs/meson.build b/docs/meson.build index 5ffd39c01b..a90c59866a 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -80,6 +80,7 @@ docs_rst_files = [ 'formatstorageencryption', 'glib-adoption', 'goals', + 'golang', 'governance', 'hacking', 'hooks', -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:13PM +0100, Peter Krempa wrote:
Our documentation has pages for 4 go modules, 2 current and 2 obsolete ones, but points only to one of them and directly to golang's docs page.
Add a sub-page where all 4 sub-pages for the modules are linked.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/docs.rst | 2 +- docs/golang.rst | 21 +++++++++++++++++++++ docs/meson.build | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 docs/golang.rst
diff --git a/docs/golang.rst b/docs/golang.rst new file mode 100644 index 0000000000..77821cee24 --- /dev/null +++ b/docs/golang.rst @@ -0,0 +1,21 @@ +==================== +Go Language bindings +==================== + +Modern libvirt API bindings with Go modules +------------------------------------------- + +The libvirt API bindings package and module for XML manipulation: + + - `libvirt.org/go/libvirt <go/libvirt.html>`__ package https://pkg.go.dev/libvirt.org/go/libvirt + - `libvirt.org/go/libvirtxml <go/libvirtxml.html>`__ package https://pkg.go.dev/libvirt.org/go/libvirtxml + + +Obsolete libvirt language bindings +---------------------------------- + +The following two go packages were superseded, but software currently using them
Missing words at the end
+No further development will take place. + + - `libvirt.org/libvirt-go <libvirt-go.html>`__ - CGo binding to the native API + - `libvirt.org/libvirt-go-xml <libvirt-go-xml.html>`)) - annotated Go struct definitions for XML handling
If that above is fixed in some obvious manner Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Prevent sub-pages without a way to reach them. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- scripts/check-html-references.py | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/scripts/check-html-references.py b/scripts/check-html-references.py index 8e726928e0..4f08feab59 100755 --- a/scripts/check-html-references.py +++ b/scripts/check-html-references.py @@ -40,6 +40,8 @@ def get_file_list(prefix): filelist.append(os.path.join(root, file)) + filelist.sort() + return filelist @@ -118,9 +120,54 @@ def check_targets(targets, anchors): return False +def check_usage_crawl(page, targets, visited): + visited.append(page) + + tocrawl = [] + + for filename, docname, target, _ in targets: + if page != filename: + continue + + targetpage = target.split("#", 1)[0] + + if targetpage not in visited and targetpage not in tocrawl: + tocrawl.append(targetpage) + + for crawl in tocrawl: + check_usage_crawl(crawl, targets, visited) + + +# crawls the document references starting from entrypoint and tries to find +# unreachable pages +def check_usage(targets, files, entrypoint): + visited = [] + fail = False + + check_usage_crawl(entrypoint, targets, visited) + + for file in files: + if file not in visited: + brokendoc = file + + for filename, docname, _, _ in targets: + if filename != file: + continue + if docname: + brokendoc = docname + break + + print(f'ERROR: \'{brokendoc}\': is not referenced from anywhere') + fail = True + + return fail + + parser = argparse.ArgumentParser(description='HTML reference checker') parser.add_argument('--webroot', required=True, help='path to the web root') +parser.add_argument('--entrypoint', default="index.html", + help='file name of web entry point relative to --webroot') parser.add_argument('--external', action="store_true", help='print external references instead') @@ -128,8 +175,12 @@ args = parser.parse_args() files = get_file_list(os.path.abspath(args.webroot)) +entrypoint = os.path.join(os.path.abspath(args.webroot), args.entrypoint) + targets, anchors = process_all(files) +fail = False + if args.external: prev = None externallinks.sort() @@ -140,6 +191,12 @@ if args.external: prev = ext else: if check_targets(targets, anchors): + fail = True + + if check_usage(targets, files, entrypoint): + fail = True + + if fail: sys.exit(1) sys.exit(0) -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:14PM +0100, Peter Krempa wrote:
Prevent sub-pages without a way to reach them.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- scripts/check-html-references.py | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

The images are referenced from '../images/' but the document is two layers deep thus '../../images' needs to be used Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/kbase/internals/eventloop.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/kbase/internals/eventloop.rst b/docs/kbase/internals/eventloop.rst index 856cabc85f..c7770614a1 100644 --- a/docs/kbase/internals/eventloop.rst +++ b/docs/kbase/internals/eventloop.rst @@ -23,7 +23,7 @@ desired function. If generalized, this is how many long running programs (daemons) work. Even those who are not waiting for direct user input and have no graphical interface. Such as Libvirt. -.. image:: ../images/event_loop_simple.png +.. image:: ../../images/event_loop_simple.png :alt: event loop In Libvirt this approach is used in combination with ``poll(2)`` as all the @@ -57,7 +57,7 @@ a message event loop is blocked and for an outside observer unresponsive. This is not acceptable for Libvirt. Therefore we have came up with the following solution. -.. image:: ../images/event_loop_worker.png +.. image:: ../../images/event_loop_worker.png :alt: event loop The event loop does only necessary minimum and hand over message processing to -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:15PM +0100, Peter Krempa wrote:
The images are referenced from '../images/' but the document is two layers deep thus '../../images' needs to be used
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/kbase/internals/eventloop.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

The logo directory wasn't really referenced from anywhere. Additionally there wasn't any reasonable index for all the image files which we have. Turn the README file into rST and display the images it references. Link to the new index file from the docs page. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/docs.rst | 3 + docs/logos/README | 98 ------------------------ docs/logos/README.rst | 166 +++++++++++++++++++++++++++++++++++++++++ docs/logos/meson.build | 47 ++++++++++++ 4 files changed, 216 insertions(+), 98 deletions(-) delete mode 100644 docs/logos/README create mode 100644 docs/logos/README.rst diff --git a/docs/docs.rst b/docs/docs.rst index 855ce6a069..ea14555575 100644 --- a/docs/docs.rst +++ b/docs/docs.rst @@ -163,3 +163,6 @@ Project development `New repo setup <newreposetup.html>`__ Procedure for configuring new git repositories for libvirt + +`Libvirt logos <logos/index.html>`__ + Libvirt logo files and guideline how to use them diff --git a/docs/logos/README b/docs/logos/README deleted file mode 100644 index 64dee41ec8..0000000000 --- a/docs/logos/README +++ /dev/null @@ -1,98 +0,0 @@ - Libvirt Logo README - =================== - -The master SVG files were created in InkScape, using the Overpass font from Red -Hat: - - https://overpassfont.org/ - - -Logo formats -============ - -The following SVG files are provided, along with standard bitmap sizes in PNG -format: - - - logo-base.svg - - The basic "sardine tin" graphic used to create the other forms of the - libvirt logo. - - The tin is rotated by 20 degrees, so its angle matches the angle of the left - side of the letter "v" in the Overpass font - - Never use this logo file directly. It exists merely as a base for building - the other logos - - - - logo-square.svg - - The minimal square format logo for libvirt. Simply embeds the word "libvirt" - into the basic logo graphic. - - This is intended for use where a compact, square format representation of - the logo is required. - - Bitmap sizes: 64, 128, 192, 256 px square - - - - logo-square-powered.svg - - A variant of the square logo for use by 3rd party applications, to advertise - their use of libvirt. - - Bitmap sizes: 64, 128, 192, 256 px square - - - - logo-banner-light.svg - - A wide banner format of the logo. Embeds the words "libvirt virtualization - API" into the basic logo graphic. The text is rendered in a light color, so - suitable for placement over a dark background. - - Bitmap sizes: 257x92, 800x286 px - - - - logo-banner-dark.svg - - A wide banner format of the logo. Embeds the words "libvirt virtualization - API" into the basic logo graphic. The text is rendered in a dark color, so - suitable for placement over a light background. - - Bitmap sizes: 257x92, 800x286 px - - - - logo-sticker-square.svg - - A logo formatted into a square shape with outline, suitable for printing - as a sticker. See https://github.com/terinjokes/StickerConstructorSpec - - - - logo-sticker-hexagon.svg - - A logo formatted into a hexagon shape with outline, suitable for printing - as a sticker. See https://github.com/terinjokes/StickerConstructorSpec - - -PNG file creation -================= - -The bitmap images should not be created in Inkscape, since its anti-aliasing of -the rendered bitmaps is too aggressive, resulting in fuzzy images. Instead the -GIMP is used to create bitmaps as follows: - - - File -> Open, select the SVG file - - When prompted for the image size, enter 1024 as the width and allow height - to be auto-set based on aspect ratio - - - Image -> Scale Image - - Enter desired final bitmap size and use "Cubic" as scaling method. - - - File -> Export As - - -It is important to let GIMP render initially at 1024 and then scale down, rather -than rendering directly at the target size, since this the manual scaling step -produces better quality diff --git a/docs/logos/README.rst b/docs/logos/README.rst new file mode 100644 index 0000000000..4b03d3aad1 --- /dev/null +++ b/docs/logos/README.rst @@ -0,0 +1,166 @@ +=================== +Libvirt Logo README +=================== + +The master SVG files were created in InkScape, using the Overpass font from Red +Hat: + + https://overpassfont.org/ + + +.. contents:: + + +Logo formats +============ + +The following SVG files are provided, along with standard bitmap sizes in PNG +format: + +``logo-base.svg`` +----------------- + +.. image:: logo-base.svg + +The basic "sardine tin" graphic used to create the other forms of the +libvirt logo. + +The tin is rotated by 20 degrees, so its angle matches the angle of the left +side of the letter "v" in the Overpass font + +Never use this logo file directly. It exists merely as a base for building +the other logos + +``logo-square.svg`` +------------------- + +.. image:: logo-square.svg + +The minimal square format logo for libvirt. Simply embeds the word "libvirt" +into the basic logo graphic. + +This is intended for use where a compact, square format representation of +the logo is required. + +Bitmap sizes: 96, 128, 192, 256 px square + +- 96px: + +.. image:: logo-square-96.png + +- 128px: + +.. image:: logo-square-128.png + +- 192px: + +.. image:: logo-square-192.png + +- 256px: + +.. image:: logo-square-256.png + + + +``logo-square-powered.svg`` +--------------------------- + +.. image:: logo-square-powered.svg + +A variant of the square logo for use by 3rd party applications, to advertise +their use of libvirt. + +Bitmap sizes: 96, 128, 192, 256 px square + +- 96px: + +.. image:: logo-square-powered-96.png + +- 128px: + +.. image:: logo-square-powered-128.png + +- 192px: + +.. image:: logo-square-powered-192.png + +- 256px: + +.. image:: logo-square-powered-256.png + +``logo-banner-light.svg`` +------------------------- + +.. image:: logo-banner-light.svg + +A wide banner format of the logo. Embeds the words "libvirt virtualization +API" into the basic logo graphic. The text is rendered in a light color, so +suitable for placement over a dark background. + +Bitmap sizes: 256x92, 800x286 px + +- 256x92px: + +.. image:: logo-banner-light-256.png + +- 800x286px: + +.. image:: logo-banner-light-800.png + +``logo-banner-dark.svg`` +------------------------ + +.. image:: logo-banner-dark.svg + +A wide banner format of the logo. Embeds the words "libvirt virtualization +API" into the basic logo graphic. The text is rendered in a dark color, so +suitable for placement over a light background. + +Bitmap sizes: 256x92, 800x286 px + +- 256x92px: + +.. image:: logo-banner-dark-256.png + +- 800x286px: + +.. image:: logo-banner-dark-800.png + +``logo-sticker-square.svg`` +--------------------------- + +.. image:: logo-sticker-square.svg + +A logo formatted into a square shape with outline, suitable for printing +as a sticker. See https://github.com/terinjokes/StickerConstructorSpec + +``logo-sticker-hexagon.svg`` +---------------------------- + +.. image:: logo-sticker-hexagon.svg + +A logo formatted into a hexagon shape with outline, suitable for printing +as a sticker. See https://github.com/terinjokes/StickerConstructorSpec + +PNG file creation +================= + +The bitmap images should not be created in Inkscape, since its anti-aliasing of +the rendered bitmaps is too aggressive, resulting in fuzzy images. Instead the +GIMP is used to create bitmaps as follows: + + - File -> Open, select the SVG file + + When prompted for the image size, enter 1024 as the width and allow height + to be auto-set based on aspect ratio + + - Image -> Scale Image + + Enter desired final bitmap size and use "Cubic" as scaling method. + + - File -> Export As + + +It is important to let GIMP render initially at 1024 and then scale down, rather +than rendering directly at the target size, since this the manual scaling step +produces better quality diff --git a/docs/logos/meson.build b/docs/logos/meson.build index 70ba67d71c..c65fcdd8ed 100644 --- a/docs/logos/meson.build +++ b/docs/logos/meson.build @@ -29,3 +29,50 @@ foreach file : docs_logo_files install_web_files += '@0@:@1@'.format(meson.current_source_dir() / file, docs_html_dir / 'logos') endforeach + + +html_xslt_gen_install_dir = docs_html_dir / 'logos' +html_xslt_gen = [] + +# README.rst is formatted as index.html for viewing +html_xslt_gen += { + 'name': 'index', + 'file': docs_rst2html5_gen.process('README.rst'), + 'source': 'docs' / 'logos' / 'README.rst', + 'href_base': '../', +} + + +# --- begin of XSLT processing --- + +foreach data : html_xslt_gen + html_filename = data['name'] + '.html' + + html_file = custom_target( + html_filename, + input: data.get('file', data['name'] + '.html.in'), + output: html_filename, + command: [ + xsltproc_prog, + '--stringparam', 'pagesrc', data.get('source', ''), + '--stringparam', 'builddir', meson.project_build_root(), + '--stringparam', 'timestamp', docs_timestamp, + '--stringparam', 'href_base', data.get('href_base', ''), + '--nonet', + site_xsl, + '@INPUT@', + ], + depends: data.get('depends', []), + depend_files: [ page_xsl ], + capture: true, + install: true, + install_dir: html_xslt_gen_install_dir, + ) + + install_web_deps += html_file + install_web_files += html_file.full_path() + ':' + html_xslt_gen_install_dir +endforeach + +html_xslt_gen = [] + +# --- end of XSLT processing --- -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:16PM +0100, Peter Krempa wrote:
The logo directory wasn't really referenced from anywhere. Additionally there wasn't any reasonable index for all the image files which we have.
Turn the README file into rST and display the images it references. Link to the new index file from the docs page.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/docs.rst | 3 + docs/logos/README | 98 ------------------------ docs/logos/README.rst | 166 +++++++++++++++++++++++++++++++++++++++++ docs/logos/meson.build | 47 ++++++++++++ 4 files changed, 216 insertions(+), 98 deletions(-) delete mode 100644 docs/logos/README create mode 100644 docs/logos/README.rst
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Check both that a file is referenced from our pages and also that pages reference existing images. The mode for dumping external references now also dumps images. '--ignore-image' can be used repeatedly to suppress errors for specific images. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- scripts/check-html-references.py | 101 ++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 14 deletions(-) diff --git a/scripts/check-html-references.py b/scripts/check-html-references.py index 4f08feab59..788622a2d0 100755 --- a/scripts/check-html-references.py +++ b/scripts/check-html-references.py @@ -24,25 +24,32 @@ import xml.etree.ElementTree as ET ns = {'html': 'http://www.w3.org/1999/xhtml'} externallinks = [] +externalimages = [] def get_file_list(prefix): filelist = [] + imagelist = [] + imageformats = ['.jpg', '.svg', '.png'] for root, dir, files in os.walk(prefix): for file in files: - if not re.search('\\.html$', file): - continue + ext = os.path.splitext(file)[1] - # the 404 page doesn't play well - if '404.html' in file: - continue + if ext == '.html': + # the 404 page doesn't play well + if '404.html' in file: + continue + + filelist.append(os.path.join(root, file)) - filelist.append(os.path.join(root, file)) + elif ext in imageformats: + imagelist.append(os.path.join(root, file)) filelist.sort() + imagelist.sort() - return filelist + return filelist, imagelist # loads an XHTML and extracts all anchors, local and remote links for the one file @@ -50,12 +57,14 @@ def process_file(filename): tree = ET.parse(filename) root = tree.getroot() docname = root.get('data-sourcedoc') + dirname = os.path.dirname(filename) if not docname: docname = filename anchors = [filename] targets = [] + images = [] for elem in root.findall('.//html:a', ns): target = elem.get('href') @@ -68,7 +77,6 @@ def process_file(filename): if re.search('://', target): externallinks.append(target) elif target[0] != '#' and 'mailto:' not in target: - dirname = os.path.dirname(filename) targetfull = os.path.normpath(os.path.join(dirname, target)) targets.append((filename, docname, targetfull, target)) @@ -87,20 +95,33 @@ def process_file(filename): if an: anchors.append(filename + '#' + an) - return (anchors, targets) + # find local images + for elem in root.findall('.//html:img', ns): + src = elem.get('src') + + if src: + if re.search('://', src): + externalimages.append(src) + else: + imagefull = os.path.normpath(os.path.join(dirname, src)) + images.append((imagefull, docname)) + + return (anchors, targets, images) def process_all(filelist): anchors = [] targets = [] + images = [] for file in filelist: - anchor, target = process_file(file) + anchor, target, image = process_file(file) targets = targets + target anchors = anchors + anchor + images = images + image - return (targets, anchors) + return (targets, anchors, images) def check_targets(targets, anchors): @@ -163,6 +184,46 @@ def check_usage(targets, files, entrypoint): return fail +# checks that images present in the directory are being used and also that +# pages link to existing images. For favicons, which are not referenced from +# the '.html' files there's a builtin set of exceptions. +def check_images(usedimages, imagefiles, ignoreimages): + favicons = [ + 'android-chrome-192x192.png', + 'android-chrome-256x256.png', + 'apple-touch-icon.png', + 'favicon-16x16.png', + 'favicon-32x32.png', + 'mstile-150x150.png', + ] + fail = False + + if ignoreimages: + favicons = favicons + ignoreimages + + for usedimage, docname in usedimages: + if usedimage not in imagefiles: + print(f'ERROR: \'{docname}\' references image \'{usedimage}\' not among images') + fail = True + + for imagefile in imagefiles: + used = False + + if imagefile in (usedimage[0] for usedimage in usedimages): + used = True + else: + for favicon in favicons: + if favicon in imagefile: + used = True + break + + if not used: + print(f'ERROR: Image \'{imagefile}\' is not used by any page') + fail = True + + return fail + + parser = argparse.ArgumentParser(description='HTML reference checker') parser.add_argument('--webroot', required=True, help='path to the web root') @@ -170,14 +231,16 @@ parser.add_argument('--entrypoint', default="index.html", help='file name of web entry point relative to --webroot') parser.add_argument('--external', action="store_true", help='print external references instead') +parser.add_argument('--ignore-images', action='append', + help='paths to images that should be considered as used') args = parser.parse_args() -files = get_file_list(os.path.abspath(args.webroot)) +files, imagefiles = get_file_list(os.path.abspath(args.webroot)) entrypoint = os.path.join(os.path.abspath(args.webroot), args.entrypoint) -targets, anchors = process_all(files) +targets, anchors, usedimages = process_all(files) fail = False @@ -186,7 +249,14 @@ if args.external: externallinks.sort() for ext in externallinks: if ext != prev: - print(ext) + print(f'link: {ext}') + + prev = ext + + externalimages.sort() + for ext in externalimages: + if ext != prev: + print(f'image: {ext}') prev = ext else: @@ -196,6 +266,9 @@ else: if check_usage(targets, files, entrypoint): fail = True + if check_images(usedimages, imagefiles, args.ignore_images): + fail = True + if fail: sys.exit(1) -- 2.39.1

On Tue, Feb 14, 2023 at 10:51:17PM +0100, Peter Krempa wrote:
Check both that a file is referenced from our pages and also that pages reference existing images.
The mode for dumping external references now also dumps images.
'--ignore-image' can be used repeatedly to suppress errors for specific images.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- scripts/check-html-references.py | 101 ++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 14 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
participants (2)
-
Daniel P. Berrangé
-
Peter Krempa