From 4a52556ba69c6ea6b954b3ab839c789a4c889f14 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 12:36:54 +0200 Subject: [PATCH 01/18] Copy from offline prototype --- doc/adoc/mysql/antora.yml | 5 + doc/adoc/mysql/modules/ROOT/nav.adoc | 4 + doc/adoc/mysql/modules/ROOT/pages/index.adoc | 105 ++ .../mysql/modules/ROOT/pages/overview.adoc | 3 + doc/docca-asciidoc/docca_asciidoc.py | 1407 ++++++++++++++ doc/docca-asciidoc/templates/class.jinja2 | 72 + doc/docca-asciidoc/templates/common.jinja2 | 171 ++ doc/docca-asciidoc/templates/enum.jinja2 | 34 + .../templates/overload-set.jinja2 | 80 + doc/docca-asciidoc/templates/quickref.jinja2 | 42 + .../templates/type-alias.jinja2 | 17 + doc/supplemental-ui/css/custom.css | 146 ++ doc/supplemental-ui/partials/head-styles.hbs | 2 + package-lock.json | 1616 +++++++++++++++++ package.json | 6 + site.playbook.yml | 32 + 16 files changed, 3742 insertions(+) create mode 100644 doc/adoc/mysql/antora.yml create mode 100644 doc/adoc/mysql/modules/ROOT/nav.adoc create mode 100644 doc/adoc/mysql/modules/ROOT/pages/index.adoc create mode 100644 doc/adoc/mysql/modules/ROOT/pages/overview.adoc create mode 100755 doc/docca-asciidoc/docca_asciidoc.py create mode 100644 doc/docca-asciidoc/templates/class.jinja2 create mode 100644 doc/docca-asciidoc/templates/common.jinja2 create mode 100644 doc/docca-asciidoc/templates/enum.jinja2 create mode 100644 doc/docca-asciidoc/templates/overload-set.jinja2 create mode 100644 doc/docca-asciidoc/templates/quickref.jinja2 create mode 100644 doc/docca-asciidoc/templates/type-alias.jinja2 create mode 100644 doc/supplemental-ui/css/custom.css create mode 100644 doc/supplemental-ui/partials/head-styles.hbs create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 site.playbook.yml diff --git a/doc/adoc/mysql/antora.yml b/doc/adoc/mysql/antora.yml new file mode 100644 index 000000000..66a9afb8d --- /dev/null +++ b/doc/adoc/mysql/antora.yml @@ -0,0 +1,5 @@ +name: mysql +title: Boost.MySQL +version: ~ +nav: + - modules/ROOT/nav.adoc diff --git a/doc/adoc/mysql/modules/ROOT/nav.adoc b/doc/adoc/mysql/modules/ROOT/nav.adoc new file mode 100644 index 000000000..1fdce5430 --- /dev/null +++ b/doc/adoc/mysql/modules/ROOT/nav.adoc @@ -0,0 +1,4 @@ +* xref:index.adoc[Introduction] +* xref:overview.adoc[] +* xref:reference.adoc[] + diff --git a/doc/adoc/mysql/modules/ROOT/pages/index.adoc b/doc/adoc/mysql/modules/ROOT/pages/index.adoc new file mode 100644 index 000000000..b4d46cc64 --- /dev/null +++ b/doc/adoc/mysql/modules/ROOT/pages/index.adoc @@ -0,0 +1,105 @@ + +[#intro] += Introduction + +Boost.MySQL is a pass:[C++11] client for the https://www.mysql.com/[MySQL] and https://mariadb.com/[MariaDB] database servers, based on Boost.Asio. + +== Motivation + +MySQL and MariaDB are widespread SQL database servers. MySQL +clients connect to the server in order to issue SQL queries. For this +purpose, MySQL employs a dedicated protocol. Boost.MySQL is an +implementation of the client side of this protocol. + +This library is a full implementation of the +https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_PROTOCOL.html[MySQL client/server protocol]. +It aims to expose the protocol primitives in an efficient but easy-to-use way. +It is similar in scope to the official https://dev.mysql.com/doc/c-api/8.0/en/[libmysqlclient], +but interoperable with Asio, safer and more expressive. Note that Boost.MySQL +*does not use libmysqlclient*: it's a full implementation of the MySQL protocol, which makes +it natively compatible with Asio. + +This library is relatively low level. It gives you access to text SQL queries and +prepared statements. Don't expect an ORM. xref:overview.adoc[This section] presents a quick tour +over the main library capabilities. + +The design goals of this library are: + +- *Interoperability with Asio*: this library employs the same principles as Boost.Asio and Boost.Beast. + Users of any of these libraries will immediately understand Boost.MySQL, and will have it easy + to integrate it in their programs. +* *Basis for further abstraction*: it allows efficient access to the MySQL client/server protocol + so it can be used by higher level components as a building block. Do a single thing and do it well. +* *Efficiency*. +* *Ease of use*: the MySQL protocol is full of pitfalls. We believe in simplicity. While retaining + control over the important parts, the library hides as much complexity from the protocol as possible. + +Non-goals: + +* *Being an ORM*. +* *Portability to other SQL databases*. This library focuses on MySQL. It won't work with Postgres + or SQLite. + +== When to use + +If any of the following statements is true, you may consider using Boost.MySQL: + +* Your application uses Boost.Asio and you need to access a MySQL server. +* You need asynchronous access to a MySQL server from a pass:[C++] application. +* You need efficient access to a MySQL server from a pass:[C++] application. +* You need a BSL-licensed library to access your MySQL server. +* You are writing a higher-level database access library, like an ORM. + +Use cases may include web servers, ETL processes and IoT systems. + +It may not be a good fit for you if: + +* You only need synchronous access to a MySQL server and efficiency doesn't matter + to your application. The official client libraries may be better suited for you, in this case. +* You need homogeneous SQL access to different SQL databases (and not only MySQL access). + You may find more value in using https://github.com/rbock/sqlpp11[sqlpp11] or a similar wrapper + library. + + + +== Tested compilers and systems + +Boost.MySQL is tested under the following compilers: + +* gcc 5.4 (Linux) +* gcc 6.5 (Linux) +* gcc 10.3 (Linux) +* gcc 11.2 (Linux) +* gcc 13.0 (Linux) +* gcc 14.0 (Linux) +* clang 3.6 (Linux) +* clang 7.0 (Linux) +* clang 11.0 (Linux) +* clang 14.0 (Linux) +* clang 16.0 (Linux) +* clang 17.0 (Linux) +* clang 18.0 (Linux) +* Apple clang 14.0 (OSX) +* MSVC 14.1 - Visual Studio 2017 (Windows) +* MSVC 14.2 - Visual Studio 2019 (Windows) +* MSVC 14.3 - Visual Studio 2022 (Windows) + +And with the following RDBMS systems: + +* MySQL v5.7.41. +* MySQL v8.4.1. +* MariaDB v11.4.2. + +== Acknowledgements + +I would like to specially acknowledge https://github.com/madmongo1[Richard Hodges] (hodges.r@gmail.com) +for his invaluable technical guidance during development. Thanks also to +Christian Mazakas for his ideas in early stages, and to +https://github.com/klemens-morgenstern[Klemens Morgenstern] and +and https://github.com/vinniefalco[Vinnie Falco] for his techincal advice. +Without you, this library would not exist. + +Finally, thanks to https://github.com/chriskohlhoff[Christopher Kohlhoff] +for his awesome Asio library, and to https://github.com/HowardHinnant[Howard Hinnant] +for his date algorithms, shamelessly copied in this lib. + diff --git a/doc/adoc/mysql/modules/ROOT/pages/overview.adoc b/doc/adoc/mysql/modules/ROOT/pages/overview.adoc new file mode 100644 index 000000000..4b478055c --- /dev/null +++ b/doc/adoc/mysql/modules/ROOT/pages/overview.adoc @@ -0,0 +1,3 @@ += Overview + +Under construction \ No newline at end of file diff --git a/doc/docca-asciidoc/docca_asciidoc.py b/doc/docca-asciidoc/docca_asciidoc.py new file mode 100755 index 000000000..ff6962de6 --- /dev/null +++ b/doc/docca-asciidoc/docca_asciidoc.py @@ -0,0 +1,1407 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2024 Dmitry Arkhipov (grisumbras@yandex.ru) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/json +# + +import argparse +import jinja2 +import json +import io +import os.path +import sys +import xml.etree.ElementTree as ET +from typing import Dict, Optional, List as PyList +from os import makedirs + +class Nullcontext(): + def __init__(self): + pass + + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_value, traceback): + pass + + +class Access: + public = 'public' + protected = 'protected' + private = 'private' + +class FunctionKind: + static = 'static' + nonstatic = 'nonstatic' + friend = 'friend' + free = 'free' + +class VirtualKind: + nonvirtual = 'non-virtual' + purevirtual = 'pure-virtual' + virtual = 'virtual' + + +class Linebreak(): + pass + +class PhraseContainer: + def __init__(self, parts): + self._parts = parts + + def __getitem__(self, pos): + return self._parts[pos] + + def __setitem__(self, pos, val): + self._parts[pos] = val + + def __len__(self): + return len(self._parts) + +class Phrase(PhraseContainer): + @property + def text(self): + return ''.join(( + part if isinstance(part, str) + else '' if isinstance(part, Linebreak) + else part.text + for part in self + )) + +class Emphasised(Phrase): + pass + +class Monospaced(Phrase): + pass + +class Strong(Phrase): + pass + +class EntityRef(Phrase): + def __init__(self, entity, parts): + super().__init__(parts) + self.entity = entity + + @property + def text(self): + result = super().text + if not result: + result = self.entity.fully_qualified_name + return result + +class UrlLink(Phrase): + def __init__(self, url, parts): + super().__init__(parts) + self.url = url + assert url + + @property + def text(self): + result = super().text + if not result: + result = self.url + return result + + +class Block: + pass + +class Paragraph(PhraseContainer, Block): + def __init__(self, parts): + super().__init__(parts) + + def __getitem__(self, pos): + return self._parts[pos] + + def __len__(self): + return len(self._parts) + + @property + def text(self): + return ''.join([ + (p if isinstance(p, str) else p.text) for p in self._parts + ]) + +class List(Block): + Arabic = '1' + LowerLatin = 'a' + UpperLatin = 'A' + LowerRoman = 'i' + UpperRoman = 'I' + + def __init__(self, kind, items): + self.kind = kind + self.is_ordered = kind is not None + self._items = items + + def __getitem__(self, pos): + return self._items[pos] + + def __len__(self): + return len(self._items) + +class ListItem(Block): + def __init__(self, blocks): + assert blocks + self._blocks = blocks + + def __getitem__(self, pos): + return self._blocks[pos] + + def __len__(self): + return len(self.blocks) + +class Section(Block): + See = 'see' + Returns = 'return' + Author = 'author' + Authors = 'authors' + Version = 'version' + Since = 'since' + Date = 'date' + Note = 'note' + Warning = 'warning' + Preconditions = 'pre' + Postconditions = 'post' + Copyright = 'copyright' + Invariants = 'invariant' + Remarks = 'remark' + Attention = 'attention' + Custom = 'par' + RCS = 'rcs' + + def __init__(self, kind, title, blocks): + self.kind = kind + self.title = title + self._blocks = blocks + + def __getitem__(self, pos): + return self._blocks[pos] + + def __len__(self): + return len(self._blocks) + +class ParameterList(Block): + Parameters = 'param' + ReturnValues = 'retval' + Exceptions = 'exception' + TemplateParameters = 'templateparam' + + def __init__(self, kind, items): + self.kind = kind + self._items = items + + def __getitem__(self, pos): + return self._items[pos] + + def __len__(self): + return len(self._items) + +class ParameterDescription(Block): + def __init__(self, description, params): + self.description = description + self._params = params + + def __getitem__(self, pos): + return self._params[pos] + + def __len__(self): + return len(self._params) + +class ParameterItem(Block): + def __init__(self, type, name, direction): + self.type = type + self.name = name + self.direction = direction + + @property + def is_in(self): + return self.direction in ('in', 'inout') + + @property + def is_out(self): + return self.direction in ('out', 'inout') + +class CodeBlock(Block): + def __init__(self, lines): + self._lines = lines + + def __getitem__(self, pos): + return self._lines[pos] + + def __len__(self): + return len(self._lines) + +class Table(Block): + def __init__(self, cols, rows, caption=None, width=None): + self.cols = cols + self.width = width + self.caption = caption + self._rows = rows + + def __getitem__(self, pos): + return self._rows[pos] + + def __len__(self): + return len(self._rows) + +class Cell(Block): + def __init__( + self, blocks, + col_span=1, row_span=1, is_header=False, horizontal_align=None, + vertical_align=None, width=None, role=None + ): + self._blocks = blocks + + self.col_span = int(col_span or 1) + self.row_span = int(row_span or 1) + self.is_header = is_header or False + self.horizontal_align = horizontal_align + self.vertical_align = vertical_align + self.width = width + self.role = role + + def __getitem__(self, pos): + return self._blocks[pos] + + def __len__(self): + return len(self._blocks) + + +def make_blocks(element : Optional[ET.Element], index) -> PyList[Block]: + if element is None: + return [] + + result = [] + cur_para = [] + + def finish_paragraph(cur_para): + if cur_para: + if isinstance(cur_para[0], str): + cur_para[0] = cur_para[0].lstrip() + if not cur_para[0]: + cur_para = cur_para[1:] + if cur_para: + if isinstance(cur_para[-1], str): + cur_para[-1] = cur_para[-1].rstrip() + if not cur_para[-1]: + cur_para = cur_para[:-1] + + # spaces after linebreaks usually cause issues + for n in range(1, len(cur_para)): + if (isinstance(cur_para[n - 1], Linebreak) + and isinstance(cur_para[n], str)): + cur_para[n] = cur_para[n].lstrip() + + if cur_para: + result.append(Paragraph(cur_para)) + + return [] + + if element.text: + cur_para.append(remove_endlines(element.text)) + + for child in element: + func = { + 'itemizedlist': make_list, + 'simplesect': make_section, + 'programlisting': make_codeblock, + 'parameterlist': make_parameters, + 'table': make_table, + }.get(child.tag) + if func: + cur_para = finish_paragraph(cur_para) + result.append(func(child, index)) + elif child.tag == 'para': + cur_para = finish_paragraph(cur_para) + result.extend(make_blocks(child, index)) + else: + cur_para.append(make_phrase(child, index)) + if child.tail: + cur_para.append(remove_endlines(child.tail)) + + finish_paragraph(cur_para) + return result + +def make_list(element, index): + items = [] + for child in element: + assert child.tag == 'listitem' + items.append(make_blocks(child, index)) + return List(element.get('type'), items) + +def make_parameters(element, index): + result = [] + descr = None + kind = element.get('kind') + for descr_block in element: + assert descr_block.tag == 'parameteritem' + descr = None + params = [] + for item in descr_block: + if item.tag == 'parameterdescription': + assert descr == None + descr = item + continue + + assert item.tag == 'parameternamelist' + + name = item.find('parametername') + direction = name.get('direction') if name is not None else None + params.append( + ParameterItem( + text_with_refs(item.find('parametertype'), index), + text_with_refs(name, index), + direction)) + + assert descr is not None + result.append(ParameterDescription(make_blocks(descr, index), params)) + return ParameterList(kind, result) + +def make_section(element, index): + title = None + if len(element) and element[0].tag == 'title': + title = phrase_content(element[0], index) + title = Paragraph(title or []) + + kind = element.get('kind') + + parts = [] + for child in element: + if child.tag == 'para': + parts.extend(make_blocks(child, index)) + + return Section(kind, title, parts) + +def make_codeblock(element, index): + lines = [] + for line in element: + assert line.tag == 'codeline' + text = '' + for hl in line: + assert hl.tag == 'highlight' + if hl.text: + text += hl.text + + for part in hl: + if part.tag == 'sp': + text += ' ' + elif part.tag == 'ref': + text += part.text or '' + if part.tail: + text += part.tail + if hl.tail: + text += hl.tail + lines.append(text) + + return CodeBlock(lines) + +def make_table(element, index): + cols = element.get('cols') + + caption = None + if len(element) and element[0].tag == 'caption': + caption = phrase_content(element[0], index) + caption = Paragraph(caption or []) + + rows = [] + for row in element[(1 if caption else 0):]: + assert row.tag == 'row' + cells = [] + for cell in row: + cells.append(Cell( + make_blocks(cell, index), + col_span=cell.get('colspan'), + row_span=cell.get('rowspan'), + is_header=cell.get('thead'), + horizontal_align=cell.get('align'), + vertical_align=cell.get('valign'), + width=cell.get('width'), + role=cell.get('class'), + )) + rows.append(cells) + + return Table(cols, rows, caption) + +def phrase_content(element, index, allow_missing_refs=False): + if element is None: + return [] + + result = [] + if element.text: + result.append(remove_endlines(element.text)) + + for child in element: + result.append( + make_phrase(child, index, allow_missing_refs=allow_missing_refs)) + if child.tail: + result.append(remove_endlines(child.tail)) + + return result + +def make_phrase(element, index, allow_missing_refs=False): + func = { + 'bold': make_strong, + 'computeroutput': make_monospaced, + 'verbatim': make_monospaced, + 'emphasis': make_emphasised, + 'ulink': make_url_link, + 'linebreak': make_linebreak, + 'ref': make_entity_reference, + }[element.tag] + return func(element, index, allow_missing_refs=allow_missing_refs) + +def make_strong(element, index, allow_missing_refs=False): + return Strong( + phrase_content(element, index, allow_missing_refs=allow_missing_refs)) + +def make_monospaced(element, index, allow_missing_refs=False): + return Monospaced( + phrase_content(element, index, allow_missing_refs=allow_missing_refs)) + +def make_emphasised(element, index, allow_missing_refs=False): + return Emphasised( + phrase_content(element, index, allow_missing_refs=allow_missing_refs)) + +def make_url_link(element, index, allow_missing_refs=False): + return UrlLink( + element.get('url'), + phrase_content(element, index, allow_missing_refs=allow_missing_refs)) + +def make_linebreak(element, index, allow_missing_refs=None): + return Linebreak() + +def make_entity_reference( + element, index, refid=None, allow_missing_refs=False +): + refid = refid or element.get('refid') + assert refid + + target = index.get(refid) + if target: + return EntityRef( + target, + phrase_content( + element, index, allow_missing_refs=allow_missing_refs)) + + if allow_missing_refs: + return Phrase(phrase_content(element, index, allow_missing_refs=True)) + +def text_with_refs(element, index): + return Phrase(phrase_content(element, index, allow_missing_refs=True)) + +def resolve_type(element, index): + result = text_with_refs(element, index) + if ( + result + and isinstance(result[0], str) + and result[0].startswith('constexpr') + ): + result[0] = result[0][len('constexpr'):].lstrip() + return result + +_chartable = { + ord('\r'): None, + ord('\n'): None, +} +def remove_endlines(s): + return s.translate(_chartable) + + +class Location(): + def __init__(self, elem): + self.file = elem.get('file') + + self.line = elem.get('line') + if self.line: + self.line = int(self.line) + + self.column = elem.get('column') + if self.column : + self.column = int(self.column) + + +class Entity(): + access = Access.public + + nametag: str + + @staticmethod + def _sanitize_path_segment(s: str) -> str: + return s.replace("[", "-lb") \ + .replace("]", "-rb")\ + .replace("(", "-lp")\ + .replace(")", "-rp")\ + .replace("<=>", "-spshp")\ + .replace("->", "-arrow")\ + .replace("operator>", "operator-gt")\ + .replace("operator~", "operator-bnot")\ + .replace("=", "-eq")\ + .replace("!", "-not")\ + .replace("+", "-plus")\ + .replace("&", "-and")\ + .replace("|", "-or")\ + .replace("^", "-xor")\ + .replace("*", "-star")\ + .replace("/", "-slash")\ + .replace("%", "-mod")\ + .replace("<", "-lt")\ + .replace(">", "-gt")\ + .replace("~", "dtor-")\ + .replace(",", "-comma")\ + .replace(":", "-")\ + .replace(" ", "-") + + def __init__(self, element: ET.Element, scope, index=dict()): + self.id = element.get('id', '') + assert self.id + + self.scope = scope + + self.name = ''.join( element.find(self.nametag).itertext() ) + + self.groups = [] + + loc = element.find('location') + self._location = Location(loc) if (loc is not None) else None + + self._brief = element.find('briefdescription') + self._description = element.find('detaileddescription') + + self.index = index + index[self.id] = self + + + @property + def location(self): + return ( + self._location + or (self.scope.location if self.scope else None) + ) + + @property + def fully_qualified_name(self): + return '::'.join((c.name for c in self.path)) + + @property + def path(self): + result = self.scope.path if self.scope else [] + result.append(self) + return result + + def lookup(self, qname): + name_parts = qname.split('::') + if not name_parts: + return + + scope = self + while scope is not None: + if scope.name == name_parts[0]: + break + else: + found = None + for entity in scope.members.values(): + if entity.name == name_parts[0]: + found = entity + break + if found is None: + scope = scope.scope + else: + break + if not scope: + return + + for part in name_parts: + if scope.name != part: + found = None + for entity in scope.members.values(): + if entity.name == part: + found = entity + break + scope = found + if found is None: + break + + return scope + + def resolve_references(self): + self.brief = make_blocks(self._brief, self.index) + delattr(self, '_brief') + + self.description = make_blocks(self._description, self.index) + delattr(self, '_description') + + def update_scopes(self): + pass + + def __lt__(self, other): + return self.name < other.name + + @property + def asciidoc_file(self) -> str: + file_path = '/'.join(self._sanitize_path_segment(elm.name) for elm in self.path) + return f'{file_path}.adoc' + + + +class Compound(Entity): + nametag = 'compoundname' + + def __init__(self, element, scope, index=dict()): + super().__init__(element, scope, index) + + self.members = {} + self._nested = [] + for section in element: + if section.tag in ('innerclass', 'innernamespace', 'innergroup'): + self._nested.append(( + section.get('prot', Access.public), + section.get('refid'))) + + def update_scopes(self): + super().update_scopes() + + for access, refid in self._nested: + entity = self.index[refid] + entity.scope = self + entity.access = access + + assert entity.name not in self.members + self.members[entity.name] = entity + delattr(self, '_nested') + + def resolve_references(self): + super().resolve_references() + if getattr(self, '_nested', None): + self.update_scopes() + + @property + def public_types(self) -> PyList['Type']: + return [mem for mem in self.members.values() + if isinstance(mem, Type) + and mem.access == Access.public] + + + @property + def public_member_functions(self) -> PyList['OverloadSet']: + return [mem for mem in self.members.values() + if isinstance(mem, OverloadSet) + and mem.access == Access.public + and mem.kind == FunctionKind.nonstatic + ] + + @property + def public_static_functions(self) -> PyList['OverloadSet']: + return [mem for mem in self.members.values() + if isinstance(mem, OverloadSet) + and mem.access == Access.public + and mem.kind == FunctionKind.static + ] + + + +class Member(Entity): + nametag = 'name' + + def __init__(self, element: ET.Element, scope, index=dict()): + super().__init__(element, scope, index) + self.access = element.get('prot') or Access.public + + +class Group(Compound): + nametag = 'title' + + def __init__(self, element, index=dict()): + super().__init__(element, None, index) + + def adopt(self, entity, access): + entity.groups.append(self) + + +class Templatable(Entity): + def __init__(self, element, scope, index=dict()): + super().__init__(element, scope, index) + self._template_parameters = element.find('templateparamlist') + self.is_specialization = ( + (self.name.find('<') > 0) and (self.name.find('>') > 0)) + + def resolve_references(self): + super().resolve_references() + params = ( + self._template_parameters + if self._template_parameters is not None + and len(self._template_parameters) + else [] + ) + self.template_parameters = [Parameter(elem, self) for elem in params] + delattr(self, '_template_parameters') + + +class Type(Templatable): + declarator = None + objects = [] + + +class Scope(Entity): + def __init__(self, element, scope, index=dict()): + super().__init__(element, scope, index) + + nesting = 0 + name = '' + colon = False + for c in self.name: + if colon: + colon = False + if c == ':': + name = '' + continue + else: + name += ':' + + if nesting: + if c == '<': + nesting += 1 + elif c == '>': + nesting -= 1 + name += c + elif c == ':': + colon = True + else: + if c == '<': + nesting += 1 + name += c + if colon: + name.append(':') + self.name = name + + self.members = dict() + for section in element: + if not section.tag == 'sectiondef': + continue + + for member_def in section: + assert member_def.tag == 'memberdef' + + kind = member_def.get('kind') + if (kind == 'friend' + and member_def.find('type').text == 'class'): + # ignore friend classes + continue + + factory = { + 'function': OverloadSet.create, + 'friend': OverloadSet.create, + 'variable': Variable, + 'typedef': TypeAlias, + 'enum': Enum, + }[kind] + member = factory(member_def, section, self, index) + if type(member) is OverloadSet: + key = (member.name, member.access, member.kind) + self.members[key] = member + else: + assert member.name not in self.members + self.members[member.name] = member + + +class Namespace(Scope, Compound): + declarator = 'namespace' + + def __init__(self, element, index=dict()): + super().__init__(element, None, index) + + def resolve_references(self): + super().resolve_references() + for member in self.members.values(): + if isinstance(member, OverloadSet): + for func in member: + func.is_free = True + + +class Class(Scope, Compound, Type): + declarator = 'class' + + def __init__(self, element, index=dict()): + super().__init__(element, None, index) + self._bases = element.findall('basecompoundref') + + def resolve_references(self): + super().resolve_references() + self.bases = [Generalization(entry, self) for entry in self._bases] + delattr(self, '_bases') + + +class Generalization(): + def __init__(self, element, derived): + self.is_virtual = element.get('virt') == 'virtual' + self.access = element.get('prot') + assert self.access + + refid = element.get('refid') + if not refid: + entity = derived.lookup( ''.join(element.itertext()).strip() ) + if entity is not None: + refid = entity.id + + if refid: + self.base = Phrase( + [make_entity_reference(element, derived.index, refid)]) + else: + self.base = text_with_refs(element, derived.index) + + +class Struct(Class): + declarator = 'struct' + + +class Union(Class): + declarator = 'union' + + +class Enum(Scope, Type, Member): + def __init__(self, element, section, parent, index=dict()): + super().__init__(element, parent, index) + self.is_scoped = element.get('strong') == 'yes' + self._underlying_type = element.find('type') + + self.objects = [] + for child in element.findall('enumvalue'): + enumerator = Enumerator(child, section, self, index) + self.objects.append(enumerator) + assert enumerator.name not in enumerator.scope.members + enumerator.scope.members[enumerator.name] = enumerator + + @property + def declarator(self): + return 'enum class' if self.is_scoped else 'enum' + + def resolve_references(self): + super().resolve_references() + self.underlying_type = text_with_refs( + self._underlying_type, self.index) + delattr(self, '_underlying_type') + + +class Value(Member, Templatable): + def __init__(self, element: ET.Element, parent, index=dict()): + super().__init__(element, parent, index) + self.is_static = element.get('static') == 'yes' + self.is_constexpr = element.get('constexpr') == 'yes' + self.is_volatile = element.get('volatile') == 'yes' + self.is_const = ( + element.get('const') == 'yes' + or element.get('mutable') == 'no' + or False) + self.is_inline = element.get('inline') == 'yes' + + +class Function(Value): + def __init__(self, element: ET.Element, section, parent, index=dict()): + super().__init__(element, parent, index) + self.is_explicit = element.get('explicit') == 'yes' + self.refqual = element.get('refqual') + self.virtual_kind = element.get('virt', VirtualKind.nonvirtual) + self.is_friend = section.get('kind') == 'friend' + self.is_free = section.get('kind') == 'related' + self.is_constructor = self.name == parent.name + self.is_destructor = self.name == '~' + parent.name + noexcept = element.get('noexcept') + if noexcept: + self.is_noexcept = noexcept == 'yes' + else: + self.is_noexcept = self.is_destructor + + args = element.find('argsstring').text or '' + self.is_deleted = args.endswith('=delete') + self.is_defaulted = args.endswith('=default') + + self.overload_set = None + + self._return_type = element.find('type') + assert ( + self.is_constructor + or self.is_destructor + or self._return_type is not None) + + self._parameters = element.findall('param') + + def __repr__(self) -> str: + return 'Function({})'.format(json.dumps({ + 'id': self.id, + 'name': self.name, + 'brief': str(self.brief) if hasattr(self, 'brief') else '', + }, indent=4)) + + @property + def kind(self): + if self.is_friend: + return FunctionKind.friend + if self.is_free: + return FunctionKind.free + if self.is_static: + return FunctionKind.static + return FunctionKind.nonstatic + + @property + def is_sole_overload(self): + return len(self.overload_set) == 1 + + @property + def overload_index(self): + if self.overload_set is None or self.is_sole_overload: + return -1 + + for n, overload in enumerate(self.overload_set): + if self == overload: + return n + + return -1 + + def resolve_references(self): + assert self._description is not None + node = self._description.find('.//xrefsect/..') + if node is not None: + print(f'Got xrefsect for {self.name}') + subnode = node.find('xrefsect') + assert subnode is not None + xreftitle = subnode.find('xreftitle') + assert xreftitle is not None + assert xreftitle.text == 'overload_specific' + xrefdescription = subnode.find('xrefdescription') + assert xrefdescription is not None + self.overload_specific = make_blocks(xrefdescription, self.index) + node.remove(subnode) + print(self.overload_specific) + else: + self.overload_specific = [] + super().resolve_references() + + self.return_type = resolve_type(self._return_type, self.index) + delattr(self, '_return_type') + + self.parameters = [Parameter(elem, self) for elem in self._parameters] + delattr(self, '_parameters') + + def __lt__(self, other): + if not isinstance(other, Function): + return self.name < other.name + + if self.name == other.name: + if self.scope == parent.scope: + return self.overload_index < other.overload_index + return self.scope < other.scope + + # if self.is_constructor: + # return True + # if other.is_constructor: + # return False + # if self.is_destructor: + # return True + # if other.is_destructor: + # return False + return self.name < other.name + + +class Parameter(): + def __init__(self, element: ET.Element, parent): + self.type = text_with_refs(element.find('type'), parent.index) + self.default_value = text_with_refs( + element.find('defval'), parent.index) + + self.description = element.find('briefdescription') + if self.description is not None: + self.description = make_blocks(self.description, parent) + else: + self.description = [] + + self.name = element.find('declname') + if self.name is not None: + self.name = self.name.text + + self.array = text_with_refs(element.find('array'), parent.index) + if self.array: + assert isinstance(self.type[-1], str) + assert self.type[-1].endswith('(&)') + self.type[-1] = self.type[-1][:-3] + + +class OverloadSet(): + @staticmethod + def create(element, section, parent, index): + func = Function(element, section, parent, index) + + key = (func.name, func.access, func.kind) + if key in parent.members: + overload_set = parent.members[key] + overload_set.append(func) + else: + overload_set = OverloadSet([func]) + func.overload_set = overload_set + return overload_set + + def __init__(self, funcs): + self.funcs = funcs + assert len(funcs) + self._resort() + + def append(self, func): + self.funcs.append(func) + self._resort() + + def __getattr__(self, name): + return getattr(self.funcs[0], name) + + @property + def brief(self): + # print(f'Overload set: {self.name}, functions: {self.funcs}', flush=True) + return [func.brief for func in self.funcs] + + def __getitem__(self, pos): + return self.funcs[pos] + + def __len__(self): + return len(self.funcs) + + def __lt__(self, other): + if isinstance(other, OverloadSet): + return self.funcs[0] < other.funcs[0] + return self.name < other.name + + def _resort(self): + funcs_backwards = [] + briefs_backwards = [] + for func in self.funcs: + brief = ( + ''.join(func._brief.itertext()) + if func._brief is not None + else '' + ) + try: + n = briefs_backwards.index(brief) + except: + n = 0 + briefs_backwards.insert(n, brief) + funcs_backwards.insert(n, func) + funcs_backwards.reverse() + self.funcs = funcs_backwards + + +class Variable(Value): + def __init__(self, element, section, parent, index=dict()): + super().__init__(element, parent, index) + self._value = element.find('initializer') + self._type = element.find('type') + + def resolve_references(self): + super().resolve_references() + + self.value = text_with_refs(self._value, self.index) + delattr(self, '_value') + + self.type = resolve_type(self._type, self.index) + delattr(self, '_type') + + +class Enumerator(Variable): + def __init__(self, element, section, parent, index=dict()): + super().__init__(element, section, parent, index) + self.is_constexpr = True + self.is_const = True + self.is_static = True + self.enum = parent + self.scope = parent if parent.is_scoped else parent.scope + assert self.scope + + def resolve_references(self): + super().resolve_references() + self.type = Phrase([EntityRef(self.enum, [self.enum.name])]) + + +class TypeAlias(Member, Type): + declarator = 'using' + + def __init__(self, element, section, parent, index=dict()): + super().__init__(element, parent, index) + + self._aliased = element.find('type') + assert self._aliased is not None + + def resolve_references(self): + super().resolve_references() + self.aliased = text_with_refs(self._aliased, self.index) + delattr(self, '_aliased') + + +class AcceptOneorNone(argparse.Action): + def __init__(self, option_strings, dest, **kwargs): + if kwargs.get('nargs') is not None: + raise ValueError("nargs not allowed") + if kwargs.get('const') is not None: + raise ValueError("const not allowed") + if kwargs.get('default') is not None: + raise ValueError("default not allowed") + + super().__init__(option_strings, dest, **kwargs) + + def __call__(self, parser, namespace, values, option_string=None): + if getattr(namespace, self.dest) is not None: + raise argparse.ArgumentError(self, "multiple values") + + setattr(namespace, self.dest, values) + +def parse_args(args): + parser = argparse.ArgumentParser( + prog=args[0], + description='Produces API reference in QuickBook markup') + parser.add_argument( + '-i', + '--input', + action=AcceptOneorNone, + help='Doxygen XML index file; STDIN by default') + parser.add_argument( + '-o', + '--output', + action=AcceptOneorNone, + help='Output file; STDOUT by default') + parser.add_argument( + '-c', '--config', + action='append', + default=[], + help='Configuration files') + parser.add_argument( + '-T', '--template', + action=AcceptOneorNone, + help='Jinja2 template to use for output') + parser.add_argument( + '-I', '--include', + action='append', + default=[], + help='Directory with template partials') + parser.add_argument( + '-D', '--directory', + action=AcceptOneorNone, + help=( + 'Directory with additional data files; ' + 'by default INPUT parent directory if that is provided, ' + 'otherwise PWD')) + return parser.parse_args(args[1:]) + +def open_input(stdin, args, cwd): + data_dir = args.directory + if args.input: + file = open(args.input, 'r', encoding='utf-8') + ctx = file + data_dir = data_dir or os.path.dirname(args.input) + else: + file = stdin + ctx = Nullcontext() + data_dir = data_dir or cwd + return (file, ctx, data_dir) + +def open_output(stdout, args): + if args.output: + file = open(args.output, 'w', encoding='utf-8') + ctx = file + else: + file = stdout + ctx = Nullcontext() + return (file, ctx) + +def load_configs(args): + result = { + 'include_private': False, + 'legacy_behavior': True, + } + for file_name in args.config: + with open(file_name, 'r', encoding='utf-8') as file: + result.update( json.load(file) ) + return result + +def collect_compound_refs(file): + tree = ET.parse(file) + root = tree.getroot() + for child in root: + if child.tag != 'compound': + continue + + kind = child.get('kind') + assert kind + if kind in ('file', 'dir'): + continue + + refid = child.get('refid') + assert refid + yield refid + +def collect_data(parent_dir, refs) -> Dict[str, Entity]: + result = dict() + for refid in refs: + file_name = os.path.join(parent_dir, refid) + '.xml' + with open(file_name, 'r', encoding='utf-8') as file: + tree = ET.parse(file) + root = tree.getroot() + assert len(root) == 1 + + element = root[0] + assert element.tag == 'compounddef' + + factory = { + 'class': Class, + 'namespace': Namespace, + 'struct': Struct, + 'union': Union, + 'group': Group + }.get(element.get('kind')) + if not factory: + continue + factory(element, result) + + for entity in result.values(): + assert entity is not None + entity.update_scopes() + + for entity in result.values(): + entity.resolve_references(); + + return result + +def docca_include_dir(script): + return os.path.join(os.path.dirname(script), 'include') + +def template_file_name(includes, args): + return (args.template + or os.path.join(includes, 'docca/quickbook.jinja2')) + +def collect_include_dirs(template, include_dir, args): + result = [os.path.dirname(template), include_dir] + result.extend(args.include) + return result + +def construct_environment(loader, config): + env = jinja2.Environment( + loader=loader, + autoescape=False, + undefined=jinja2.StrictUndefined, + extensions=[ + 'jinja2.ext.do', + 'jinja2.ext.loopcontrols', + ], + ) + + env.globals['Access'] = Access + env.globals['FunctionKind'] = FunctionKind + env.globals['VirtualKind'] = VirtualKind + env.globals['Section'] = Section + env.globals['ParameterList'] = ParameterList + env.globals['Config'] = config + + env.tests['Entity'] = lambda x: isinstance(x, Entity) + env.tests['Templatable'] = lambda x: isinstance(x, Templatable) + env.tests['Type'] = lambda x: isinstance(x, Type) + env.tests['Scope'] = lambda x: isinstance(x, Scope) + env.tests['Namespace'] = lambda x: isinstance(x, Namespace) + env.tests['TypeAlias'] = lambda x: isinstance(x, TypeAlias) + env.tests['Class'] = lambda x: isinstance(x, Class) + env.tests['Struct'] = lambda x: isinstance(x, Struct) + env.tests['Union'] = lambda x: isinstance(x, Union) + env.tests['Enum'] = lambda x: isinstance(x, Enum) + env.tests['Value'] = lambda x: isinstance(x, Value) + env.tests['Variable'] = lambda x: isinstance(x, Variable) + env.tests['Enumerator'] = lambda x: isinstance(x, Enumerator) + env.tests['Function'] = lambda x: isinstance(x, Function) + env.tests['OverloadSet'] = lambda x: isinstance(x, OverloadSet) + env.tests['Parameter'] = lambda x: isinstance(x, Parameter) + + env.tests['Phrase'] = lambda x: isinstance(x, Phrase) + env.tests['Linebreak'] = lambda x: isinstance(x, Linebreak) + env.tests['Emphasised'] = lambda x: isinstance(x, Emphasised) + env.tests['Strong'] = lambda x: isinstance(x, Strong) + env.tests['Monospaced'] = lambda x: isinstance(x, Monospaced) + env.tests['EntityRef'] = lambda x: isinstance(x, EntityRef) + env.tests['UrlLink'] = lambda x: isinstance(x, UrlLink) + + env.tests['Block'] = lambda x: isinstance(x, Block) + env.tests['Paragraph'] = lambda x: isinstance(x, Paragraph) + env.tests['List'] = lambda x: isinstance(x, List) + env.tests['ListItem'] = lambda x: isinstance(x, ListItem) + env.tests['Section'] = lambda x: isinstance(x, Section) + env.tests['CodeBlock'] = lambda x: isinstance(x, CodeBlock) + env.tests['Table'] = lambda x: isinstance(x, Table) + env.tests['Cell'] = lambda x: isinstance(x, Cell) + env.tests['ParameterList'] = lambda x: isinstance(x, ParameterList) + env.tests['ParameterDescription'] = lambda x: isinstance(x, ParameterDescription) + env.tests['ParameterItem'] = lambda x: isinstance(x, ParameterItem) + + return env + +def render(env: jinja2.Environment, file_name, output_file, entity): + template = env.get_template(os.path.basename(file_name)) + + makedirs(os.path.dirname(output_file), exist_ok=True) + with open(output_file, 'wt', encoding='utf-8') as f: + template.stream(entity=entity).dump(f) + + +def render_quickref(env: jinja2.Environment, **kwargs): + template = env.get_template(os.path.basename('quickref.jinja2')) + output_file = 'mysql/modules/ROOT/pages/reference.adoc' + with open(output_file, 'wt', encoding='utf-8') as f: + template.stream(**kwargs).dump(f) + + +def main(args, stdin, stdout, script): + args = parse_args(args) + + file, ctx, data_dir = open_input(stdin, args, os.getcwd()) + with ctx: + refs = list(collect_compound_refs(file)) + data = collect_data(data_dir, refs) + + config = load_configs(args) + + env = construct_environment( + jinja2.FileSystemLoader('templates'), config) + + # Classes (including member types) + classes = [e for e in data.values() if isinstance(e, Class) and e.access == Access.public] + for e in classes: + render(env, 'class.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + + # Functions. TODO: free functions + fns = [] + for e in [e2 for e2 in data.values() if isinstance(e2, Compound)]: + fns += [mem for mem in e.members.values() if isinstance(mem, OverloadSet) and mem.access == Access.public] + for e in fns: + # print(f'Rendering {e.fully_qualified_name}', flush=True) + render(env, 'overload-set.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + + # Type aliases + type_alias = [e for e in data.values() if isinstance(e, TypeAlias)] + for e in type_alias: + # print(f'Rendering {e.fully_qualified_name}', flush=True) + render(env, 'type-alias.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + + # Enums + enums = [e for e in data.values() if isinstance(e, Enum)] + for e in enums: + # print(f'Rendering {e.fully_qualified_name}', flush=True) + render(env, 'enum.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + + # Quickref + render_quickref( + env, + classes=classes, + enums=enums, + free_functions=[e for e in fns if isinstance(e.scope, Namespace)], + type_aliases=[e for e in type_alias if isinstance(e.scope, Namespace)], + ) + + + +if __name__ == '__main__': + main(sys.argv, sys.stdin, sys.stdout, os.path.realpath(__file__)) diff --git a/doc/docca-asciidoc/templates/class.jinja2 b/doc/docca-asciidoc/templates/class.jinja2 new file mode 100644 index 000000000..917ce8bcd --- /dev/null +++ b/doc/docca-asciidoc/templates/class.jinja2 @@ -0,0 +1,72 @@ +{% from "common.jinja2" import description, link, template_parameters, phrase %} + +== boost::mysql::{{ entity.name }} + + +Defined in header [link-to-entity bg-white]`<{{ entity.location.file.replace('libs/mysql/include/', '') }}>` + +{{ description(entity.brief) }} + +[source, cpp, subs="+macros", role="raw-code"] +---- +{{ template_parameters(entity) }} +{{ entity.declarator }} {{ entity.name }} +{%- for entry in entity.bases -%} + {% if loop.first %}:{% else %},{% endif -%} + {{ ' ' ~ entry.access ~ ' ' }} + {%- if entry.is_virtual %}virtual {% endif -%} + {{ phrase(entry.base, in_code=True) }} +{%- endfor -%} +; +---- + +{{ description(entity.description) }} + +{% for type in entity.public_types %} +{% if loop.first %} +=== Member types + +[cols="1,2", grid=rows, frame=none, role="mt-0"] +|=== +{% endif %} +.^|{{ link(type, '[link-to-entity bg-white]`' + type.name + '`') }} +.^|{{ description(type.brief) }} + +{% if loop.last %} +|=== +{% endif %} + +{%- endfor -%} + + +{% for fn in entity.public_member_functions %} +{% if loop.first %} +=== Member functions + +[cols="1,2", grid=rows, frame=none, role="mt-0"] +|=== +{% endif %} +.^|{{ link(fn, '[link-to-entity bg-white]`' + fn.name + '`') }} +.^|{{ description(fn.brief[0]) }} + +{% if loop.last %} +|=== +{% endif %} + +{%- endfor -%} + +{% for fn in entity.public_static_functions %} +{% if loop.first %} +=== Static functions + +[cols="1,2", grid=rows, frame=none, role="mt-0"] +|=== +{% endif %} +.^|{{ link(fn, '[link-to-entity bg-white]`' + fn.name + '`') }} +.^|{{ description(fn.brief[0]) }} + +{% if loop.last %} +|=== +{% endif %} + +{%- endfor -%} diff --git a/doc/docca-asciidoc/templates/common.jinja2 b/doc/docca-asciidoc/templates/common.jinja2 new file mode 100644 index 000000000..125b85a62 --- /dev/null +++ b/doc/docca-asciidoc/templates/common.jinja2 @@ -0,0 +1,171 @@ +{% macro escape(s) -%} + {{ s.replace("[", "\\[").replace("]", "\\]") }} +{%- endmacro %} + + +{% macro subsection(sub) -%} +{% if sub.title %} + +=== {{ phrase(sub.title) }} +{% elif sub.kind %} + +=== {%- if sub.kind == 'see' %} See Also + {%- elif sub.kind == 'return' %} Return Value + {%- elif sub.kind == 'author' %} Author + {%- elif sub.kind == 'authors' %} Authors + {%- elif sub.kind == 'version' %} Version + {%- elif sub.kind == 'since' %} Since + {%- elif sub.kind == 'date' %} Date + {%- elif sub.kind == 'note' %} Remarks + {%- elif sub.kind == 'warning' %} Warning + {%- elif sub.kind == 'pre' %} Preconditions + {%- elif sub.kind == 'post' %} Postconditions + {%- elif sub.kind == 'copyright' %} Copyright + {%- elif sub.kind == 'invariant' %} Invariants + {%- elif sub.kind == 'remark' %} Remarks + {%- elif sub.kind == 'attention' %} Attention + {%- elif sub.kind == 'par' %} Paragraph + {%- elif sub.kind == 'rcs'%} RCS + {%- else %} Unknown + {%- endif -%} +{%- endif %} +{{ description(sub) }} +{%- endmacro %} + +{% macro link(entity, text) -%} + {%- if entity is Enumerator -%} + {{ link(entity.enum, text) }} + {%- else -%} + xref:{{ entity.asciidoc_file }}[{{ text }}] + {%- endif -%} +{%- endmacro %} + +{%- macro itemised(lst, nesting='') -%} + {%- for item in lst -%} + {{ nesting }} + {%- if lst.is_ordered -%} + # + {%- else -%} + * + {%- endif %} {{ description(item, nesting + ' ') }} + {%- endfor -%} +{%- endmacro %} + + +{% macro text_helper(s, in_code=False) -%} + {%- if s -%} + {%- set replacements=Config.get('replace_strings', {}) -%} + + {%- set ns = namespace(s=s) -%} + {%- if in_code -%} + {%- set ns.s = ns.s | replace(" ", " ") + | replace(" ", " ") + | replace(" ", " ") + | replace(" ", " ") + -%} + {%- if ns.s.endswith(" &") -%} + {%- set ns.s = ns.s[:-2] + "&" -%} + {%- elif ns.s.endswith(" *") -%} + {%- set ns.s = ns.s[:-2] + "*" -%} + {%- elif ns.s.endswith(" &&") -%} + {%- set ns.s = ns.s[:-3] + "&&" -%} + {%- elif ns.s.endswith(" &...") -%} + {%- set ns.s = ns.s[:-5] + "&..." -%} + {%- elif ns.s.endswith(" *...") -%} + {%- set ns.s = ns.s[:-5] + "*..." -%} + {%- elif ns.s.endswith(" &&...") -%} + {%- set ns.s = ns.s[:-6] + "&&..." -%} + {%- endif -%} + {%- else -%} + {%- set ns.s = escape(s) -%} + {%- endif -%} + {%- for src, tgt in replacements.items() -%} + {%- set ns.s = ns.s.replace(src, tgt) -%} + {%- endfor -%} + {{ ns.s }} + {%- else -%} + {{ s }} + {%- endif -%} +{%- endmacro %} + + + + +{% macro phrase(para, in_code=False) -%} +{%- for part in para -%}{{ phrase_part(part, in_code=in_code) }}{%- endfor -%} +{%- endmacro %} + +{% macro phrase_part(part, in_code=False) -%} + {%- if part is string -%} + {{ text_helper(part, in_code=in_code) }} + {%- elif part is Monospaced -%} + `+++{{ phrase(part, in_code=True) }}+++` + {%- elif part is Emphasised -%} + _{{ phrase(part, in_code=in_code) }}_ + {%- elif part is Strong -%} + *{{ phrase(part, in_code=in_code) }}* + {%- elif part is EntityRef -%} + {{ link(part.entity, part.entity.name) }} + {%- elif part is UrlLink -%} + [@{{ part.url }} {{ phrase(part, in_code=in_code) }}] + {%- elif part is Linebreak %}{# indent is intentional here #} + +{% elif part is Phrase -%} + {{ phrase(part, in_code=in_code) }} + {%- else -%} + {{ part.unhandled_type() }} + {%- endif -%} +{%- endmacro %} + +{% macro description(parts, nesting='') -%} + +{%- for part in parts -%} + +{%- if part is Paragraph -%} +{{ phrase(part) }} +{% elif part is List -%} +{{ itemised(part, nesting) }} +{%- elif part is Section -%} +{{ subsection(part) }} +{%- elif part is CodeBlock %} +{{ nesting }}``` +{% for line in part -%} +{{nesting}}{{line}} +{% endfor -%} +{{ nesting }}``` +{% elif part is ParameterList -%} +{# {{ parameter_list(part) }} #} +{% elif part is Table -%} +{{ table(part) }} +{%- else -%} +{{ part.unhandled_type() }} +{%- endif -%} + +{%- endfor -%} + +{%- endmacro %} + +{%- macro template_parameters(entity) -%} +{%- if entity.template_parameters or entity.is_specialization -%}template<{%- endif -%} +{%- for tparam in entity.template_parameters %} + {{ phrase(tparam.type, in_code=True) }} + {%- if tparam.array %} (&{% endif -%} + {%- if tparam.name -%} + {%- if not tparam.array %} {% endif -%} + {{ tparam.name }} + {%- endif -%} + {%- if tparam.array %}) {{ phrase(tparam.array, in_code=True) }}{% endif -%} + {%- if tparam.default_value %} = {{ phrase(tparam.default_value, in_code=True) }}{% endif -%} + +{%- if loop.last -%} +> +{%- else -%} +, +{%- endif -%} + +{%- else -%} +{%- if entity.is_specialization -%} +> +{%- endif -%} +{%- endfor %} +{%- endmacro %} \ No newline at end of file diff --git a/doc/docca-asciidoc/templates/enum.jinja2 b/doc/docca-asciidoc/templates/enum.jinja2 new file mode 100644 index 000000000..a754fdf4b --- /dev/null +++ b/doc/docca-asciidoc/templates/enum.jinja2 @@ -0,0 +1,34 @@ +{% from "common.jinja2" import phrase, template_parameters, description %} + +== {{ entity.fully_qualified_name }} + + +Defined in header [link-to-entity bg-white]`<{{ entity.location.file.replace('libs/mysql/include/', '') }}>` + +[source, cpp, subs="+macros", role="raw-code"] +---- +{{ entity.declarator }} {{ entity.name }} +{%- if entity.underlying_type -%} +: {{ phrase(entity.underlying_type) }} +{%- endif -%}; +---- + +{{ description(entity.brief) }} + +{{ description(entity.description) }} + +{% for enum in entity.objects %} +{% if loop.first %} +=== Enumerators + +[cols="1,2", grid=rows, frame=none, role="mt-0"] +|=== +{% endif %} +.^|[link-to-entity bg-white]`{{ enum.name }}` +.^|{{ description(enum.brief) }} {{ description(enum.description) }} + +{% if loop.last %} +|=== +{% endif %} + +{% endfor %} \ No newline at end of file diff --git a/doc/docca-asciidoc/templates/overload-set.jinja2 b/doc/docca-asciidoc/templates/overload-set.jinja2 new file mode 100644 index 000000000..ff0df6532 --- /dev/null +++ b/doc/docca-asciidoc/templates/overload-set.jinja2 @@ -0,0 +1,80 @@ + +{%- from "common.jinja2" import template_parameters, description, phrase -%} + +== {{ entity.fully_qualified_name }} + + +[cols="8,1", grid=rows, frame=none, role="mt-0"] +|=== + +{% for fn in entity %} + +a| +[source, cpp, subs="+macros", role="raw-code"] +---- +{{ template_parameters(fn) }} +{%- set qualifiers = [] -%} +{%- if fn.is_explicit -%} + {%- set qualifiers = qualifiers + ['explicit'] -%} +{%- endif -%} +{%- if fn.is_static -%} + {%- set qualifiers = qualifiers + ['static'] -%} +{%- endif -%} +{%- if fn.is_constexpr -%} + {%- set qualifiers = qualifiers + ['constexpr'] -%} +{%- endif -%} + +{%- if qualifiers | length -%} + {{ qualifiers | join(' ') }}{{' '}} +{%- endif -%} +{{ phrase(fn.return_type, in_code=True) }} +{{ fn.name }}( +{%- for param in fn.parameters %} + {{ phrase(param.type, in_code=True) }} + {%- if param.array %} (&{% endif -%} + {%- if param.name -%} + {%- if not param.array %} {% endif -%} + {{ param.name }} + {%- endif -%} + {%- if param.array %}) {{ phrase(param.array, in_code=True) }}{% endif -%} + {%- if param.default_value %} = {{ phrase(param.default_value, in_code=True) }}{% endif -%} + + {%- if not loop.last %},{% endif -%} +{%- endfor -%} +) +{%- if fn.refqual or fn.is_const -%} + {{ " " }} + {%- if fn.is_const %}const{% endif -%} + {%- if "lvalue" == fn.refqual %}& + {%- elif "rvalue" == fn.refqual %}&& + {%- endif -%} +{%- endif -%} +{%- if fn.is_noexcept and not fn.is_destructor %} noexcept{% endif -%} +{%- if not fn.is_noexcept and fn.is_destructor %} noexcept(false){% endif -%} +{%- if fn.is_deleted %} = delete +{%- elif fn.is_defaulted %} = default +{%- endif -%} +; +---- + +.^| {%- if entity | length > 1 -%} ({{ loop.index }}) {%- endif -%} + +{% endfor %} + +|=== + +{{ description(entity.brief[0]) }} + +{{ description(entity.description) }} + +{%- if entity | length > 1 -%} +[cols="1,8", grid=rows, frame=none, role="mt-0"] +|=== +{% for fn in entity -%} + {%- if fn.overload_specific | length -%} + .^|({{ loop.index }}) + |{{ description(fn.overload_specific) }} + {%- endif -%} +{%- endfor %} +|=== +{%- endif -%} diff --git a/doc/docca-asciidoc/templates/quickref.jinja2 b/doc/docca-asciidoc/templates/quickref.jinja2 new file mode 100644 index 000000000..63c96a7e4 --- /dev/null +++ b/doc/docca-asciidoc/templates/quickref.jinja2 @@ -0,0 +1,42 @@ + +{% from "common.jinja2" import link %} + +{% macro reflink(entity) %} +[.m-0] +{{ link(entity, '[link-to-entity bg-white]`' + entity.name + '`') }} +{% endmacro %} + +[#reference] += Reference +:role: quickref + +[cols="1,1"] +|=== + +a| [.pb-1]*Classes* + +{% for e in classes | sort -%} +{{ reflink(e) }} +{%- endfor %} + +a| [.pb-1]*Enumerations* + +{% for e in enums | sort -%} +{{ reflink(e) }} +{%- endfor %} + +[.pb-1]*Functions* + +{% for e in free_functions | sort -%} +{{ reflink(e) }} +{%- endfor %} + +[.pb-1]*Type aliases* + +{% for e in type_aliases | sort -%} +{{ reflink(e) }} +{%- endfor %} + + +|=== + diff --git a/doc/docca-asciidoc/templates/type-alias.jinja2 b/doc/docca-asciidoc/templates/type-alias.jinja2 new file mode 100644 index 000000000..f693c3a4b --- /dev/null +++ b/doc/docca-asciidoc/templates/type-alias.jinja2 @@ -0,0 +1,17 @@ +{% from "common.jinja2" import phrase, template_parameters, description %} + +== {{ entity.fully_qualified_name }} + + +Defined in header [link-to-entity bg-white]`<{{ entity.location.file.replace('libs/mysql/include/', '') }}>` + +[source, cpp, subs="+macros", role="raw-code"] +---- +{{ template_parameters(entity) }} +{{ entity.declarator }} {{ entity.name }} = {{ phrase(entity.aliased) }}; +---- + +{{ description(entity.brief) }} + +{{ description(entity.description) }} + diff --git a/doc/supplemental-ui/css/custom.css b/doc/supplemental-ui/css/custom.css new file mode 100644 index 000000000..8a96fa99e --- /dev/null +++ b/doc/supplemental-ui/css/custom.css @@ -0,0 +1,146 @@ + +.link-to-entity { + color: #0b0080 !important; +} + +.keyword { + color: #0000dd !important; +} + +.function-name { + color: #0645ad !important; + font-weight: bold !important; +} + +.bg-white { + background: white !important; +} + +.mt-0 { + margin-top: 0 !important; +} + +.m-0 { + margin: 0 !important; +} + +.pb-1 { + padding-bottom: 1vh; +} + +.indent { + padding-left: 2em !important; +} + +.doc { + hyphens: none !important; +} + +.quickref article { + max-width: 80% !important; +} + +/* highlight.js */ + +/*! Adapted from the GitHub style by Vasily Polovnyov */ +.hljs-comment, +.hljs-quote { + color: #008000; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #0000dd; + font-weight: var(--monospace-font-weight-bold); +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: black; +} + +.hljs-string, +.hljs-doctag { + color: #d14; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: black; + font-weight: var(--monospace-font-weight-bold); +} + +.hljs-subst { + font-weight: normal; +} + +.hljs-type, +.hljs-class .hljs-title { + color: black; + font-weight: var(--monospace-font-weight-bold); +} + +.hljs-tag, +.hljs-name, +.hljs-attribute { + color: black; + font-weight: normal; +} + +.hljs-regexp, +.hljs-link { + color: #0b0080; +} + +.hljs-symbol, +.hljs-bullet { + color: black; +} + +.hljs-built_in, +.hljs-builtin-name { + color: #0086b3; +} + +.hljs-meta { + color: #999; + font-weight: var(--monospace-font-weight-bold); +} + +.hljs-deletion { + background: #fdd; +} + +.hljs-addition { + background: #dfd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: var(--monospace-font-weight-bold); +} + +.highlightjs a { + color: #003080; +} +.highlightjs a:hover { + color: #003080; +} + +.raw-code code { + background: white !important; + box-shadow: none !important; +} + +.raw-code .source-toolbox { + display: none !important; +} \ No newline at end of file diff --git a/doc/supplemental-ui/partials/head-styles.hbs b/doc/supplemental-ui/partials/head-styles.hbs new file mode 100644 index 000000000..f15cf5141 --- /dev/null +++ b/doc/supplemental-ui/partials/head-styles.hbs @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..13780fcf1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1616 @@ +{ + "name": "asciidoc", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@asciidoctor/tabs": "1.0.0-beta.6", + "antora": "3.1.9" + } + }, + "node_modules/@antora/asciidoc-loader": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.9.tgz", + "integrity": "sha512-flE27T2yI8TX7rUNjbBHWN3iR6s+kBuRBbUPncUFcWjx6mXzll8JLiTkxnc8JXHGzgKlveT+t5AkPYGACLfasg==", + "dev": true, + "dependencies": { + "@antora/logger": "3.1.9", + "@antora/user-require-helper": "~2.0", + "@asciidoctor/core": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/cli": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", + "integrity": "sha512-kCUqWX3G/9Pvf8SWZ45ioHwWdOc9uamy2E5/FFwyGiTeu4ubNbadOauLVvMzSZHUxVDnGxXwCsmmQ2HwM919ew==", + "dev": true, + "dependencies": { + "@antora/logger": "3.1.9", + "@antora/playbook-builder": "3.1.9", + "@antora/user-require-helper": "~2.0", + "commander": "~11.1" + }, + "bin": { + "antora": "bin/antora" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/content-aggregator": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.9.tgz", + "integrity": "sha512-g+UzevPSm5c4R0j1U9uysJfdIUfp++QOHIEBmqjhfx/aIEnOL70zA+WF55Mm+syAfzU3877puI27sOp8qtPglw==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0", + "@antora/logger": "3.1.9", + "@antora/user-require-helper": "~2.0", + "braces": "~3.0", + "cache-directory": "~2.0", + "fast-glob": "~3.3", + "hpagent": "~1.2", + "isomorphic-git": "~1.25", + "js-yaml": "~4.1", + "multi-progress": "~4.0", + "picomatch": "~4.0", + "progress": "~2.0", + "should-proxy": "~1.0", + "simple-get": "~4.0", + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/content-classifier": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.9.tgz", + "integrity": "sha512-PVJqwp5uvZE1PlpeJtb0p6al75fN+fmXGIC6DHcKysRnr0xo+sgz8X2r4mnNWdTWRqum2yVigMmmuXYTg3cJlQ==", + "dev": true, + "dependencies": { + "@antora/asciidoc-loader": "3.1.9", + "@antora/logger": "3.1.9", + "mime-types": "~2.1", + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/document-converter": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.9.tgz", + "integrity": "sha512-pH7tQaIjcPsFdYkaBEAvA/5ki04IQwQGHoR+2jadKdMl6P+J5KA1VzNnMgyIL6gHn7auJIkoOKadfItRB9lHGQ==", + "dev": true, + "dependencies": { + "@antora/asciidoc-loader": "3.1.9" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/expand-path-helper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-2.0.0.tgz", + "integrity": "sha512-CSMBGC+tI21VS2kGW3PV7T2kQTM5eT3f2GTPVLttwaNYbNxDve08en/huzszHJfxo11CcEs26Ostr0F2c1QqeA==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/@antora/file-publisher": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.9.tgz", + "integrity": "sha512-C0VwVjuFbE1CVpZDgwYR1gZCNr1tMw5vueyF9wHZH0KCqAsp9iwo7bwj8wKWMPogxcxdYhnAvtDJnYmYFCuDWQ==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0", + "@antora/user-require-helper": "~2.0", + "vinyl": "~3.0", + "yazl": "~2.5" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/logger": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.9.tgz", + "integrity": "sha512-MKuANodcX0lfRyiB+Rxl/Kv7UOxc2glzTYFoIoBB7uzxF0A+AhvUJDmpGQFRFN2ihxy99N3nLJmZpDebwXyE+A==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/navigation-builder": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", + "integrity": "sha512-zyl2yNjK31Dl6TRJgnoFb4Czwt9ar3wLTycAdMeZ+U/8YcAUHD8z7NCssPFFvZ0BbUr00NP+gbqDmCr6yz32NQ==", + "dev": true, + "dependencies": { + "@antora/asciidoc-loader": "3.1.9" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/page-composer": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.9.tgz", + "integrity": "sha512-X6Qj+J5dfFAGXoCAOaA+R6xRp8UoNMDHsRsB1dUTT2QNzk1Lrq6YkYyljdD2cxkWjLVqQ/pQSP+BJVNFGbqDAQ==", + "dev": true, + "dependencies": { + "@antora/logger": "3.1.9", + "handlebars": "~4.7", + "require-from-string": "~2.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/playbook-builder": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.9.tgz", + "integrity": "sha512-MJ/OWz4pReC98nygGTXC5bOL/TDDtCYpSkHFBz2ST4L6tuM8rv9c5+cp//JkwY/QlTOvcuJ0f2xq4a7a5nI7Qw==", + "dev": true, + "dependencies": { + "@iarna/toml": "~2.2", + "convict": "~6.2", + "js-yaml": "~4.1", + "json5": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/redirect-producer": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.9.tgz", + "integrity": "sha512-9OLwoMhqifsBxTebInh/5W16GdDsdj+YkKG3TiCASlAOYsDbuhbeRPFUlyKKSRkMrtKKnFgHR0Z3DNPXYlH2NQ==", + "dev": true, + "dependencies": { + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-generator": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.9.tgz", + "integrity": "sha512-YYESPG22tGX1CxRPSAr6acKILCO8JfGkM1OYc7Sw3D7ZvCy1YgZMAaTYK0T5yl9LXg+l/UZi1xq/Ej0qHnYQiw==", + "dev": true, + "dependencies": { + "@antora/asciidoc-loader": "3.1.9", + "@antora/content-aggregator": "3.1.9", + "@antora/content-classifier": "3.1.9", + "@antora/document-converter": "3.1.9", + "@antora/file-publisher": "3.1.9", + "@antora/logger": "3.1.9", + "@antora/navigation-builder": "3.1.9", + "@antora/page-composer": "3.1.9", + "@antora/playbook-builder": "3.1.9", + "@antora/redirect-producer": "3.1.9", + "@antora/site-mapper": "3.1.9", + "@antora/site-publisher": "3.1.9", + "@antora/ui-loader": "3.1.9", + "@antora/user-require-helper": "~2.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-mapper": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.9.tgz", + "integrity": "sha512-9FCObL+JIjBoby8z+beu2uuvAtCjm5EsEQt+16gCIMX1ktVP3W3gVsdRSvVcGcVEpizILFhMawkcQknZPUp5mg==", + "dev": true, + "dependencies": { + "@antora/content-classifier": "3.1.9", + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-publisher": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.9.tgz", + "integrity": "sha512-L5To8f4QswZliXu6yB6O7O8CuBbLctjNbxZqP3m0FP7VaOONp85ftzEq1BFEm4BXXSwH1n4ujZx1qGBHP9ooOQ==", + "dev": true, + "dependencies": { + "@antora/file-publisher": "3.1.9" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/ui-loader": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.9.tgz", + "integrity": "sha512-g0/9dRE5JVMYukIU3x+Rvr41bPdK3sUD2xQIAniRjE6usIZs1mEsTGshVKVEoOqqnSekXE85HVhybjNHsC+qbQ==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0", + "braces": "~3.0", + "cache-directory": "~2.0", + "fast-glob": "~3.3", + "hpagent": "~1.2", + "js-yaml": "~4.1", + "picomatch": "~4.0", + "should-proxy": "~1.0", + "simple-get": "~4.0", + "vinyl": "~3.0", + "yauzl": "~3.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/user-require-helper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-2.0.0.tgz", + "integrity": "sha512-5fMfBZfw4zLoFdDAPMQX6Frik90uvfD8rXOA4UpXPOUikkX4uT1Rk6m0/4oi8oS3fcjiIl0k/7Nc+eTxW5TcQQ==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0" + }, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/@asciidoctor/core": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.8.tgz", + "integrity": "sha512-oozXk7ZO1RAd/KLFLkKOhqTcG4GO3CV44WwOFg2gMcCsqCUTarvMT7xERIoWW2WurKbB0/ce+98r01p8xPOlBw==", + "dev": true, + "dependencies": { + "asciidoctor-opal-runtime": "0.3.3", + "unxhr": "1.0.1" + }, + "engines": { + "node": ">=8.11", + "npm": ">=5.0.0", + "yarn": ">=1.1.0" + } + }, + "node_modules/@asciidoctor/tabs": { + "version": "1.0.0-beta.6", + "resolved": "https://registry.npmjs.org/@asciidoctor/tabs/-/tabs-1.0.0-beta.6.tgz", + "integrity": "sha512-gGZnW7UfRXnbiyKNd9PpGKtSuD8+DsqaaTSbQ1dHVkZ76NaolLhdQg8RW6/xqN3pX1vWZEcF4e81+Oe9rNRWxg==", + "dev": true, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/antora": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/antora/-/antora-3.1.9.tgz", + "integrity": "sha512-MSNXZQWeM8jKZ9v8Nby4DTMoaMzWo6YnDw3etphFip1E56/prSAgbuJU7hcUoQg1NfOJNhiiseGI6wZR5v4u6g==", + "dev": true, + "dependencies": { + "@antora/cli": "3.1.9", + "@antora/site-generator": "3.1.9" + }, + "bin": { + "antora": "bin/antora" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/asciidoctor-opal-runtime": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/asciidoctor-opal-runtime/-/asciidoctor-opal-runtime-0.3.3.tgz", + "integrity": "sha512-/CEVNiOia8E5BMO9FLooo+Kv18K4+4JBFRJp8vUy/N5dMRAg+fRNV4HA+o6aoSC79jVU/aT5XvUpxSxSsTS8FQ==", + "dev": true, + "dependencies": { + "glob": "7.1.3", + "unxhr": "1.0.1" + }, + "engines": { + "node": ">=8.11" + } + }, + "node_modules/async-lock": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "dev": true + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/bare-events": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "dev": true, + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/cache-directory": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-directory/-/cache-directory-2.0.0.tgz", + "integrity": "sha512-7YKEapH+2Uikde8hySyfobXBqPKULDyHNl/lhKm7cKf/GJFdG/tU/WpLrOg2y9aUrQrWUilYqawFIiGJPS6gDA==", + "dev": true, + "dependencies": { + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", + "dev": true + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convict": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.4.tgz", + "integrity": "sha512-qN60BAwdMVdofckX7AlohVJ2x9UvjTNoKVXCL2LxFk1l7757EJqf1nySdMkPQer0bt8kQ5lQiyZ9/2NvrFBuwQ==", + "dev": true, + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "yargs-parser": "^20.2.7" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "dev": true + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true + }, + "node_modules/hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isomorphic-git": { + "version": "1.25.10", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.25.10.tgz", + "integrity": "sha512-IxGiaKBwAdcgBXwIcxJU6rHLk+NrzYaaPKXXQffcA0GW3IUrQXdUPDXDo+hkGVcYruuz/7JlGBiuaeTCgIgivQ==", + "dev": true, + "dependencies": { + "async-lock": "^1.4.1", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^3.4.0", + "sha.js": "^2.4.9", + "simple-get": "^4.0.1" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + } + }, + "node_modules/multi-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multi-progress/-/multi-progress-4.0.0.tgz", + "integrity": "sha512-9zcjyOou3FFCKPXsmkbC3ethv51SFPoA4dJD6TscIp2pUmy26kBDZW6h9XofPELrzseSkuD7r0V+emGEeo39Pg==", + "dev": true, + "peerDependencies": { + "progress": "^2.0.0" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pino": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", + "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dev": true, + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "dev": true, + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/should-proxy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/should-proxy/-/should-proxy-1.0.4.tgz", + "integrity": "sha512-RPQhIndEIVUCjkfkQ6rs6sOR6pkxJWCNdxtfG5pP0RVgUYbK5911kLTF0TNcCC0G3YCGd492rMollFT2aTd9iQ==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/sonic-boom": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/streamx": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", + "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "dev": true, + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", + "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "dev": true, + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/uglify-js": { + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unxhr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.0.1.tgz", + "integrity": "sha512-MAhukhVHyaLGDjyDYhy8gVjWJyhTECCdNsLwlMoGFoNJ3o79fpQhtQuzmAE4IxCMDwraF4cW8ZjpAV0m9CRQbg==", + "dev": true, + "engines": { + "node": ">=8.11" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vinyl": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", + "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", + "dev": true, + "dependencies": { + "clone": "^2.1.2", + "clone-stats": "^1.0.0", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yauzl": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.1.3.tgz", + "integrity": "sha512-JCCdmlJJWv7L0q/KylOekyRaUrdEoUxWkWVcgorosTROCFWiS9p2NNPE9Yb91ak7b1N5SxAZEliWpspbZccivw==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..43e357dfe --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "devDependencies": { + "@asciidoctor/tabs": "1.0.0-beta.6", + "antora": "3.1.9" + } +} diff --git a/site.playbook.yml b/site.playbook.yml new file mode 100644 index 000000000..613513475 --- /dev/null +++ b/site.playbook.yml @@ -0,0 +1,32 @@ +site: + url: https://localhost/ + title: Boost.MySQL docs + start_page: mysql::index.adoc + +asciidoc: + attributes: + # Enable pagination + page-pagination: '' + hide-toc: '' + extensions: + - '@asciidoctor/tabs' + +content: + sources: + - url: . + start_path: mysql + branches: HEAD + +ui: + bundle: + url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable + snapshot: true + supplemental_files: ./supplemental-ui + +output: + dir: ./out + +# https://docs.antora.org/antora/latest/playbook/runtime-log-failure-level/ +runtime: + log: + failure_level: error From 6071ea445a2cf8fee2b94f847a60d2c50c6ac44b Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 12:37:56 +0200 Subject: [PATCH 02/18] ignore node_modules --- .gitignore | 1 + package-lock.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3e2e996ba..b50bb9b37 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ compile_commands.json .cache/ __build*__/ __pycache__/ +node_modules/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 13780fcf1..e58da5d4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "asciidoc", + "name": "mysql", "lockfileVersion": 3, "requires": true, "packages": { From 378c42d422a7b1e8b68286852aa8b6e19541c8ce Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 12:55:54 +0200 Subject: [PATCH 03/18] script refactor --- doc/docca-asciidoc/docca_asciidoc.py | 87 ++++++++++------------------ 1 file changed, 29 insertions(+), 58 deletions(-) diff --git a/doc/docca-asciidoc/docca_asciidoc.py b/doc/docca-asciidoc/docca_asciidoc.py index ff6962de6..65a9619c1 100755 --- a/doc/docca-asciidoc/docca_asciidoc.py +++ b/doc/docca-asciidoc/docca_asciidoc.py @@ -19,6 +19,8 @@ from typing import Dict, Optional, List as PyList from os import makedirs +DEFAULT_TPLT_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')) + class Nullcontext(): def __init__(self): pass @@ -1166,22 +1168,13 @@ def parse_args(args): parser.add_argument( '-o', '--output', - action=AcceptOneorNone, - help='Output file; STDOUT by default') + required=True, + help='Output directory') parser.add_argument( '-c', '--config', action='append', default=[], help='Configuration files') - parser.add_argument( - '-T', '--template', - action=AcceptOneorNone, - help='Jinja2 template to use for output') - parser.add_argument( - '-I', '--include', - action='append', - default=[], - help='Directory with template partials') parser.add_argument( '-D', '--directory', action=AcceptOneorNone, @@ -1203,14 +1196,6 @@ def open_input(stdin, args, cwd): data_dir = data_dir or cwd return (file, ctx, data_dir) -def open_output(stdout, args): - if args.output: - file = open(args.output, 'w', encoding='utf-8') - ctx = file - else: - file = stdout - ctx = Nullcontext() - return (file, ctx) def load_configs(args): result = { @@ -1270,17 +1255,6 @@ def collect_data(parent_dir, refs) -> Dict[str, Entity]: return result -def docca_include_dir(script): - return os.path.join(os.path.dirname(script), 'include') - -def template_file_name(includes, args): - return (args.template - or os.path.join(includes, 'docca/quickbook.jinja2')) - -def collect_include_dirs(template, include_dir, args): - result = [os.path.dirname(template), include_dir] - result.extend(args.include) - return result def construct_environment(loader, config): env = jinja2.Environment( @@ -1339,22 +1313,22 @@ def construct_environment(loader, config): return env -def render(env: jinja2.Environment, file_name, output_file, entity): - template = env.get_template(os.path.basename(file_name)) - - makedirs(os.path.dirname(output_file), exist_ok=True) - with open(output_file, 'wt', encoding='utf-8') as f: - template.stream(entity=entity).dump(f) +def render(env: jinja2.Environment, template_file: str, output_dir: str, output_file: str, **kwargs): + output_path = os.path.join(output_dir, output_file) + template = env.get_template(template_file) + makedirs(output_dir, exist_ok=True) + with open(output_path, 'wt', encoding='utf-8') as f: + template.stream(**kwargs).dump(f) -def render_quickref(env: jinja2.Environment, **kwargs): - template = env.get_template(os.path.basename('quickref.jinja2')) - output_file = 'mysql/modules/ROOT/pages/reference.adoc' - with open(output_file, 'wt', encoding='utf-8') as f: - template.stream(**kwargs).dump(f) +def render_entities(env: jinja2.Environment, template_file: str, output_dir: str, entities: PyList[Entity]): + for e in entities: + print(f'Rendering {e.fully_qualified_name}') + render(env, template_file, output_dir, e.asciidoc_file, entity=e) + -def main(args, stdin, stdout, script): +def main(args, stdin): args = parse_args(args) file, ctx, data_dir = open_input(stdin, args, os.getcwd()) @@ -1362,39 +1336,37 @@ def main(args, stdin, stdout, script): refs = list(collect_compound_refs(file)) data = collect_data(data_dir, refs) + output_dir: str = args.output + config = load_configs(args) env = construct_environment( - jinja2.FileSystemLoader('templates'), config) + jinja2.FileSystemLoader(DEFAULT_TPLT_DIR), config) # Classes (including member types) classes = [e for e in data.values() if isinstance(e, Class) and e.access == Access.public] - for e in classes: - render(env, 'class.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + render_entities(env, 'class.jinja2', output_dir, classes) - # Functions. TODO: free functions + # Functions fns = [] for e in [e2 for e2 in data.values() if isinstance(e2, Compound)]: fns += [mem for mem in e.members.values() if isinstance(mem, OverloadSet) and mem.access == Access.public] - for e in fns: - # print(f'Rendering {e.fully_qualified_name}', flush=True) - render(env, 'overload-set.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + render_entities(env, 'overload-set.jinja2', output_dir, fns) # Type aliases type_alias = [e for e in data.values() if isinstance(e, TypeAlias)] - for e in type_alias: - # print(f'Rendering {e.fully_qualified_name}', flush=True) - render(env, 'type-alias.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + render_entities(env, 'type-alias.jinja2', output_dir, type_alias) # Enums enums = [e for e in data.values() if isinstance(e, Enum)] - for e in enums: - # print(f'Rendering {e.fully_qualified_name}', flush=True) - render(env, 'enum.jinja2', f'mysql/modules/ROOT/pages/{e.asciidoc_file}', e) + render_entities(env, 'enum.jinja2', output_dir, enums) # Quickref - render_quickref( + render( env, + 'quickref.jinja2', + output_dir, + 'reference.adoc', classes=classes, enums=enums, free_functions=[e for e in fns if isinstance(e.scope, Namespace)], @@ -1402,6 +1374,5 @@ def main(args, stdin, stdout, script): ) - if __name__ == '__main__': - main(sys.argv, sys.stdin, sys.stdout, os.path.realpath(__file__)) + main(sys.argv, sys.stdin) From 1b52c506823f5feeadbcc16c75e1e5312338d738 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 12:59:56 +0200 Subject: [PATCH 04/18] script path fixes --- doc/docca-asciidoc/docca_asciidoc.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/docca-asciidoc/docca_asciidoc.py b/doc/docca-asciidoc/docca_asciidoc.py index 65a9619c1..7e045a2cb 100755 --- a/doc/docca-asciidoc/docca_asciidoc.py +++ b/doc/docca-asciidoc/docca_asciidoc.py @@ -968,7 +968,6 @@ def resolve_references(self): assert self._description is not None node = self._description.find('.//xrefsect/..') if node is not None: - print(f'Got xrefsect for {self.name}') subnode = node.find('xrefsect') assert subnode is not None xreftitle = subnode.find('xreftitle') @@ -978,7 +977,6 @@ def resolve_references(self): assert xrefdescription is not None self.overload_specific = make_blocks(xrefdescription, self.index) node.remove(subnode) - print(self.overload_specific) else: self.overload_specific = [] super().resolve_references() @@ -1316,7 +1314,7 @@ def construct_environment(loader, config): def render(env: jinja2.Environment, template_file: str, output_dir: str, output_file: str, **kwargs): output_path = os.path.join(output_dir, output_file) template = env.get_template(template_file) - makedirs(output_dir, exist_ok=True) + makedirs(os.path.dirname(output_path), exist_ok=True) with open(output_path, 'wt', encoding='utf-8') as f: template.stream(**kwargs).dump(f) From 9b62ac59d99b6c436019ba5dc1f143e6c8992050 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 13:20:03 +0200 Subject: [PATCH 05/18] proper antora setup --- .gitignore | 3 ++- doc/adoc/mysql/modules/ROOT/nav.adoc | 2 +- site.playbook.yml => local-playbook.yml | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) rename site.playbook.yml => local-playbook.yml (84%) diff --git a/.gitignore b/.gitignore index b50bb9b37..982df3fbe 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ compile_commands.json .cache/ __build*__/ __pycache__/ -node_modules/ \ No newline at end of file +node_modules/ +doc/adoc/mysql/modules/reference/ \ No newline at end of file diff --git a/doc/adoc/mysql/modules/ROOT/nav.adoc b/doc/adoc/mysql/modules/ROOT/nav.adoc index 1fdce5430..3e983a602 100644 --- a/doc/adoc/mysql/modules/ROOT/nav.adoc +++ b/doc/adoc/mysql/modules/ROOT/nav.adoc @@ -1,4 +1,4 @@ * xref:index.adoc[Introduction] * xref:overview.adoc[] -* xref:reference.adoc[] +* xref:reference:reference.adoc[] diff --git a/site.playbook.yml b/local-playbook.yml similarity index 84% rename from site.playbook.yml rename to local-playbook.yml index 613513475..8cc412ce9 100644 --- a/site.playbook.yml +++ b/local-playbook.yml @@ -14,17 +14,17 @@ asciidoc: content: sources: - url: . - start_path: mysql + start_path: doc/adoc/mysql branches: HEAD ui: bundle: url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable snapshot: true - supplemental_files: ./supplemental-ui + supplemental_files: ./doc/supplemental-ui output: - dir: ./out + dir: ./private/out # https://docs.antora.org/antora/latest/playbook/runtime-log-failure-level/ runtime: From efa9c433266e8c40713ce8220bcadcc4455589cf Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 16:59:02 +0200 Subject: [PATCH 06/18] recover from branch --- doc/Jamfile | 8 +++-- include/boost/mysql/any_address.hpp | 45 ++++++++++------------------- 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/doc/Jamfile b/doc/Jamfile index 1d1243c4b..21ff739d7 100644 --- a/doc/Jamfile +++ b/doc/Jamfile @@ -10,6 +10,7 @@ project mysql/doc ; import boostbook ; import os ; +import path ; import ../../../tools/docca/docca.jam ; @@ -25,6 +26,9 @@ local doxygen_exclussions = src.hpp ; +local include-prefix = [ path.root $(__file__:D) [ path.pwd ] ] ; +include-prefix = [ path.native $(include-prefix:D)/include ] ; + docca.reference reference.qbk : xsl/custom-overrides.xsl @@ -37,6 +41,7 @@ docca.reference reference.qbk MACRO_EXPANSION=YES EXPAND_ONLY_PREDEF=YES SEARCH_INCLUDES=NO + STRIP_FROM_PATH=$(include-prefix) "PREDEFINED=\\ BOOST_MYSQL_DOXYGEN \\ __cpp_lib_string_view \\ @@ -74,7 +79,7 @@ docca.reference reference.qbk SKIP_FUNCTION_MACROS=NO OUTPUT_LANGUAGE=English ABBREVIATE_BRIEF= - INLINE_INHERITED_MEMB=YES + # INLINE_INHERITED_MEMB=YES AUTOLINK_SUPPORT=NO EXTRACT_ALL=NO EXTRACT_PRIVATE=NO @@ -90,7 +95,6 @@ docca.reference reference.qbk SHOW_USED_FILES=NO SHOW_FILES=NO SHOW_NAMESPACES=NO - CLASS_DIAGRAMS=NO QUIET=YES ; diff --git a/include/boost/mysql/any_address.hpp b/include/boost/mysql/any_address.hpp index f471d0e9b..cc11edc8e 100644 --- a/include/boost/mysql/any_address.hpp +++ b/include/boost/mysql/any_address.hpp @@ -99,29 +99,24 @@ class any_address public: /** - * \brief Constructs an empty address. - * \details Results in an address with `this->type() == address_type::host_and_port`, + * \brief Constructor. + * \xrefitem overload_specific "overload_specific" "overload_specific" + * Constructs an empty address. Results in an address with `this->type() == address_type::host_and_port`, * `this->hostname() == ""` and `this->port() == default_port`, which identifies * a server running on `localhost` using the default port. - * \par Exception safety - * No-throw guarantee. */ any_address() noexcept : any_address(address_type::host_and_port, std::string(), default_port) {} /** - * \brief Copy constructor. - * \par Exception safety - * Strong guarantee. Exceptions may be thrown by memory allocations. - * \par Object lifetimes - * `*this` and `other` will have independent lifetimes (regular value semantics). + * \xrefitem overload_specific "overload_specific" "overload_specific" + * Copy constructor. May throw on allocation failure. + * After construction, `*this` and `other` will have independent lifetimes (regular value semantics). */ any_address(const any_address& other) = default; /** - * \brief Move constructor. - * \details Leaves `other` in a valid but unspecified state. - * \par Exception safety - * No-throw guarantee. + * \xrefitem overload_specific "overload_specific" "overload_specific" + * Move constructor. Leaves `other` in a valid but unspecified state. */ any_address(any_address&& other) = default; @@ -146,15 +141,11 @@ class any_address ~any_address() = default; /** - * \brief Constructs an address containing a host and a port. - * \details Results in an address with `this->type() == address_type::host_and_port`, + * \xrefitem overload_specific "overload_specific" "overload_specific" + * Constructs an address containing a host and a port. + * Results in an address with `this->type() == address_type::host_and_port`, * `this->hostname() == value.hostname()` and `this->port() == value.port()`. - * - * \par Object lifetimes - * `*this` and `value` will have independent lifetimes (regular value semantics). - * - * \par Exception safety - * No-throw guarantee. + * After construction, `*this` and `value` will have independent lifetimes (regular value semantics). */ any_address(host_and_port value) noexcept : impl_{address_type::host_and_port, std::move(value.host), value.port} @@ -162,15 +153,11 @@ class any_address } /** - * \brief Constructs an address containing a UNIX socket path. - * \details Results in an address with `this->type() == address_type::unix_path`, + * \xrefitem overload_specific "overload_specific" "overload_specific" + * Constructs an address containing a UNIX socket path. + * Results in an address with `this->type() == address_type::unix_path`, * `this->unix_socket_path() == value.path()`. - * - * \par Object lifetimes - * `*this` and `value` will have independent lifetimes (regular value semantics). - * - * \par Exception safety - * No-throw guarantee. + * After construction, `*this` and `value` will have independent lifetimes (regular value semantics). */ any_address(unix_path value) noexcept : impl_{address_type::unix_path, std::move(value.path), 0} {} From 663904eaef964bd642b3436cadd42af2748ac664 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 17:03:16 +0200 Subject: [PATCH 07/18] header_file macro --- doc/docca-asciidoc/templates/class.jinja2 | 6 +++--- doc/docca-asciidoc/templates/common.jinja2 | 4 ++++ doc/docca-asciidoc/templates/enum.jinja2 | 4 ++-- doc/docca-asciidoc/templates/type-alias.jinja2 | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/doc/docca-asciidoc/templates/class.jinja2 b/doc/docca-asciidoc/templates/class.jinja2 index 917ce8bcd..771573c29 100644 --- a/doc/docca-asciidoc/templates/class.jinja2 +++ b/doc/docca-asciidoc/templates/class.jinja2 @@ -1,9 +1,9 @@ -{% from "common.jinja2" import description, link, template_parameters, phrase %} +{% from "common.jinja2" import description, link, template_parameters, phrase, header_file %} -== boost::mysql::{{ entity.name }} +== {{ entity.fully_qualified_name }} -Defined in header [link-to-entity bg-white]`<{{ entity.location.file.replace('libs/mysql/include/', '') }}>` +{{ header_file(entity) }} {{ description(entity.brief) }} diff --git a/doc/docca-asciidoc/templates/common.jinja2 b/doc/docca-asciidoc/templates/common.jinja2 index 125b85a62..988e78c73 100644 --- a/doc/docca-asciidoc/templates/common.jinja2 +++ b/doc/docca-asciidoc/templates/common.jinja2 @@ -2,6 +2,10 @@ {{ s.replace("[", "\\[").replace("]", "\\]") }} {%- endmacro %} +{%- macro header_file(e) -%} + Defined in header [link-to-entity bg-white]`<{{ e.location.file }}>` +{%- endmacro -%} + {% macro subsection(sub) -%} {% if sub.title %} diff --git a/doc/docca-asciidoc/templates/enum.jinja2 b/doc/docca-asciidoc/templates/enum.jinja2 index a754fdf4b..6d21b0a61 100644 --- a/doc/docca-asciidoc/templates/enum.jinja2 +++ b/doc/docca-asciidoc/templates/enum.jinja2 @@ -1,9 +1,9 @@ -{% from "common.jinja2" import phrase, template_parameters, description %} +{% from "common.jinja2" import phrase, template_parameters, description, header_file %} == {{ entity.fully_qualified_name }} -Defined in header [link-to-entity bg-white]`<{{ entity.location.file.replace('libs/mysql/include/', '') }}>` +{{ header_file(entity) }} [source, cpp, subs="+macros", role="raw-code"] ---- diff --git a/doc/docca-asciidoc/templates/type-alias.jinja2 b/doc/docca-asciidoc/templates/type-alias.jinja2 index f693c3a4b..d99ac797e 100644 --- a/doc/docca-asciidoc/templates/type-alias.jinja2 +++ b/doc/docca-asciidoc/templates/type-alias.jinja2 @@ -1,9 +1,9 @@ -{% from "common.jinja2" import phrase, template_parameters, description %} +{% from "common.jinja2" import phrase, template_parameters, description, header_file %} == {{ entity.fully_qualified_name }} -Defined in header [link-to-entity bg-white]`<{{ entity.location.file.replace('libs/mysql/include/', '') }}>` +{{ header_file(entity) }} [source, cpp, subs="+macros", role="raw-code"] ---- From 79417d2be82d8b35351d8ee1105f1b06a6f4b395 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 17:07:18 +0200 Subject: [PATCH 08/18] header linking --- doc/docca-asciidoc/templates/common.jinja2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/docca-asciidoc/templates/common.jinja2 b/doc/docca-asciidoc/templates/common.jinja2 index 988e78c73..ba858a2bd 100644 --- a/doc/docca-asciidoc/templates/common.jinja2 +++ b/doc/docca-asciidoc/templates/common.jinja2 @@ -3,7 +3,7 @@ {%- endmacro %} {%- macro header_file(e) -%} - Defined in header [link-to-entity bg-white]`<{{ e.location.file }}>` + Defined in header [link-to-entity bg-white]`` {%- endmacro -%} From 62a67bf41865312752421494ce90bdc395909542 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 17:22:05 +0200 Subject: [PATCH 09/18] namespace scope variables --- doc/docca-asciidoc/docca_asciidoc.py | 26 ++++++++++----- doc/docca-asciidoc/templates/quickref.jinja2 | 5 +++ doc/docca-asciidoc/templates/variable.jinja2 | 34 ++++++++++++++++++++ 3 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 doc/docca-asciidoc/templates/variable.jinja2 diff --git a/doc/docca-asciidoc/docca_asciidoc.py b/doc/docca-asciidoc/docca_asciidoc.py index 7e045a2cb..08e646d96 100755 --- a/doc/docca-asciidoc/docca_asciidoc.py +++ b/doc/docca-asciidoc/docca_asciidoc.py @@ -577,6 +577,10 @@ def __init__(self, element: ET.Element, scope, index=dict()): self.index = index index[self.id] = self + + + def __repr__(self) -> str: + return f'{type(self).__name__}({self.fully_qualified_name})' @property @@ -932,13 +936,6 @@ def __init__(self, element: ET.Element, section, parent, index=dict()): self._parameters = element.findall('param') - def __repr__(self) -> str: - return 'Function({})'.format(json.dumps({ - 'id': self.id, - 'name': self.name, - 'brief': str(self.brief) if hasattr(self, 'brief') else '', - }, indent=4)) - @property def kind(self): if self.is_friend: @@ -1048,6 +1045,9 @@ def __init__(self, funcs): self.funcs = funcs assert len(funcs) self._resort() + + def __repr__(self) -> str: + return f'OverloadSet({self.fully_qualified_name})' def append(self, func): self.funcs.append(func) @@ -1321,7 +1321,7 @@ def render(env: jinja2.Environment, template_file: str, output_dir: str, output_ def render_entities(env: jinja2.Environment, template_file: str, output_dir: str, entities: PyList[Entity]): for e in entities: - print(f'Rendering {e.fully_qualified_name}') + print(f'Rendering {e}') render(env, template_file, output_dir, e.asciidoc_file, entity=e) @@ -1341,6 +1341,9 @@ def main(args, stdin): env = construct_environment( jinja2.FileSystemLoader(DEFAULT_TPLT_DIR), config) + # Namespaces (not rendered directly) + namespaces = [e for e in data.values() if isinstance(e, Namespace)] + # Classes (including member types) classes = [e for e in data.values() if isinstance(e, Class) and e.access == Access.public] render_entities(env, 'class.jinja2', output_dir, classes) @@ -1358,6 +1361,12 @@ def main(args, stdin): # Enums enums = [e for e in data.values() if isinstance(e, Enum)] render_entities(env, 'enum.jinja2', output_dir, enums) + + # Constants + constants = [] + for ns in namespaces: + constants += [e for e in ns.members.values() if isinstance(e, Variable)] + render_entities(env, 'variable.jinja2', output_dir, constants) # Quickref render( @@ -1369,6 +1378,7 @@ def main(args, stdin): enums=enums, free_functions=[e for e in fns if isinstance(e.scope, Namespace)], type_aliases=[e for e in type_alias if isinstance(e.scope, Namespace)], + constants=constants ) diff --git a/doc/docca-asciidoc/templates/quickref.jinja2 b/doc/docca-asciidoc/templates/quickref.jinja2 index 63c96a7e4..53b6183a0 100644 --- a/doc/docca-asciidoc/templates/quickref.jinja2 +++ b/doc/docca-asciidoc/templates/quickref.jinja2 @@ -37,6 +37,11 @@ a| [.pb-1]*Enumerations* {{ reflink(e) }} {%- endfor %} +[.pb-1]*Constants* + +{% for e in constants | sort -%} +{{ reflink(e) }} +{%- endfor %} |=== diff --git a/doc/docca-asciidoc/templates/variable.jinja2 b/doc/docca-asciidoc/templates/variable.jinja2 new file mode 100644 index 000000000..f99843b4c --- /dev/null +++ b/doc/docca-asciidoc/templates/variable.jinja2 @@ -0,0 +1,34 @@ +{% from "common.jinja2" import phrase, template_parameters, description, header_file %} + +== {{ entity.fully_qualified_name }} + + +{{ header_file(entity) }} + +[source, cpp, subs="+macros", role="raw-code"] +---- +{{ template_parameters(entity) }} +{%- set qualifiers = [] -%} +{%- if entity.is_static -%} + {%- set qualifiers = qualifiers + ['static'] -%} +{%- endif -%} +{%- if entity.is_constexpr -%} + {%- set qualifiers = qualifiers + ['constexpr'] -%} +{%- endif -%} +{%- if entity.is_inline -%} + {%- set qualifiers = qualifiers + ['inline'] -%} +{%- endif -%} + +{%- if qualifiers | length -%} + {{ qualifiers | join(' ') }}{{' '}} +{%- endif -%} + +{{ phrase(entity.type) }} {{ entity.name }} +{%- if entity.value %} {{ phrase(entity.value) }}{% endif -%} +; +---- + +{{ description(entity.brief) }} + +{{ description(entity.description) }} + From a148863d4752342d27ee7d64d91be8eaf3b2cf84 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 18:06:58 +0200 Subject: [PATCH 10/18] Data members --- doc/docca-asciidoc/templates/class.jinja2 | 30 +++++++++++++++++++++++ doc/supplemental-ui/css/custom.css | 7 +++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/doc/docca-asciidoc/templates/class.jinja2 b/doc/docca-asciidoc/templates/class.jinja2 index 771573c29..c8a471448 100644 --- a/doc/docca-asciidoc/templates/class.jinja2 +++ b/doc/docca-asciidoc/templates/class.jinja2 @@ -55,6 +55,8 @@ {%- endfor -%} + + {% for fn in entity.public_static_functions %} {% if loop.first %} === Static functions @@ -68,5 +70,33 @@ {% if loop.last %} |=== {% endif %} +{%- endfor -%} + + +{% for mem in entity.members.values() + | select("Variable") + | selectattr("access", "eq", Access.public) + | selectattr("is_static", "eq", False) %} + +{% if loop.first %} +=== Data members + +[cols="1", grid=none, frame=none, role="mt-0 space-rows"] +|=== +{% endif %} +.^a| +[source, cpp, subs="+macros"] +---- +{{ phrase(mem.type) }} {{ mem.name }}{%- if mem.value %} {{ phrase(mem.value) }} {%- endif -%}; +---- + + +{{ description(mem.brief) }} + +{{ description(mem.description) }} + +{% if loop.last %} +|=== +{% endif %} {%- endfor -%} diff --git a/doc/supplemental-ui/css/custom.css b/doc/supplemental-ui/css/custom.css index 8a96fa99e..8fb8a275a 100644 --- a/doc/supplemental-ui/css/custom.css +++ b/doc/supplemental-ui/css/custom.css @@ -25,7 +25,12 @@ } .pb-1 { - padding-bottom: 1vh; + padding-bottom: 1vh !important; +} + +.space-rows td { + padding-top: 2em !important; + padding-bottom: 2em !important; } .indent { From c37b50981a57db516990c9497a62f4720b8adde8 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 18:09:06 +0200 Subject: [PATCH 11/18] Fix UrlLink --- doc/docca-asciidoc/templates/common.jinja2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/docca-asciidoc/templates/common.jinja2 b/doc/docca-asciidoc/templates/common.jinja2 index ba858a2bd..c03501336 100644 --- a/doc/docca-asciidoc/templates/common.jinja2 +++ b/doc/docca-asciidoc/templates/common.jinja2 @@ -111,7 +111,7 @@ {%- elif part is EntityRef -%} {{ link(part.entity, part.entity.name) }} {%- elif part is UrlLink -%} - [@{{ part.url }} {{ phrase(part, in_code=in_code) }}] + {{ part.url }}:[{{ phrase(part, in_code=in_code) }}] {%- elif part is Linebreak %}{# indent is intentional here #} {% elif part is Phrase -%} From b65d8b07385631d95ea31405bd888928fbf93d59 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 18:19:21 +0200 Subject: [PATCH 12/18] Linking to member variables --- doc/docca-asciidoc/templates/class.jinja2 | 2 +- doc/docca-asciidoc/templates/common.jinja2 | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/docca-asciidoc/templates/class.jinja2 b/doc/docca-asciidoc/templates/class.jinja2 index c8a471448..a87a92fcf 100644 --- a/doc/docca-asciidoc/templates/class.jinja2 +++ b/doc/docca-asciidoc/templates/class.jinja2 @@ -86,7 +86,7 @@ |=== {% endif %} .^a| -[source, cpp, subs="+macros"] +[source, cpp, subs="+macros", id={{ mem.name }}] ---- {{ phrase(mem.type) }} {{ mem.name }}{%- if mem.value %} {{ phrase(mem.value) }} {%- endif -%}; ---- diff --git a/doc/docca-asciidoc/templates/common.jinja2 b/doc/docca-asciidoc/templates/common.jinja2 index c03501336..85392550d 100644 --- a/doc/docca-asciidoc/templates/common.jinja2 +++ b/doc/docca-asciidoc/templates/common.jinja2 @@ -39,6 +39,8 @@ {% macro link(entity, text) -%} {%- if entity is Enumerator -%} {{ link(entity.enum, text) }} + {%- elif entity is Variable and entity.scope is Class -%} + xref:{{ entity.scope.asciidoc_file }}#{{ entity.name }}[{{ text }}] {%- else -%} xref:{{ entity.asciidoc_file }}[{{ text }}] {%- endif -%} From a835fdae044450e385a71ef709ce6d897259be2d Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 18:22:32 +0200 Subject: [PATCH 13/18] better qualifying --- doc/docca-asciidoc/templates/common.jinja2 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/docca-asciidoc/templates/common.jinja2 b/doc/docca-asciidoc/templates/common.jinja2 index 85392550d..bf6dae7fe 100644 --- a/doc/docca-asciidoc/templates/common.jinja2 +++ b/doc/docca-asciidoc/templates/common.jinja2 @@ -111,7 +111,12 @@ {%- elif part is Strong -%} *{{ phrase(part, in_code=in_code) }}* {%- elif part is EntityRef -%} - {{ link(part.entity, part.entity.name) }} + {# Qualify only entities that are not in a namespace #} + {%- if part.entity.scope is Namespace -%} + {{ link(part.entity, part.entity.name) }} + {%- else -%} + {{ link(part.entity, part.entity.scope.name + '::' + part.entity.name) }} + {%- endif -%} {%- elif part is UrlLink -%} {{ part.url }}:[{{ phrase(part, in_code=in_code) }}] {%- elif part is Linebreak %}{# indent is intentional here #} From 7697ebc4648427a35e9a6ef1ca76eea87b4a8873 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 18:26:29 +0200 Subject: [PATCH 14/18] Remove rendering of specializations --- doc/docca-asciidoc/docca_asciidoc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/docca-asciidoc/docca_asciidoc.py b/doc/docca-asciidoc/docca_asciidoc.py index 08e646d96..d49172a73 100755 --- a/doc/docca-asciidoc/docca_asciidoc.py +++ b/doc/docca-asciidoc/docca_asciidoc.py @@ -1345,7 +1345,9 @@ def main(args, stdin): namespaces = [e for e in data.values() if isinstance(e, Namespace)] # Classes (including member types) - classes = [e for e in data.values() if isinstance(e, Class) and e.access == Access.public] + classes = [e for e in data.values() + if isinstance(e, Class) and e.access == Access.public and + not e.is_specialization] render_entities(env, 'class.jinja2', output_dir, classes) # Functions From 28e8065229a365825f028a8ad4477c5ff25b29fc Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 18:33:26 +0200 Subject: [PATCH 15/18] static variables --- doc/docca-asciidoc/templates/class.jinja2 | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/doc/docca-asciidoc/templates/class.jinja2 b/doc/docca-asciidoc/templates/class.jinja2 index a87a92fcf..a49a3f512 100644 --- a/doc/docca-asciidoc/templates/class.jinja2 +++ b/doc/docca-asciidoc/templates/class.jinja2 @@ -100,3 +100,41 @@ |=== {% endif %} {%- endfor -%} + + +{# TODO: this is duplicate #} +{% for mem in entity.members.values() + | select("Variable") + | selectattr("access", "eq", Access.public) + | selectattr("is_static", "eq", True) %} + +{% if loop.first %} +=== Static data members + +[cols="1", grid=none, frame=none, role="mt-0 space-rows"] +|=== +{% endif %} +.^a| +[source, cpp, subs="+macros", id={{ mem.name }}] +---- +{{ template_parameters(mem) }} +{%- set qualifiers = ['static'] -%} +{%- if mem.is_constexpr -%} + {%- set qualifiers = qualifiers + ['constexpr'] -%} +{%- endif -%} +{%- if mem.is_inline -%} + {%- set qualifiers = qualifiers + ['inline'] -%} +{%- endif -%} + +{{ qualifiers | join(' ') }} {{ phrase(mem.type) }} {{ mem.name }}{%- if mem.value %} {{ phrase(mem.value) }} {%- endif -%}; +---- + + +{{ description(mem.brief) }} + +{{ description(mem.description) }} + +{% if loop.last %} +|=== +{% endif %} +{%- endfor -%} \ No newline at end of file From 37d5abc15517184b19fcf66c19d2c572360b7600 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 18:33:45 +0200 Subject: [PATCH 16/18] any_connection_params template friendliness --- include/boost/mysql/any_connection.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/mysql/any_connection.hpp b/include/boost/mysql/any_connection.hpp index 98cad7c62..24c6b2c86 100644 --- a/include/boost/mysql/any_connection.hpp +++ b/include/boost/mysql/any_connection.hpp @@ -75,8 +75,7 @@ struct any_connection_params * If the connection is configured to use TLS and this member is `nullptr`, * an internal `asio::ssl::context` object with suitable default options * will be created. - * - * \par Object lifetimes + * \n * If set to non-null, the pointee object must be kept alive until * all \ref any_connection objects constructed from `*this` are destroyed. */ From be07f1b92d43f1df05f90825793ffc055fcb8263 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 23:26:53 +0200 Subject: [PATCH 17/18] Move docca to its repo --- doc/docca-asciidoc/docca_asciidoc.py | 1388 ----------------- doc/docca-asciidoc/templates/class.jinja2 | 140 -- doc/docca-asciidoc/templates/common.jinja2 | 182 --- doc/docca-asciidoc/templates/enum.jinja2 | 34 - .../templates/overload-set.jinja2 | 80 - doc/docca-asciidoc/templates/quickref.jinja2 | 47 - .../templates/type-alias.jinja2 | 17 - doc/docca-asciidoc/templates/variable.jinja2 | 34 - 8 files changed, 1922 deletions(-) delete mode 100755 doc/docca-asciidoc/docca_asciidoc.py delete mode 100644 doc/docca-asciidoc/templates/class.jinja2 delete mode 100644 doc/docca-asciidoc/templates/common.jinja2 delete mode 100644 doc/docca-asciidoc/templates/enum.jinja2 delete mode 100644 doc/docca-asciidoc/templates/overload-set.jinja2 delete mode 100644 doc/docca-asciidoc/templates/quickref.jinja2 delete mode 100644 doc/docca-asciidoc/templates/type-alias.jinja2 delete mode 100644 doc/docca-asciidoc/templates/variable.jinja2 diff --git a/doc/docca-asciidoc/docca_asciidoc.py b/doc/docca-asciidoc/docca_asciidoc.py deleted file mode 100755 index d49172a73..000000000 --- a/doc/docca-asciidoc/docca_asciidoc.py +++ /dev/null @@ -1,1388 +0,0 @@ -#!/usr/bin/env python - -# -# Copyright (c) 2024 Dmitry Arkhipov (grisumbras@yandex.ru) -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -# -# Official repository: https://github.com/boostorg/json -# - -import argparse -import jinja2 -import json -import io -import os.path -import sys -import xml.etree.ElementTree as ET -from typing import Dict, Optional, List as PyList -from os import makedirs - -DEFAULT_TPLT_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')) - -class Nullcontext(): - def __init__(self): - pass - - def __enter__(self): - pass - - def __exit__(self, exc_type, exc_value, traceback): - pass - - -class Access: - public = 'public' - protected = 'protected' - private = 'private' - -class FunctionKind: - static = 'static' - nonstatic = 'nonstatic' - friend = 'friend' - free = 'free' - -class VirtualKind: - nonvirtual = 'non-virtual' - purevirtual = 'pure-virtual' - virtual = 'virtual' - - -class Linebreak(): - pass - -class PhraseContainer: - def __init__(self, parts): - self._parts = parts - - def __getitem__(self, pos): - return self._parts[pos] - - def __setitem__(self, pos, val): - self._parts[pos] = val - - def __len__(self): - return len(self._parts) - -class Phrase(PhraseContainer): - @property - def text(self): - return ''.join(( - part if isinstance(part, str) - else '' if isinstance(part, Linebreak) - else part.text - for part in self - )) - -class Emphasised(Phrase): - pass - -class Monospaced(Phrase): - pass - -class Strong(Phrase): - pass - -class EntityRef(Phrase): - def __init__(self, entity, parts): - super().__init__(parts) - self.entity = entity - - @property - def text(self): - result = super().text - if not result: - result = self.entity.fully_qualified_name - return result - -class UrlLink(Phrase): - def __init__(self, url, parts): - super().__init__(parts) - self.url = url - assert url - - @property - def text(self): - result = super().text - if not result: - result = self.url - return result - - -class Block: - pass - -class Paragraph(PhraseContainer, Block): - def __init__(self, parts): - super().__init__(parts) - - def __getitem__(self, pos): - return self._parts[pos] - - def __len__(self): - return len(self._parts) - - @property - def text(self): - return ''.join([ - (p if isinstance(p, str) else p.text) for p in self._parts - ]) - -class List(Block): - Arabic = '1' - LowerLatin = 'a' - UpperLatin = 'A' - LowerRoman = 'i' - UpperRoman = 'I' - - def __init__(self, kind, items): - self.kind = kind - self.is_ordered = kind is not None - self._items = items - - def __getitem__(self, pos): - return self._items[pos] - - def __len__(self): - return len(self._items) - -class ListItem(Block): - def __init__(self, blocks): - assert blocks - self._blocks = blocks - - def __getitem__(self, pos): - return self._blocks[pos] - - def __len__(self): - return len(self.blocks) - -class Section(Block): - See = 'see' - Returns = 'return' - Author = 'author' - Authors = 'authors' - Version = 'version' - Since = 'since' - Date = 'date' - Note = 'note' - Warning = 'warning' - Preconditions = 'pre' - Postconditions = 'post' - Copyright = 'copyright' - Invariants = 'invariant' - Remarks = 'remark' - Attention = 'attention' - Custom = 'par' - RCS = 'rcs' - - def __init__(self, kind, title, blocks): - self.kind = kind - self.title = title - self._blocks = blocks - - def __getitem__(self, pos): - return self._blocks[pos] - - def __len__(self): - return len(self._blocks) - -class ParameterList(Block): - Parameters = 'param' - ReturnValues = 'retval' - Exceptions = 'exception' - TemplateParameters = 'templateparam' - - def __init__(self, kind, items): - self.kind = kind - self._items = items - - def __getitem__(self, pos): - return self._items[pos] - - def __len__(self): - return len(self._items) - -class ParameterDescription(Block): - def __init__(self, description, params): - self.description = description - self._params = params - - def __getitem__(self, pos): - return self._params[pos] - - def __len__(self): - return len(self._params) - -class ParameterItem(Block): - def __init__(self, type, name, direction): - self.type = type - self.name = name - self.direction = direction - - @property - def is_in(self): - return self.direction in ('in', 'inout') - - @property - def is_out(self): - return self.direction in ('out', 'inout') - -class CodeBlock(Block): - def __init__(self, lines): - self._lines = lines - - def __getitem__(self, pos): - return self._lines[pos] - - def __len__(self): - return len(self._lines) - -class Table(Block): - def __init__(self, cols, rows, caption=None, width=None): - self.cols = cols - self.width = width - self.caption = caption - self._rows = rows - - def __getitem__(self, pos): - return self._rows[pos] - - def __len__(self): - return len(self._rows) - -class Cell(Block): - def __init__( - self, blocks, - col_span=1, row_span=1, is_header=False, horizontal_align=None, - vertical_align=None, width=None, role=None - ): - self._blocks = blocks - - self.col_span = int(col_span or 1) - self.row_span = int(row_span or 1) - self.is_header = is_header or False - self.horizontal_align = horizontal_align - self.vertical_align = vertical_align - self.width = width - self.role = role - - def __getitem__(self, pos): - return self._blocks[pos] - - def __len__(self): - return len(self._blocks) - - -def make_blocks(element : Optional[ET.Element], index) -> PyList[Block]: - if element is None: - return [] - - result = [] - cur_para = [] - - def finish_paragraph(cur_para): - if cur_para: - if isinstance(cur_para[0], str): - cur_para[0] = cur_para[0].lstrip() - if not cur_para[0]: - cur_para = cur_para[1:] - if cur_para: - if isinstance(cur_para[-1], str): - cur_para[-1] = cur_para[-1].rstrip() - if not cur_para[-1]: - cur_para = cur_para[:-1] - - # spaces after linebreaks usually cause issues - for n in range(1, len(cur_para)): - if (isinstance(cur_para[n - 1], Linebreak) - and isinstance(cur_para[n], str)): - cur_para[n] = cur_para[n].lstrip() - - if cur_para: - result.append(Paragraph(cur_para)) - - return [] - - if element.text: - cur_para.append(remove_endlines(element.text)) - - for child in element: - func = { - 'itemizedlist': make_list, - 'simplesect': make_section, - 'programlisting': make_codeblock, - 'parameterlist': make_parameters, - 'table': make_table, - }.get(child.tag) - if func: - cur_para = finish_paragraph(cur_para) - result.append(func(child, index)) - elif child.tag == 'para': - cur_para = finish_paragraph(cur_para) - result.extend(make_blocks(child, index)) - else: - cur_para.append(make_phrase(child, index)) - if child.tail: - cur_para.append(remove_endlines(child.tail)) - - finish_paragraph(cur_para) - return result - -def make_list(element, index): - items = [] - for child in element: - assert child.tag == 'listitem' - items.append(make_blocks(child, index)) - return List(element.get('type'), items) - -def make_parameters(element, index): - result = [] - descr = None - kind = element.get('kind') - for descr_block in element: - assert descr_block.tag == 'parameteritem' - descr = None - params = [] - for item in descr_block: - if item.tag == 'parameterdescription': - assert descr == None - descr = item - continue - - assert item.tag == 'parameternamelist' - - name = item.find('parametername') - direction = name.get('direction') if name is not None else None - params.append( - ParameterItem( - text_with_refs(item.find('parametertype'), index), - text_with_refs(name, index), - direction)) - - assert descr is not None - result.append(ParameterDescription(make_blocks(descr, index), params)) - return ParameterList(kind, result) - -def make_section(element, index): - title = None - if len(element) and element[0].tag == 'title': - title = phrase_content(element[0], index) - title = Paragraph(title or []) - - kind = element.get('kind') - - parts = [] - for child in element: - if child.tag == 'para': - parts.extend(make_blocks(child, index)) - - return Section(kind, title, parts) - -def make_codeblock(element, index): - lines = [] - for line in element: - assert line.tag == 'codeline' - text = '' - for hl in line: - assert hl.tag == 'highlight' - if hl.text: - text += hl.text - - for part in hl: - if part.tag == 'sp': - text += ' ' - elif part.tag == 'ref': - text += part.text or '' - if part.tail: - text += part.tail - if hl.tail: - text += hl.tail - lines.append(text) - - return CodeBlock(lines) - -def make_table(element, index): - cols = element.get('cols') - - caption = None - if len(element) and element[0].tag == 'caption': - caption = phrase_content(element[0], index) - caption = Paragraph(caption or []) - - rows = [] - for row in element[(1 if caption else 0):]: - assert row.tag == 'row' - cells = [] - for cell in row: - cells.append(Cell( - make_blocks(cell, index), - col_span=cell.get('colspan'), - row_span=cell.get('rowspan'), - is_header=cell.get('thead'), - horizontal_align=cell.get('align'), - vertical_align=cell.get('valign'), - width=cell.get('width'), - role=cell.get('class'), - )) - rows.append(cells) - - return Table(cols, rows, caption) - -def phrase_content(element, index, allow_missing_refs=False): - if element is None: - return [] - - result = [] - if element.text: - result.append(remove_endlines(element.text)) - - for child in element: - result.append( - make_phrase(child, index, allow_missing_refs=allow_missing_refs)) - if child.tail: - result.append(remove_endlines(child.tail)) - - return result - -def make_phrase(element, index, allow_missing_refs=False): - func = { - 'bold': make_strong, - 'computeroutput': make_monospaced, - 'verbatim': make_monospaced, - 'emphasis': make_emphasised, - 'ulink': make_url_link, - 'linebreak': make_linebreak, - 'ref': make_entity_reference, - }[element.tag] - return func(element, index, allow_missing_refs=allow_missing_refs) - -def make_strong(element, index, allow_missing_refs=False): - return Strong( - phrase_content(element, index, allow_missing_refs=allow_missing_refs)) - -def make_monospaced(element, index, allow_missing_refs=False): - return Monospaced( - phrase_content(element, index, allow_missing_refs=allow_missing_refs)) - -def make_emphasised(element, index, allow_missing_refs=False): - return Emphasised( - phrase_content(element, index, allow_missing_refs=allow_missing_refs)) - -def make_url_link(element, index, allow_missing_refs=False): - return UrlLink( - element.get('url'), - phrase_content(element, index, allow_missing_refs=allow_missing_refs)) - -def make_linebreak(element, index, allow_missing_refs=None): - return Linebreak() - -def make_entity_reference( - element, index, refid=None, allow_missing_refs=False -): - refid = refid or element.get('refid') - assert refid - - target = index.get(refid) - if target: - return EntityRef( - target, - phrase_content( - element, index, allow_missing_refs=allow_missing_refs)) - - if allow_missing_refs: - return Phrase(phrase_content(element, index, allow_missing_refs=True)) - -def text_with_refs(element, index): - return Phrase(phrase_content(element, index, allow_missing_refs=True)) - -def resolve_type(element, index): - result = text_with_refs(element, index) - if ( - result - and isinstance(result[0], str) - and result[0].startswith('constexpr') - ): - result[0] = result[0][len('constexpr'):].lstrip() - return result - -_chartable = { - ord('\r'): None, - ord('\n'): None, -} -def remove_endlines(s): - return s.translate(_chartable) - - -class Location(): - def __init__(self, elem): - self.file = elem.get('file') - - self.line = elem.get('line') - if self.line: - self.line = int(self.line) - - self.column = elem.get('column') - if self.column : - self.column = int(self.column) - - -class Entity(): - access = Access.public - - nametag: str - - @staticmethod - def _sanitize_path_segment(s: str) -> str: - return s.replace("[", "-lb") \ - .replace("]", "-rb")\ - .replace("(", "-lp")\ - .replace(")", "-rp")\ - .replace("<=>", "-spshp")\ - .replace("->", "-arrow")\ - .replace("operator>", "operator-gt")\ - .replace("operator~", "operator-bnot")\ - .replace("=", "-eq")\ - .replace("!", "-not")\ - .replace("+", "-plus")\ - .replace("&", "-and")\ - .replace("|", "-or")\ - .replace("^", "-xor")\ - .replace("*", "-star")\ - .replace("/", "-slash")\ - .replace("%", "-mod")\ - .replace("<", "-lt")\ - .replace(">", "-gt")\ - .replace("~", "dtor-")\ - .replace(",", "-comma")\ - .replace(":", "-")\ - .replace(" ", "-") - - def __init__(self, element: ET.Element, scope, index=dict()): - self.id = element.get('id', '') - assert self.id - - self.scope = scope - - self.name = ''.join( element.find(self.nametag).itertext() ) - - self.groups = [] - - loc = element.find('location') - self._location = Location(loc) if (loc is not None) else None - - self._brief = element.find('briefdescription') - self._description = element.find('detaileddescription') - - self.index = index - index[self.id] = self - - - def __repr__(self) -> str: - return f'{type(self).__name__}({self.fully_qualified_name})' - - - @property - def location(self): - return ( - self._location - or (self.scope.location if self.scope else None) - ) - - @property - def fully_qualified_name(self): - return '::'.join((c.name for c in self.path)) - - @property - def path(self): - result = self.scope.path if self.scope else [] - result.append(self) - return result - - def lookup(self, qname): - name_parts = qname.split('::') - if not name_parts: - return - - scope = self - while scope is not None: - if scope.name == name_parts[0]: - break - else: - found = None - for entity in scope.members.values(): - if entity.name == name_parts[0]: - found = entity - break - if found is None: - scope = scope.scope - else: - break - if not scope: - return - - for part in name_parts: - if scope.name != part: - found = None - for entity in scope.members.values(): - if entity.name == part: - found = entity - break - scope = found - if found is None: - break - - return scope - - def resolve_references(self): - self.brief = make_blocks(self._brief, self.index) - delattr(self, '_brief') - - self.description = make_blocks(self._description, self.index) - delattr(self, '_description') - - def update_scopes(self): - pass - - def __lt__(self, other): - return self.name < other.name - - @property - def asciidoc_file(self) -> str: - file_path = '/'.join(self._sanitize_path_segment(elm.name) for elm in self.path) - return f'{file_path}.adoc' - - - -class Compound(Entity): - nametag = 'compoundname' - - def __init__(self, element, scope, index=dict()): - super().__init__(element, scope, index) - - self.members = {} - self._nested = [] - for section in element: - if section.tag in ('innerclass', 'innernamespace', 'innergroup'): - self._nested.append(( - section.get('prot', Access.public), - section.get('refid'))) - - def update_scopes(self): - super().update_scopes() - - for access, refid in self._nested: - entity = self.index[refid] - entity.scope = self - entity.access = access - - assert entity.name not in self.members - self.members[entity.name] = entity - delattr(self, '_nested') - - def resolve_references(self): - super().resolve_references() - if getattr(self, '_nested', None): - self.update_scopes() - - @property - def public_types(self) -> PyList['Type']: - return [mem for mem in self.members.values() - if isinstance(mem, Type) - and mem.access == Access.public] - - - @property - def public_member_functions(self) -> PyList['OverloadSet']: - return [mem for mem in self.members.values() - if isinstance(mem, OverloadSet) - and mem.access == Access.public - and mem.kind == FunctionKind.nonstatic - ] - - @property - def public_static_functions(self) -> PyList['OverloadSet']: - return [mem for mem in self.members.values() - if isinstance(mem, OverloadSet) - and mem.access == Access.public - and mem.kind == FunctionKind.static - ] - - - -class Member(Entity): - nametag = 'name' - - def __init__(self, element: ET.Element, scope, index=dict()): - super().__init__(element, scope, index) - self.access = element.get('prot') or Access.public - - -class Group(Compound): - nametag = 'title' - - def __init__(self, element, index=dict()): - super().__init__(element, None, index) - - def adopt(self, entity, access): - entity.groups.append(self) - - -class Templatable(Entity): - def __init__(self, element, scope, index=dict()): - super().__init__(element, scope, index) - self._template_parameters = element.find('templateparamlist') - self.is_specialization = ( - (self.name.find('<') > 0) and (self.name.find('>') > 0)) - - def resolve_references(self): - super().resolve_references() - params = ( - self._template_parameters - if self._template_parameters is not None - and len(self._template_parameters) - else [] - ) - self.template_parameters = [Parameter(elem, self) for elem in params] - delattr(self, '_template_parameters') - - -class Type(Templatable): - declarator = None - objects = [] - - -class Scope(Entity): - def __init__(self, element, scope, index=dict()): - super().__init__(element, scope, index) - - nesting = 0 - name = '' - colon = False - for c in self.name: - if colon: - colon = False - if c == ':': - name = '' - continue - else: - name += ':' - - if nesting: - if c == '<': - nesting += 1 - elif c == '>': - nesting -= 1 - name += c - elif c == ':': - colon = True - else: - if c == '<': - nesting += 1 - name += c - if colon: - name.append(':') - self.name = name - - self.members = dict() - for section in element: - if not section.tag == 'sectiondef': - continue - - for member_def in section: - assert member_def.tag == 'memberdef' - - kind = member_def.get('kind') - if (kind == 'friend' - and member_def.find('type').text == 'class'): - # ignore friend classes - continue - - factory = { - 'function': OverloadSet.create, - 'friend': OverloadSet.create, - 'variable': Variable, - 'typedef': TypeAlias, - 'enum': Enum, - }[kind] - member = factory(member_def, section, self, index) - if type(member) is OverloadSet: - key = (member.name, member.access, member.kind) - self.members[key] = member - else: - assert member.name not in self.members - self.members[member.name] = member - - -class Namespace(Scope, Compound): - declarator = 'namespace' - - def __init__(self, element, index=dict()): - super().__init__(element, None, index) - - def resolve_references(self): - super().resolve_references() - for member in self.members.values(): - if isinstance(member, OverloadSet): - for func in member: - func.is_free = True - - -class Class(Scope, Compound, Type): - declarator = 'class' - - def __init__(self, element, index=dict()): - super().__init__(element, None, index) - self._bases = element.findall('basecompoundref') - - def resolve_references(self): - super().resolve_references() - self.bases = [Generalization(entry, self) for entry in self._bases] - delattr(self, '_bases') - - -class Generalization(): - def __init__(self, element, derived): - self.is_virtual = element.get('virt') == 'virtual' - self.access = element.get('prot') - assert self.access - - refid = element.get('refid') - if not refid: - entity = derived.lookup( ''.join(element.itertext()).strip() ) - if entity is not None: - refid = entity.id - - if refid: - self.base = Phrase( - [make_entity_reference(element, derived.index, refid)]) - else: - self.base = text_with_refs(element, derived.index) - - -class Struct(Class): - declarator = 'struct' - - -class Union(Class): - declarator = 'union' - - -class Enum(Scope, Type, Member): - def __init__(self, element, section, parent, index=dict()): - super().__init__(element, parent, index) - self.is_scoped = element.get('strong') == 'yes' - self._underlying_type = element.find('type') - - self.objects = [] - for child in element.findall('enumvalue'): - enumerator = Enumerator(child, section, self, index) - self.objects.append(enumerator) - assert enumerator.name not in enumerator.scope.members - enumerator.scope.members[enumerator.name] = enumerator - - @property - def declarator(self): - return 'enum class' if self.is_scoped else 'enum' - - def resolve_references(self): - super().resolve_references() - self.underlying_type = text_with_refs( - self._underlying_type, self.index) - delattr(self, '_underlying_type') - - -class Value(Member, Templatable): - def __init__(self, element: ET.Element, parent, index=dict()): - super().__init__(element, parent, index) - self.is_static = element.get('static') == 'yes' - self.is_constexpr = element.get('constexpr') == 'yes' - self.is_volatile = element.get('volatile') == 'yes' - self.is_const = ( - element.get('const') == 'yes' - or element.get('mutable') == 'no' - or False) - self.is_inline = element.get('inline') == 'yes' - - -class Function(Value): - def __init__(self, element: ET.Element, section, parent, index=dict()): - super().__init__(element, parent, index) - self.is_explicit = element.get('explicit') == 'yes' - self.refqual = element.get('refqual') - self.virtual_kind = element.get('virt', VirtualKind.nonvirtual) - self.is_friend = section.get('kind') == 'friend' - self.is_free = section.get('kind') == 'related' - self.is_constructor = self.name == parent.name - self.is_destructor = self.name == '~' + parent.name - noexcept = element.get('noexcept') - if noexcept: - self.is_noexcept = noexcept == 'yes' - else: - self.is_noexcept = self.is_destructor - - args = element.find('argsstring').text or '' - self.is_deleted = args.endswith('=delete') - self.is_defaulted = args.endswith('=default') - - self.overload_set = None - - self._return_type = element.find('type') - assert ( - self.is_constructor - or self.is_destructor - or self._return_type is not None) - - self._parameters = element.findall('param') - - @property - def kind(self): - if self.is_friend: - return FunctionKind.friend - if self.is_free: - return FunctionKind.free - if self.is_static: - return FunctionKind.static - return FunctionKind.nonstatic - - @property - def is_sole_overload(self): - return len(self.overload_set) == 1 - - @property - def overload_index(self): - if self.overload_set is None or self.is_sole_overload: - return -1 - - for n, overload in enumerate(self.overload_set): - if self == overload: - return n - - return -1 - - def resolve_references(self): - assert self._description is not None - node = self._description.find('.//xrefsect/..') - if node is not None: - subnode = node.find('xrefsect') - assert subnode is not None - xreftitle = subnode.find('xreftitle') - assert xreftitle is not None - assert xreftitle.text == 'overload_specific' - xrefdescription = subnode.find('xrefdescription') - assert xrefdescription is not None - self.overload_specific = make_blocks(xrefdescription, self.index) - node.remove(subnode) - else: - self.overload_specific = [] - super().resolve_references() - - self.return_type = resolve_type(self._return_type, self.index) - delattr(self, '_return_type') - - self.parameters = [Parameter(elem, self) for elem in self._parameters] - delattr(self, '_parameters') - - def __lt__(self, other): - if not isinstance(other, Function): - return self.name < other.name - - if self.name == other.name: - if self.scope == parent.scope: - return self.overload_index < other.overload_index - return self.scope < other.scope - - # if self.is_constructor: - # return True - # if other.is_constructor: - # return False - # if self.is_destructor: - # return True - # if other.is_destructor: - # return False - return self.name < other.name - - -class Parameter(): - def __init__(self, element: ET.Element, parent): - self.type = text_with_refs(element.find('type'), parent.index) - self.default_value = text_with_refs( - element.find('defval'), parent.index) - - self.description = element.find('briefdescription') - if self.description is not None: - self.description = make_blocks(self.description, parent) - else: - self.description = [] - - self.name = element.find('declname') - if self.name is not None: - self.name = self.name.text - - self.array = text_with_refs(element.find('array'), parent.index) - if self.array: - assert isinstance(self.type[-1], str) - assert self.type[-1].endswith('(&)') - self.type[-1] = self.type[-1][:-3] - - -class OverloadSet(): - @staticmethod - def create(element, section, parent, index): - func = Function(element, section, parent, index) - - key = (func.name, func.access, func.kind) - if key in parent.members: - overload_set = parent.members[key] - overload_set.append(func) - else: - overload_set = OverloadSet([func]) - func.overload_set = overload_set - return overload_set - - def __init__(self, funcs): - self.funcs = funcs - assert len(funcs) - self._resort() - - def __repr__(self) -> str: - return f'OverloadSet({self.fully_qualified_name})' - - def append(self, func): - self.funcs.append(func) - self._resort() - - def __getattr__(self, name): - return getattr(self.funcs[0], name) - - @property - def brief(self): - # print(f'Overload set: {self.name}, functions: {self.funcs}', flush=True) - return [func.brief for func in self.funcs] - - def __getitem__(self, pos): - return self.funcs[pos] - - def __len__(self): - return len(self.funcs) - - def __lt__(self, other): - if isinstance(other, OverloadSet): - return self.funcs[0] < other.funcs[0] - return self.name < other.name - - def _resort(self): - funcs_backwards = [] - briefs_backwards = [] - for func in self.funcs: - brief = ( - ''.join(func._brief.itertext()) - if func._brief is not None - else '' - ) - try: - n = briefs_backwards.index(brief) - except: - n = 0 - briefs_backwards.insert(n, brief) - funcs_backwards.insert(n, func) - funcs_backwards.reverse() - self.funcs = funcs_backwards - - -class Variable(Value): - def __init__(self, element, section, parent, index=dict()): - super().__init__(element, parent, index) - self._value = element.find('initializer') - self._type = element.find('type') - - def resolve_references(self): - super().resolve_references() - - self.value = text_with_refs(self._value, self.index) - delattr(self, '_value') - - self.type = resolve_type(self._type, self.index) - delattr(self, '_type') - - -class Enumerator(Variable): - def __init__(self, element, section, parent, index=dict()): - super().__init__(element, section, parent, index) - self.is_constexpr = True - self.is_const = True - self.is_static = True - self.enum = parent - self.scope = parent if parent.is_scoped else parent.scope - assert self.scope - - def resolve_references(self): - super().resolve_references() - self.type = Phrase([EntityRef(self.enum, [self.enum.name])]) - - -class TypeAlias(Member, Type): - declarator = 'using' - - def __init__(self, element, section, parent, index=dict()): - super().__init__(element, parent, index) - - self._aliased = element.find('type') - assert self._aliased is not None - - def resolve_references(self): - super().resolve_references() - self.aliased = text_with_refs(self._aliased, self.index) - delattr(self, '_aliased') - - -class AcceptOneorNone(argparse.Action): - def __init__(self, option_strings, dest, **kwargs): - if kwargs.get('nargs') is not None: - raise ValueError("nargs not allowed") - if kwargs.get('const') is not None: - raise ValueError("const not allowed") - if kwargs.get('default') is not None: - raise ValueError("default not allowed") - - super().__init__(option_strings, dest, **kwargs) - - def __call__(self, parser, namespace, values, option_string=None): - if getattr(namespace, self.dest) is not None: - raise argparse.ArgumentError(self, "multiple values") - - setattr(namespace, self.dest, values) - -def parse_args(args): - parser = argparse.ArgumentParser( - prog=args[0], - description='Produces API reference in QuickBook markup') - parser.add_argument( - '-i', - '--input', - action=AcceptOneorNone, - help='Doxygen XML index file; STDIN by default') - parser.add_argument( - '-o', - '--output', - required=True, - help='Output directory') - parser.add_argument( - '-c', '--config', - action='append', - default=[], - help='Configuration files') - parser.add_argument( - '-D', '--directory', - action=AcceptOneorNone, - help=( - 'Directory with additional data files; ' - 'by default INPUT parent directory if that is provided, ' - 'otherwise PWD')) - return parser.parse_args(args[1:]) - -def open_input(stdin, args, cwd): - data_dir = args.directory - if args.input: - file = open(args.input, 'r', encoding='utf-8') - ctx = file - data_dir = data_dir or os.path.dirname(args.input) - else: - file = stdin - ctx = Nullcontext() - data_dir = data_dir or cwd - return (file, ctx, data_dir) - - -def load_configs(args): - result = { - 'include_private': False, - 'legacy_behavior': True, - } - for file_name in args.config: - with open(file_name, 'r', encoding='utf-8') as file: - result.update( json.load(file) ) - return result - -def collect_compound_refs(file): - tree = ET.parse(file) - root = tree.getroot() - for child in root: - if child.tag != 'compound': - continue - - kind = child.get('kind') - assert kind - if kind in ('file', 'dir'): - continue - - refid = child.get('refid') - assert refid - yield refid - -def collect_data(parent_dir, refs) -> Dict[str, Entity]: - result = dict() - for refid in refs: - file_name = os.path.join(parent_dir, refid) + '.xml' - with open(file_name, 'r', encoding='utf-8') as file: - tree = ET.parse(file) - root = tree.getroot() - assert len(root) == 1 - - element = root[0] - assert element.tag == 'compounddef' - - factory = { - 'class': Class, - 'namespace': Namespace, - 'struct': Struct, - 'union': Union, - 'group': Group - }.get(element.get('kind')) - if not factory: - continue - factory(element, result) - - for entity in result.values(): - assert entity is not None - entity.update_scopes() - - for entity in result.values(): - entity.resolve_references(); - - return result - - -def construct_environment(loader, config): - env = jinja2.Environment( - loader=loader, - autoescape=False, - undefined=jinja2.StrictUndefined, - extensions=[ - 'jinja2.ext.do', - 'jinja2.ext.loopcontrols', - ], - ) - - env.globals['Access'] = Access - env.globals['FunctionKind'] = FunctionKind - env.globals['VirtualKind'] = VirtualKind - env.globals['Section'] = Section - env.globals['ParameterList'] = ParameterList - env.globals['Config'] = config - - env.tests['Entity'] = lambda x: isinstance(x, Entity) - env.tests['Templatable'] = lambda x: isinstance(x, Templatable) - env.tests['Type'] = lambda x: isinstance(x, Type) - env.tests['Scope'] = lambda x: isinstance(x, Scope) - env.tests['Namespace'] = lambda x: isinstance(x, Namespace) - env.tests['TypeAlias'] = lambda x: isinstance(x, TypeAlias) - env.tests['Class'] = lambda x: isinstance(x, Class) - env.tests['Struct'] = lambda x: isinstance(x, Struct) - env.tests['Union'] = lambda x: isinstance(x, Union) - env.tests['Enum'] = lambda x: isinstance(x, Enum) - env.tests['Value'] = lambda x: isinstance(x, Value) - env.tests['Variable'] = lambda x: isinstance(x, Variable) - env.tests['Enumerator'] = lambda x: isinstance(x, Enumerator) - env.tests['Function'] = lambda x: isinstance(x, Function) - env.tests['OverloadSet'] = lambda x: isinstance(x, OverloadSet) - env.tests['Parameter'] = lambda x: isinstance(x, Parameter) - - env.tests['Phrase'] = lambda x: isinstance(x, Phrase) - env.tests['Linebreak'] = lambda x: isinstance(x, Linebreak) - env.tests['Emphasised'] = lambda x: isinstance(x, Emphasised) - env.tests['Strong'] = lambda x: isinstance(x, Strong) - env.tests['Monospaced'] = lambda x: isinstance(x, Monospaced) - env.tests['EntityRef'] = lambda x: isinstance(x, EntityRef) - env.tests['UrlLink'] = lambda x: isinstance(x, UrlLink) - - env.tests['Block'] = lambda x: isinstance(x, Block) - env.tests['Paragraph'] = lambda x: isinstance(x, Paragraph) - env.tests['List'] = lambda x: isinstance(x, List) - env.tests['ListItem'] = lambda x: isinstance(x, ListItem) - env.tests['Section'] = lambda x: isinstance(x, Section) - env.tests['CodeBlock'] = lambda x: isinstance(x, CodeBlock) - env.tests['Table'] = lambda x: isinstance(x, Table) - env.tests['Cell'] = lambda x: isinstance(x, Cell) - env.tests['ParameterList'] = lambda x: isinstance(x, ParameterList) - env.tests['ParameterDescription'] = lambda x: isinstance(x, ParameterDescription) - env.tests['ParameterItem'] = lambda x: isinstance(x, ParameterItem) - - return env - -def render(env: jinja2.Environment, template_file: str, output_dir: str, output_file: str, **kwargs): - output_path = os.path.join(output_dir, output_file) - template = env.get_template(template_file) - makedirs(os.path.dirname(output_path), exist_ok=True) - with open(output_path, 'wt', encoding='utf-8') as f: - template.stream(**kwargs).dump(f) - - -def render_entities(env: jinja2.Environment, template_file: str, output_dir: str, entities: PyList[Entity]): - for e in entities: - print(f'Rendering {e}') - render(env, template_file, output_dir, e.asciidoc_file, entity=e) - - - -def main(args, stdin): - args = parse_args(args) - - file, ctx, data_dir = open_input(stdin, args, os.getcwd()) - with ctx: - refs = list(collect_compound_refs(file)) - data = collect_data(data_dir, refs) - - output_dir: str = args.output - - config = load_configs(args) - - env = construct_environment( - jinja2.FileSystemLoader(DEFAULT_TPLT_DIR), config) - - # Namespaces (not rendered directly) - namespaces = [e for e in data.values() if isinstance(e, Namespace)] - - # Classes (including member types) - classes = [e for e in data.values() - if isinstance(e, Class) and e.access == Access.public and - not e.is_specialization] - render_entities(env, 'class.jinja2', output_dir, classes) - - # Functions - fns = [] - for e in [e2 for e2 in data.values() if isinstance(e2, Compound)]: - fns += [mem for mem in e.members.values() if isinstance(mem, OverloadSet) and mem.access == Access.public] - render_entities(env, 'overload-set.jinja2', output_dir, fns) - - # Type aliases - type_alias = [e for e in data.values() if isinstance(e, TypeAlias)] - render_entities(env, 'type-alias.jinja2', output_dir, type_alias) - - # Enums - enums = [e for e in data.values() if isinstance(e, Enum)] - render_entities(env, 'enum.jinja2', output_dir, enums) - - # Constants - constants = [] - for ns in namespaces: - constants += [e for e in ns.members.values() if isinstance(e, Variable)] - render_entities(env, 'variable.jinja2', output_dir, constants) - - # Quickref - render( - env, - 'quickref.jinja2', - output_dir, - 'reference.adoc', - classes=classes, - enums=enums, - free_functions=[e for e in fns if isinstance(e.scope, Namespace)], - type_aliases=[e for e in type_alias if isinstance(e.scope, Namespace)], - constants=constants - ) - - -if __name__ == '__main__': - main(sys.argv, sys.stdin) diff --git a/doc/docca-asciidoc/templates/class.jinja2 b/doc/docca-asciidoc/templates/class.jinja2 deleted file mode 100644 index a49a3f512..000000000 --- a/doc/docca-asciidoc/templates/class.jinja2 +++ /dev/null @@ -1,140 +0,0 @@ -{% from "common.jinja2" import description, link, template_parameters, phrase, header_file %} - -== {{ entity.fully_qualified_name }} - - -{{ header_file(entity) }} - -{{ description(entity.brief) }} - -[source, cpp, subs="+macros", role="raw-code"] ----- -{{ template_parameters(entity) }} -{{ entity.declarator }} {{ entity.name }} -{%- for entry in entity.bases -%} - {% if loop.first %}:{% else %},{% endif -%} - {{ ' ' ~ entry.access ~ ' ' }} - {%- if entry.is_virtual %}virtual {% endif -%} - {{ phrase(entry.base, in_code=True) }} -{%- endfor -%} -; ----- - -{{ description(entity.description) }} - -{% for type in entity.public_types %} -{% if loop.first %} -=== Member types - -[cols="1,2", grid=rows, frame=none, role="mt-0"] -|=== -{% endif %} -.^|{{ link(type, '[link-to-entity bg-white]`' + type.name + '`') }} -.^|{{ description(type.brief) }} - -{% if loop.last %} -|=== -{% endif %} - -{%- endfor -%} - - -{% for fn in entity.public_member_functions %} -{% if loop.first %} -=== Member functions - -[cols="1,2", grid=rows, frame=none, role="mt-0"] -|=== -{% endif %} -.^|{{ link(fn, '[link-to-entity bg-white]`' + fn.name + '`') }} -.^|{{ description(fn.brief[0]) }} - -{% if loop.last %} -|=== -{% endif %} - -{%- endfor -%} - - - -{% for fn in entity.public_static_functions %} -{% if loop.first %} -=== Static functions - -[cols="1,2", grid=rows, frame=none, role="mt-0"] -|=== -{% endif %} -.^|{{ link(fn, '[link-to-entity bg-white]`' + fn.name + '`') }} -.^|{{ description(fn.brief[0]) }} - -{% if loop.last %} -|=== -{% endif %} -{%- endfor -%} - - - -{% for mem in entity.members.values() - | select("Variable") - | selectattr("access", "eq", Access.public) - | selectattr("is_static", "eq", False) %} - -{% if loop.first %} -=== Data members - -[cols="1", grid=none, frame=none, role="mt-0 space-rows"] -|=== -{% endif %} -.^a| -[source, cpp, subs="+macros", id={{ mem.name }}] ----- -{{ phrase(mem.type) }} {{ mem.name }}{%- if mem.value %} {{ phrase(mem.value) }} {%- endif -%}; ----- - - -{{ description(mem.brief) }} - -{{ description(mem.description) }} - -{% if loop.last %} -|=== -{% endif %} -{%- endfor -%} - - -{# TODO: this is duplicate #} -{% for mem in entity.members.values() - | select("Variable") - | selectattr("access", "eq", Access.public) - | selectattr("is_static", "eq", True) %} - -{% if loop.first %} -=== Static data members - -[cols="1", grid=none, frame=none, role="mt-0 space-rows"] -|=== -{% endif %} -.^a| -[source, cpp, subs="+macros", id={{ mem.name }}] ----- -{{ template_parameters(mem) }} -{%- set qualifiers = ['static'] -%} -{%- if mem.is_constexpr -%} - {%- set qualifiers = qualifiers + ['constexpr'] -%} -{%- endif -%} -{%- if mem.is_inline -%} - {%- set qualifiers = qualifiers + ['inline'] -%} -{%- endif -%} - -{{ qualifiers | join(' ') }} {{ phrase(mem.type) }} {{ mem.name }}{%- if mem.value %} {{ phrase(mem.value) }} {%- endif -%}; ----- - - -{{ description(mem.brief) }} - -{{ description(mem.description) }} - -{% if loop.last %} -|=== -{% endif %} -{%- endfor -%} \ No newline at end of file diff --git a/doc/docca-asciidoc/templates/common.jinja2 b/doc/docca-asciidoc/templates/common.jinja2 deleted file mode 100644 index bf6dae7fe..000000000 --- a/doc/docca-asciidoc/templates/common.jinja2 +++ /dev/null @@ -1,182 +0,0 @@ -{% macro escape(s) -%} - {{ s.replace("[", "\\[").replace("]", "\\]") }} -{%- endmacro %} - -{%- macro header_file(e) -%} - Defined in header [link-to-entity bg-white]`` -{%- endmacro -%} - - -{% macro subsection(sub) -%} -{% if sub.title %} - -=== {{ phrase(sub.title) }} -{% elif sub.kind %} - -=== {%- if sub.kind == 'see' %} See Also - {%- elif sub.kind == 'return' %} Return Value - {%- elif sub.kind == 'author' %} Author - {%- elif sub.kind == 'authors' %} Authors - {%- elif sub.kind == 'version' %} Version - {%- elif sub.kind == 'since' %} Since - {%- elif sub.kind == 'date' %} Date - {%- elif sub.kind == 'note' %} Remarks - {%- elif sub.kind == 'warning' %} Warning - {%- elif sub.kind == 'pre' %} Preconditions - {%- elif sub.kind == 'post' %} Postconditions - {%- elif sub.kind == 'copyright' %} Copyright - {%- elif sub.kind == 'invariant' %} Invariants - {%- elif sub.kind == 'remark' %} Remarks - {%- elif sub.kind == 'attention' %} Attention - {%- elif sub.kind == 'par' %} Paragraph - {%- elif sub.kind == 'rcs'%} RCS - {%- else %} Unknown - {%- endif -%} -{%- endif %} -{{ description(sub) }} -{%- endmacro %} - -{% macro link(entity, text) -%} - {%- if entity is Enumerator -%} - {{ link(entity.enum, text) }} - {%- elif entity is Variable and entity.scope is Class -%} - xref:{{ entity.scope.asciidoc_file }}#{{ entity.name }}[{{ text }}] - {%- else -%} - xref:{{ entity.asciidoc_file }}[{{ text }}] - {%- endif -%} -{%- endmacro %} - -{%- macro itemised(lst, nesting='') -%} - {%- for item in lst -%} - {{ nesting }} - {%- if lst.is_ordered -%} - # - {%- else -%} - * - {%- endif %} {{ description(item, nesting + ' ') }} - {%- endfor -%} -{%- endmacro %} - - -{% macro text_helper(s, in_code=False) -%} - {%- if s -%} - {%- set replacements=Config.get('replace_strings', {}) -%} - - {%- set ns = namespace(s=s) -%} - {%- if in_code -%} - {%- set ns.s = ns.s | replace(" ", " ") - | replace(" ", " ") - | replace(" ", " ") - | replace(" ", " ") - -%} - {%- if ns.s.endswith(" &") -%} - {%- set ns.s = ns.s[:-2] + "&" -%} - {%- elif ns.s.endswith(" *") -%} - {%- set ns.s = ns.s[:-2] + "*" -%} - {%- elif ns.s.endswith(" &&") -%} - {%- set ns.s = ns.s[:-3] + "&&" -%} - {%- elif ns.s.endswith(" &...") -%} - {%- set ns.s = ns.s[:-5] + "&..." -%} - {%- elif ns.s.endswith(" *...") -%} - {%- set ns.s = ns.s[:-5] + "*..." -%} - {%- elif ns.s.endswith(" &&...") -%} - {%- set ns.s = ns.s[:-6] + "&&..." -%} - {%- endif -%} - {%- else -%} - {%- set ns.s = escape(s) -%} - {%- endif -%} - {%- for src, tgt in replacements.items() -%} - {%- set ns.s = ns.s.replace(src, tgt) -%} - {%- endfor -%} - {{ ns.s }} - {%- else -%} - {{ s }} - {%- endif -%} -{%- endmacro %} - - - - -{% macro phrase(para, in_code=False) -%} -{%- for part in para -%}{{ phrase_part(part, in_code=in_code) }}{%- endfor -%} -{%- endmacro %} - -{% macro phrase_part(part, in_code=False) -%} - {%- if part is string -%} - {{ text_helper(part, in_code=in_code) }} - {%- elif part is Monospaced -%} - `+++{{ phrase(part, in_code=True) }}+++` - {%- elif part is Emphasised -%} - _{{ phrase(part, in_code=in_code) }}_ - {%- elif part is Strong -%} - *{{ phrase(part, in_code=in_code) }}* - {%- elif part is EntityRef -%} - {# Qualify only entities that are not in a namespace #} - {%- if part.entity.scope is Namespace -%} - {{ link(part.entity, part.entity.name) }} - {%- else -%} - {{ link(part.entity, part.entity.scope.name + '::' + part.entity.name) }} - {%- endif -%} - {%- elif part is UrlLink -%} - {{ part.url }}:[{{ phrase(part, in_code=in_code) }}] - {%- elif part is Linebreak %}{# indent is intentional here #} - -{% elif part is Phrase -%} - {{ phrase(part, in_code=in_code) }} - {%- else -%} - {{ part.unhandled_type() }} - {%- endif -%} -{%- endmacro %} - -{% macro description(parts, nesting='') -%} - -{%- for part in parts -%} - -{%- if part is Paragraph -%} -{{ phrase(part) }} -{% elif part is List -%} -{{ itemised(part, nesting) }} -{%- elif part is Section -%} -{{ subsection(part) }} -{%- elif part is CodeBlock %} -{{ nesting }}``` -{% for line in part -%} -{{nesting}}{{line}} -{% endfor -%} -{{ nesting }}``` -{% elif part is ParameterList -%} -{# {{ parameter_list(part) }} #} -{% elif part is Table -%} -{{ table(part) }} -{%- else -%} -{{ part.unhandled_type() }} -{%- endif -%} - -{%- endfor -%} - -{%- endmacro %} - -{%- macro template_parameters(entity) -%} -{%- if entity.template_parameters or entity.is_specialization -%}template<{%- endif -%} -{%- for tparam in entity.template_parameters %} - {{ phrase(tparam.type, in_code=True) }} - {%- if tparam.array %} (&{% endif -%} - {%- if tparam.name -%} - {%- if not tparam.array %} {% endif -%} - {{ tparam.name }} - {%- endif -%} - {%- if tparam.array %}) {{ phrase(tparam.array, in_code=True) }}{% endif -%} - {%- if tparam.default_value %} = {{ phrase(tparam.default_value, in_code=True) }}{% endif -%} - -{%- if loop.last -%} -> -{%- else -%} -, -{%- endif -%} - -{%- else -%} -{%- if entity.is_specialization -%} -> -{%- endif -%} -{%- endfor %} -{%- endmacro %} \ No newline at end of file diff --git a/doc/docca-asciidoc/templates/enum.jinja2 b/doc/docca-asciidoc/templates/enum.jinja2 deleted file mode 100644 index 6d21b0a61..000000000 --- a/doc/docca-asciidoc/templates/enum.jinja2 +++ /dev/null @@ -1,34 +0,0 @@ -{% from "common.jinja2" import phrase, template_parameters, description, header_file %} - -== {{ entity.fully_qualified_name }} - - -{{ header_file(entity) }} - -[source, cpp, subs="+macros", role="raw-code"] ----- -{{ entity.declarator }} {{ entity.name }} -{%- if entity.underlying_type -%} -: {{ phrase(entity.underlying_type) }} -{%- endif -%}; ----- - -{{ description(entity.brief) }} - -{{ description(entity.description) }} - -{% for enum in entity.objects %} -{% if loop.first %} -=== Enumerators - -[cols="1,2", grid=rows, frame=none, role="mt-0"] -|=== -{% endif %} -.^|[link-to-entity bg-white]`{{ enum.name }}` -.^|{{ description(enum.brief) }} {{ description(enum.description) }} - -{% if loop.last %} -|=== -{% endif %} - -{% endfor %} \ No newline at end of file diff --git a/doc/docca-asciidoc/templates/overload-set.jinja2 b/doc/docca-asciidoc/templates/overload-set.jinja2 deleted file mode 100644 index ff0df6532..000000000 --- a/doc/docca-asciidoc/templates/overload-set.jinja2 +++ /dev/null @@ -1,80 +0,0 @@ - -{%- from "common.jinja2" import template_parameters, description, phrase -%} - -== {{ entity.fully_qualified_name }} - - -[cols="8,1", grid=rows, frame=none, role="mt-0"] -|=== - -{% for fn in entity %} - -a| -[source, cpp, subs="+macros", role="raw-code"] ----- -{{ template_parameters(fn) }} -{%- set qualifiers = [] -%} -{%- if fn.is_explicit -%} - {%- set qualifiers = qualifiers + ['explicit'] -%} -{%- endif -%} -{%- if fn.is_static -%} - {%- set qualifiers = qualifiers + ['static'] -%} -{%- endif -%} -{%- if fn.is_constexpr -%} - {%- set qualifiers = qualifiers + ['constexpr'] -%} -{%- endif -%} - -{%- if qualifiers | length -%} - {{ qualifiers | join(' ') }}{{' '}} -{%- endif -%} -{{ phrase(fn.return_type, in_code=True) }} -{{ fn.name }}( -{%- for param in fn.parameters %} - {{ phrase(param.type, in_code=True) }} - {%- if param.array %} (&{% endif -%} - {%- if param.name -%} - {%- if not param.array %} {% endif -%} - {{ param.name }} - {%- endif -%} - {%- if param.array %}) {{ phrase(param.array, in_code=True) }}{% endif -%} - {%- if param.default_value %} = {{ phrase(param.default_value, in_code=True) }}{% endif -%} - - {%- if not loop.last %},{% endif -%} -{%- endfor -%} -) -{%- if fn.refqual or fn.is_const -%} - {{ " " }} - {%- if fn.is_const %}const{% endif -%} - {%- if "lvalue" == fn.refqual %}& - {%- elif "rvalue" == fn.refqual %}&& - {%- endif -%} -{%- endif -%} -{%- if fn.is_noexcept and not fn.is_destructor %} noexcept{% endif -%} -{%- if not fn.is_noexcept and fn.is_destructor %} noexcept(false){% endif -%} -{%- if fn.is_deleted %} = delete -{%- elif fn.is_defaulted %} = default -{%- endif -%} -; ----- - -.^| {%- if entity | length > 1 -%} ({{ loop.index }}) {%- endif -%} - -{% endfor %} - -|=== - -{{ description(entity.brief[0]) }} - -{{ description(entity.description) }} - -{%- if entity | length > 1 -%} -[cols="1,8", grid=rows, frame=none, role="mt-0"] -|=== -{% for fn in entity -%} - {%- if fn.overload_specific | length -%} - .^|({{ loop.index }}) - |{{ description(fn.overload_specific) }} - {%- endif -%} -{%- endfor %} -|=== -{%- endif -%} diff --git a/doc/docca-asciidoc/templates/quickref.jinja2 b/doc/docca-asciidoc/templates/quickref.jinja2 deleted file mode 100644 index 53b6183a0..000000000 --- a/doc/docca-asciidoc/templates/quickref.jinja2 +++ /dev/null @@ -1,47 +0,0 @@ - -{% from "common.jinja2" import link %} - -{% macro reflink(entity) %} -[.m-0] -{{ link(entity, '[link-to-entity bg-white]`' + entity.name + '`') }} -{% endmacro %} - -[#reference] -= Reference -:role: quickref - -[cols="1,1"] -|=== - -a| [.pb-1]*Classes* - -{% for e in classes | sort -%} -{{ reflink(e) }} -{%- endfor %} - -a| [.pb-1]*Enumerations* - -{% for e in enums | sort -%} -{{ reflink(e) }} -{%- endfor %} - -[.pb-1]*Functions* - -{% for e in free_functions | sort -%} -{{ reflink(e) }} -{%- endfor %} - -[.pb-1]*Type aliases* - -{% for e in type_aliases | sort -%} -{{ reflink(e) }} -{%- endfor %} - -[.pb-1]*Constants* - -{% for e in constants | sort -%} -{{ reflink(e) }} -{%- endfor %} - -|=== - diff --git a/doc/docca-asciidoc/templates/type-alias.jinja2 b/doc/docca-asciidoc/templates/type-alias.jinja2 deleted file mode 100644 index d99ac797e..000000000 --- a/doc/docca-asciidoc/templates/type-alias.jinja2 +++ /dev/null @@ -1,17 +0,0 @@ -{% from "common.jinja2" import phrase, template_parameters, description, header_file %} - -== {{ entity.fully_qualified_name }} - - -{{ header_file(entity) }} - -[source, cpp, subs="+macros", role="raw-code"] ----- -{{ template_parameters(entity) }} -{{ entity.declarator }} {{ entity.name }} = {{ phrase(entity.aliased) }}; ----- - -{{ description(entity.brief) }} - -{{ description(entity.description) }} - diff --git a/doc/docca-asciidoc/templates/variable.jinja2 b/doc/docca-asciidoc/templates/variable.jinja2 deleted file mode 100644 index f99843b4c..000000000 --- a/doc/docca-asciidoc/templates/variable.jinja2 +++ /dev/null @@ -1,34 +0,0 @@ -{% from "common.jinja2" import phrase, template_parameters, description, header_file %} - -== {{ entity.fully_qualified_name }} - - -{{ header_file(entity) }} - -[source, cpp, subs="+macros", role="raw-code"] ----- -{{ template_parameters(entity) }} -{%- set qualifiers = [] -%} -{%- if entity.is_static -%} - {%- set qualifiers = qualifiers + ['static'] -%} -{%- endif -%} -{%- if entity.is_constexpr -%} - {%- set qualifiers = qualifiers + ['constexpr'] -%} -{%- endif -%} -{%- if entity.is_inline -%} - {%- set qualifiers = qualifiers + ['inline'] -%} -{%- endif -%} - -{%- if qualifiers | length -%} - {{ qualifiers | join(' ') }}{{' '}} -{%- endif -%} - -{{ phrase(entity.type) }} {{ entity.name }} -{%- if entity.value %} {{ phrase(entity.value) }}{% endif -%} -; ----- - -{{ description(entity.brief) }} - -{{ description(entity.description) }} - From 7e39f852217142cebd53603b0e8d0f6ca40417a9 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Wed, 14 Aug 2024 23:54:21 +0200 Subject: [PATCH 18/18] nowrap for code --- doc/supplemental-ui/css/custom.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/supplemental-ui/css/custom.css b/doc/supplemental-ui/css/custom.css index 8fb8a275a..23e19fcfa 100644 --- a/doc/supplemental-ui/css/custom.css +++ b/doc/supplemental-ui/css/custom.css @@ -45,6 +45,10 @@ max-width: 80% !important; } +.whitespace-nowrap { + white-space: nowrap !important; +} + /* highlight.js */ /*! Adapted from the GitHub style by Vasily Polovnyov */