From 41deb4d7a769a4754fcb79f15a73be207255c799 Mon Sep 17 00:00:00 2001 From: Mark Gillard Date: Mon, 31 Jul 2023 16:39:22 +0300 Subject: [PATCH] fixed internal @refs being treated as external also: - added auto-linking for C++ named requirements - minor style fixes --- CHANGELOG.md | 6 +++ src/poxy/css/poxy-overrides.css | 23 ++++++---- src/poxy/fixers.py | 39 ++++++++++++----- src/poxy/generated/poxy.css | 16 ++++--- src/poxy/project.py | 74 +++++++++++++++++++++++++++++++-- src/poxy/version.txt | 2 +- 6 files changed, 131 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55b7c59..079721c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v0.13.2 - 2023-07-31 + +- fixed doxygen's `@ref` links to `#id` anchors on the same page being treated as external links +- added auto-linking for C++ [named requirements](https://en.cppreference.com/w/cpp/named_req) +- minor style fixes + ## v0.13.1 - 2023-07-29 - fixed crash regression with Doxygen 1.9.7 diff --git a/src/poxy/css/poxy-overrides.css b/src/poxy/css/poxy-overrides.css index 08853ae..3300acc 100644 --- a/src/poxy/css/poxy-overrides.css +++ b/src/poxy/css/poxy-overrides.css @@ -194,23 +194,25 @@ h3 .m-doc-include .cp { } /* "Try this code on Compiler Explorer" */ -.godbolt { +pre .poxy-godbolt, +code .poxy-godbolt { font-family: "Source Sans Pro", sans-serif; } -p.godbolt { +pre p.poxy-godbolt, +code p.poxy-godbolt { text-align: center; padding: 0rem; text-indent: 0rem; + float: right; } -a.godbolt { +pre p.poxy-godbolt a.poxy-godbolt, +code p.poxy-godbolt a.poxy-godbolt { padding: 0.5rem; display: inline-block; } -pre > p.godbolt { - float: right; -} @media screen and (max-width: 768px) { - .godbolt { + pre p.poxy-godbolt, + code p.poxy-godbolt { display: none; } } @@ -406,7 +408,7 @@ section.m-doc-details div .m-table.m-fullwidth.m-flat tbody td:first-of-type wbr .poxy-about-the-author { margin-top: 4rem; } -.poxy-about-the-author .socials { +.poxy-about-the-author .poxy-socials { display: block; padding-top: 0.5rem; } @@ -426,3 +428,8 @@ footer nav a.sponsor:hover, a.poxy-icon.sponsor:hover { color: var(--sponsor-color) !important; } + +/* C++ named requirement links */ +main article a.poxy-named-requirement { + font-style: italic; +} diff --git a/src/poxy/fixers.py b/src/poxy/fixers.py index 76a3ef8..3042d80 100644 --- a/src/poxy/fixers.py +++ b/src/poxy/fixers.py @@ -836,31 +836,45 @@ class Links(HTMLFixer): __external_href = re.compile(r'^(?:https?|s?ftp|mailto)[:].+$', re.I) __internal_doc_id = re.compile(r'^[a-fA-F0-9]+$') - __godbolt = re.compile(r'^\s*https[:]//godbolt.org/z/.+?$', re.I) __local_href = re.compile(r'^([-/_a-zA-Z0-9]+\.[a-zA-Z]+)(?:#(.*))?$') + __godbolt = re.compile(r'^\s*(?:https?[:]//)?(?:www[.])?godbolt[.]org/z/.+?$', re.I) + __cppreference = re.compile(r'^\s*(?:https?[:]//)?(?:[a-z]+[.])?cppreference[.]com.*$', re.I) + __named_req = re.compile(r'^\s*(?:https?[:]//)?(?:[a-z]+[.])?cppreference[.]com/w/cpp/named_req/.+?$', re.I) def __call__(self, context: Context, doc: soup.HTMLDocument, path: Path): changed = False for anchor in doc.body('a', href=True): - href = anchor['href'] + # make sure internal links to #ids on the same page don't get treated as external links + # (some versions of doxygen did this with @ref) + if anchor['href'].startswith(rf'{path.name}#'): + anchor['href'] = anchor['href'][len(rf'{path.name}') :] + changed = True + + # tag links to cppreference.com + if self.__cppreference.fullmatch(anchor['href']): + changed = soup.add_class(anchor, 'poxy-cppreference') or changed + + # tag links to cpp named requirements + if self.__named_req.fullmatch(anchor['href']): + changed = soup.add_class(anchor, 'poxy-named-requirement') or changed # make sure links to external sources are correctly marked as such - if self.__external_href.fullmatch(href) is not None: + if self.__external_href.fullmatch(anchor['href']) is not None: if 'target' not in anchor.attrs or anchor['target'] != '_blank': anchor['target'] = '_blank' changed = True changed = soup.add_class(anchor, 'poxy-external') or changed # do magic with godbolt.org links - if self.__godbolt.fullmatch(href): - changed = soup.add_class(anchor, 'godbolt') or changed + if self.__godbolt.fullmatch(anchor['href']): + changed = soup.add_class(anchor, 'poxy-godbolt') or changed if ( anchor.parent.name == 'p' and len(anchor.parent.contents) == 1 and anchor.parent.next_sibling is not None - and anchor.parent.next_sibling.name == 'pre' + and anchor.parent.next_sibling.name in ('pre', 'code') ): - soup.add_class(anchor.parent, ('m-note', 'm-success', 'godbolt')) + soup.add_class(anchor.parent, ('m-note', 'm-success', 'poxy-godbolt')) code_block = anchor.parent.next_sibling code_block.insert(0, anchor.parent.extract()) changed = True @@ -869,7 +883,7 @@ def __call__(self, context: Context, doc: soup.HTMLDocument, path: Path): is_mdoc = r'class' in anchor.attrs and (r'm-doc' in anchor['class'] or r'm-doc-self' in anchor['class']) # make sure links to local files point to actual existing files - match = self.__local_href.fullmatch(href) + match = self.__local_href.fullmatch(anchor['href']) if match and not coerce_path(path.parent, match[1]).exists(): changed = True # fix for some doxygen versions not emitting the 'md_' prefix: @@ -880,8 +894,7 @@ def __call__(self, context: Context, doc: soup.HTMLDocument, path: Path): continue # non-existent hrefs that correspond to internal documentation can sometimes by fixed by the next step if is_mdoc: - href = r'#' - anchor[r'href'] = r'#' + anchor['href'] = r'#' # otherwise this is a href to a non-existent file so we just convert it to a plain span else: for attr in ( @@ -902,7 +915,11 @@ def __call__(self, context: Context, doc: soup.HTMLDocument, path: Path): continue # make sure internal documentation #id links actually have somewhere to go - if is_mdoc and href.startswith(r'#') and (len(href) == 1 or doc.body.find(id=href[1:]) is None): + if ( + is_mdoc + and anchor['href'].startswith(r'#') + and (len(anchor['href']) == 1 or doc.body.find(id=anchor['href'][1:]) is None) + ): changed = True soup.remove_class(anchor, 'm-doc') soup.add_class(anchor, 'm-doc-self') diff --git a/src/poxy/generated/poxy.css b/src/poxy/generated/poxy.css index a777076..97088f5 100644 --- a/src/poxy/generated/poxy.css +++ b/src/poxy/generated/poxy.css @@ -2716,12 +2716,15 @@ h1 .m-doc-include *, h3 .m-doc-include * { opacity: 1 !important; } h1 .m-doc-include .cp, h3 .m-doc-include .cp { color: var(--dim-color); } -.godbolt { font-family: "Source Sans Pro", sans-serif; } -p.godbolt { text-align: center; padding: 0rem; text-indent: 0rem; } -a.godbolt { padding: 0.5rem; display: inline-block; } -pre > p.godbolt { float: right; } +pre .poxy-godbolt, +code .poxy-godbolt { font-family: "Source Sans Pro", sans-serif; } +pre p.poxy-godbolt, +code p.poxy-godbolt { text-align: center; padding: 0rem; text-indent: 0rem; float: right; } +pre p.poxy-godbolt a.poxy-godbolt, +code p.poxy-godbolt a.poxy-godbolt { padding: 0.5rem; display: inline-block; } @media screen and (max-width: 768px) { -.godbolt { display: none; } +pre p.poxy-godbolt, +code p.poxy-godbolt { display: none; } } h2:last-child, h3:last-child, @@ -2813,11 +2816,12 @@ margin-top: initial; .m-doc-template-params.m-doc-template-long .m-doc-template-param::before { content: ""; display: block; } section.m-doc-details div .m-table.m-fullwidth.m-flat tbody td:first-of-type wbr { display: none; } .poxy-about-the-author { margin-top: 4rem; } -.poxy-about-the-author .socials { display: block; padding-top: 0.5rem; } +.poxy-about-the-author .poxy-socials { display: block; padding-top: 0.5rem; } .poxy-about-the-author img.poxy-icon, .poxy-about-the-author svg.poxy-icon { max-width: 1.5rem; max-height: 1.5rem; margin-right: 0.5rem; } header nav #m-navbar-collapse li a.sponsor:hover { border-color: var(--sponsor-color) !important; } header nav a.sponsor:hover, footer nav a.sponsor:hover, a.poxy-icon.sponsor:hover { color: var(--sponsor-color) !important; } +main article a.poxy-named-requirement { font-style: italic; } diff --git a/src/poxy/project.py b/src/poxy/project.py index c96af26..feb1292 100644 --- a/src/poxy/project.py +++ b/src/poxy/project.py @@ -438,12 +438,80 @@ class Defaults(object): r'std::unordered_sets?': r'https://en.cppreference.com/w/cpp/container/unordered_set', r'std::vectors?': r'https://en.cppreference.com/w/cpp/container/vector', r'std::atomic[a-zA-Z_0-9]*': r'https://en.cppreference.com/w/cpp/atomic/atomic', + # named requirements + r'Allocators?': r'https://en.cppreference.com/w/cpp/named_req/Allocator', + r'AllocatorAwareContainers?': r'https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer', + r'AssociativeContainers?': r'https://en.cppreference.com/w/cpp/named_req/AssociativeContainer', + r'BasicFormatters?': r'https://en.cppreference.com/w/cpp/named_req/BasicFormatter', + r'BasicLockables?': r'https://en.cppreference.com/w/cpp/named_req/BasicLockable', + r'(?:Legacy)?BidirectionalIterators?': r'https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator', + r'BinaryPredicates?': r'https://en.cppreference.com/w/cpp/named_req/BinaryPredicate', + r'BinaryTypeTraits?': r'https://en.cppreference.com/w/cpp/named_req/BinaryTypeTrait', + r'BitmaskTypes?': r'https://en.cppreference.com/w/cpp/named_req/BitmaskType', + r'Callables?': r'https://en.cppreference.com/w/cpp/named_req/Callable', + r'CharTraits?': r'https://en.cppreference.com/w/cpp/named_req/CharTraits', + r'Compares?': r'https://en.cppreference.com/w/cpp/named_req/Compare', + r'(?:Legacy)?ConstexprIterators?': r'https://en.cppreference.com/w/cpp/named_req/ConstexprIterator', + r'Containers?': r'https://en.cppreference.com/w/cpp/named_req/Container', + r'ContiguousContainers?': r'https://en.cppreference.com/w/cpp/named_req/ContiguousContainer', + r'(?:Legacy)?ContiguousIterators?': r'https://en.cppreference.com/w/cpp/named_req/ContiguousIterator', + r'CopyAssignables?': r'https://en.cppreference.com/w/cpp/named_req/CopyAssignable', + r'CopyConstructibles?': r'https://en.cppreference.com/w/cpp/named_req/CopyConstructible', + r'CopyInsertables?': r'https://en.cppreference.com/w/cpp/named_req/CopyInsertable', + r'DefaultConstructibles?': r'https://en.cppreference.com/w/cpp/named_req/DefaultConstructible', + r'DefaultInsertables?': r'https://en.cppreference.com/w/cpp/named_req/DefaultInsertable', + r'Destructibles?': r'https://en.cppreference.com/w/cpp/named_req/Destructible', + r'EmplaceConstructibles?': r'https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible', + r'EqualityComparables?': r'https://en.cppreference.com/w/cpp/named_req/EqualityComparable', + r'Erasables?': r'https://en.cppreference.com/w/cpp/named_req/Erasable', + r'FormattedInputFunctions?': r'https://en.cppreference.com/w/cpp/named_req/FormattedInputFunction', + r'FormattedOutputFunctions?': r'https://en.cppreference.com/w/cpp/named_req/FormattedOutputFunction', + r'(?:Legacy)?ForwardIterators?': r'https://en.cppreference.com/w/cpp/named_req/ForwardIterator', + r'FunctionObjects?': r'https://en.cppreference.com/w/cpp/named_req/FunctionObject', + r'ImplicitLifetimeTypes?': r'https://en.cppreference.com/w/cpp/named_req/ImplicitLifetimeType', + r'LegacyIterators?': r'https://en.cppreference.com/w/cpp/named_req/LegacyIterator', r'(?:Legacy)?InputIterators?': r'https://en.cppreference.com/w/cpp/named_req/InputIterator', + r'(?:Legacy)?Iterators?': r'https://en.cppreference.com/w/cpp/named_req/Iterator', + r'LessThanComparables?': r'https://en.cppreference.com/w/cpp/named_req/LessThanComparable', + r'LiteralTypes?': r'https://en.cppreference.com/w/cpp/named_req/LiteralType', + r'Lockables?': r'https://en.cppreference.com/w/cpp/named_req/Lockable', + r'MoveAssignables?': r'https://en.cppreference.com/w/cpp/named_req/MoveAssignable', + r'MoveConstructibles?': r'https://en.cppreference.com/w/cpp/named_req/MoveConstructible', + r'MoveInsertables?': r'https://en.cppreference.com/w/cpp/named_req/MoveInsertable', + r'NullablePointers?': r'https://en.cppreference.com/w/cpp/named_req/NullablePointer', + r'NumericTypes?': r'https://en.cppreference.com/w/cpp/named_req/NumericType', r'(?:Legacy)?OutputIterators?': r'https://en.cppreference.com/w/cpp/named_req/OutputIterator', - r'(?:Legacy)?ForwardIterators?': r'https://en.cppreference.com/w/cpp/named_req/ForwardIterator', - r'(?:Legacy)?BidirectionalIterators?': r'https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator', + r'PODTypes?': r'https://en.cppreference.com/w/cpp/named_req/PODType', + r'Predicates?': r'https://en.cppreference.com/w/cpp/named_req/Predicate', r'(?:Legacy)?RandomAccessIterators?': r'https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator', - r'(?:Legacy)?ContiguousIterators?': r'https://en.cppreference.com/w/cpp/named_req/ContiguousIterator', + r'RandomNumberDistributions?': r'https://en.cppreference.com/w/cpp/named_req/RandomNumberDistribution', + r'RandomNumberEngines?': r'https://en.cppreference.com/w/cpp/named_req/RandomNumberEngine', + r'RandomNumberEngineAdaptors?': r'https://en.cppreference.com/w/cpp/named_req/RandomNumberEngineAdaptor', + r'RangeAdaptorClosureObjects?': r'https://en.cppreference.com/w/cpp/named_req/RangeAdaptorClosureObject', + r'RangeAdaptorObjects?': r'https://en.cppreference.com/w/cpp/named_req/RangeAdaptorObject', + r'RegexTraitss?': r'https://en.cppreference.com/w/cpp/named_req/RegexTraits', + r'ReversibleContainers?': r'https://en.cppreference.com/w/cpp/named_req/ReversibleContainer', + r'ScalarTypes?': r'https://en.cppreference.com/w/cpp/named_req/ScalarType', + r'SeedSequences?': r'https://en.cppreference.com/w/cpp/named_req/SeedSequence', + r'SequenceContainers?': r'https://en.cppreference.com/w/cpp/named_req/SequenceContainer', + r'SharedLockables?': r'https://en.cppreference.com/w/cpp/named_req/SharedLockable', + r'SharedMutexs?': r'https://en.cppreference.com/w/cpp/named_req/SharedMutex', + r'SharedTimedLockables?': r'https://en.cppreference.com/w/cpp/named_req/SharedTimedLockable', + r'SharedTimedMutexs?': r'https://en.cppreference.com/w/cpp/named_req/SharedTimedMutex', + r'StandardLayoutTypes?': r'https://en.cppreference.com/w/cpp/named_req/StandardLayoutType', + r'Swappables?': r'https://en.cppreference.com/w/cpp/named_req/Swappable', + r'TimedLockables?': r'https://en.cppreference.com/w/cpp/named_req/TimedLockable', + r'TimedMutexs?': r'https://en.cppreference.com/w/cpp/named_req/TimedMutex', + r'TransformationTraits?': r'https://en.cppreference.com/w/cpp/named_req/TransformationTrait', + r'TrivialClocks?': r'https://en.cppreference.com/w/cpp/named_req/TrivialClock', + r'TriviallyCopyables?': r'https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable', + r'TrivialTypes?': r'https://en.cppreference.com/w/cpp/named_req/TrivialType', + r'UnaryTypeTraits?': r'https://en.cppreference.com/w/cpp/named_req/UnaryTypeTrait', + r'UnformattedInputFunctions?': r'https://en.cppreference.com/w/cpp/named_req/UnformattedInputFunction', + r'UnformattedOutputFunctions?': r'https://en.cppreference.com/w/cpp/named_req/UnformattedOutputFunction', + r'UniformRandomBitGenerators?': r'https://en.cppreference.com/w/cpp/named_req/UniformRandomBitGenerator', + r'UnorderedAssociativeContainers?': r'https://en.cppreference.com/w/cpp/named_req/UnorderedAssociativeContainer', + r'ValueSwappables?': r'https://en.cppreference.com/w/cpp/named_req/ValueSwappable', # windows r'(?:L?P)?(?:' + r'D?WORD(?:32|64|_PTR)?|HANDLE|HMODULE|BOOL(?:EAN)?' diff --git a/src/poxy/version.txt b/src/poxy/version.txt index c317a91..9beb74d 100644 --- a/src/poxy/version.txt +++ b/src/poxy/version.txt @@ -1 +1 @@ -0.13.1 +0.13.2