summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Ledbetter <timledbetter@gmail.com>2023-04-16 10:28:45 +0100
committerAndrew Kaster <andrewdkaster@gmail.com>2023-04-25 02:16:48 -0600
commit10700ca4c1cabe7889b0031bc01a3b18c68df77d (patch)
tree96684ae2dafff5d6387eca5d93c025d81f0107ba
parentf9d8e42636c9f72f88e97b33a44b1d020641bdb1 (diff)
downloadserenity-10700ca4c1cabe7889b0031bc01a3b18c68df77d.zip
LibManual: Associate SubsectionNode with similarly named markdown file
For a subsection named `Foo` with a markdown file `Foo.md` in the same directory, the document `Foo.md` will be returned when the subsection is selected. This prevents PageNodes and SubsectionNodes from sharing the same name, which fixes an issue in Help where subsections could not be navigated.
-rw-r--r--Userland/Libraries/LibManual/SectionNode.cpp39
-rw-r--r--Userland/Libraries/LibManual/SubsectionNode.cpp21
-rw-r--r--Userland/Libraries/LibManual/SubsectionNode.h6
3 files changed, 34 insertions, 32 deletions
diff --git a/Userland/Libraries/LibManual/SectionNode.cpp b/Userland/Libraries/LibManual/SectionNode.cpp
index 150f960f32..cc2a39f07a 100644
--- a/Userland/Libraries/LibManual/SectionNode.cpp
+++ b/Userland/Libraries/LibManual/SectionNode.cpp
@@ -8,6 +8,7 @@
#include "PageNode.h"
#include "Path.h"
#include "SubsectionNode.h"
+#include <AK/HashTable.h>
#include <AK/LexicalPath.h>
#include <AK/QuickSort.h>
#include <LibCore/DirIterator.h>
@@ -43,7 +44,16 @@ ErrorOr<void> SectionNode::reify_if_needed() const
m_reified = true;
auto own_path = TRY(path());
- Core::DirIterator dir_iter { own_path.to_deprecated_string(), Core::DirIterator::Flags::SkipDots };
+ Core::DirIterator dir_iterator { own_path.to_deprecated_string(), Core::DirIterator::Flags::SkipDots };
+ Vector<DeprecatedString> directories;
+ HashTable<DeprecatedString> files;
+ while (dir_iterator.has_next()) {
+ auto entry = dir_iterator.next();
+ if (entry->type == Core::DirectoryEntry::Type::Directory)
+ TRY(directories.try_append(entry->name));
+ else if (entry->type == Core::DirectoryEntry::Type::File && entry->name.ends_with(".md"sv, CaseSensitivity::CaseInsensitive))
+ TRY(files.try_set(entry->name));
+ }
struct Child {
NonnullRefPtr<Node const> node;
@@ -51,18 +61,21 @@ ErrorOr<void> SectionNode::reify_if_needed() const
};
Vector<Child> children;
- while (dir_iter.has_next()) {
- LexicalPath lexical_path(dir_iter.next_path());
- if (lexical_path.extension() != "md") {
- if (FileSystem::is_directory(LexicalPath::absolute_path(own_path.to_deprecated_string(), lexical_path.string()))) {
- dbgln("Found subsection {}", lexical_path);
- children.append({ .node = TRY(try_make_ref_counted<SubsectionNode>(*this, lexical_path.title())),
- .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) });
- }
- } else {
- children.append({ .node = TRY(try_make_ref_counted<PageNode>(*this, TRY(String::from_utf8(lexical_path.title())))),
- .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) });
- }
+ for (auto const& directory : directories) {
+ LexicalPath lexical_path(directory);
+ RefPtr<PageNode> associated_page;
+ auto matching_page_name = DeprecatedString::formatted("{}.md", directory);
+ if (files.remove(matching_page_name))
+ associated_page = TRY(try_make_ref_counted<PageNode>(*this, TRY(String::from_utf8(lexical_path.title()))));
+
+ TRY(children.try_append({ .node = TRY(try_make_ref_counted<SubsectionNode>(*this, lexical_path.title(), associated_page)),
+ .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) }));
+ }
+
+ for (auto const& file : files) {
+ LexicalPath lexical_path(file);
+ children.append({ .node = TRY(try_make_ref_counted<PageNode>(*this, TRY(String::from_utf8(lexical_path.title())))),
+ .name_for_sorting = TRY(String::from_utf8(lexical_path.title())) });
}
quick_sort(children, [](auto const& a, auto const& b) { return a.name_for_sorting < b.name_for_sorting; });
diff --git a/Userland/Libraries/LibManual/SubsectionNode.cpp b/Userland/Libraries/LibManual/SubsectionNode.cpp
index cb1e6d44fb..f5535a1bf8 100644
--- a/Userland/Libraries/LibManual/SubsectionNode.cpp
+++ b/Userland/Libraries/LibManual/SubsectionNode.cpp
@@ -10,31 +10,16 @@
namespace Manual {
-SubsectionNode::SubsectionNode(NonnullRefPtr<SectionNode const> parent, StringView name)
+SubsectionNode::SubsectionNode(NonnullRefPtr<SectionNode const> parent, StringView name, RefPtr<PageNode> page)
: SectionNode(name, name)
, m_parent(move(parent))
+ , m_page(move(page))
{
}
Node const* SubsectionNode::parent() const { return m_parent; }
-PageNode const* SubsectionNode::document() const
-{
- auto maybe_siblings = parent()->children();
- if (maybe_siblings.is_error())
- return nullptr;
- auto siblings = maybe_siblings.release_value();
- for (auto const& sibling : siblings) {
- if (&*sibling == this)
- continue;
- auto sibling_name = sibling->name();
- if (sibling_name.is_error())
- continue;
- if (sibling_name.value() == m_name && is<PageNode>(*sibling))
- return static_cast<PageNode const*>(&*sibling);
- }
- return nullptr;
-}
+PageNode const* SubsectionNode::document() const { return m_page; }
ErrorOr<String> SubsectionNode::name() const { return m_name; }
diff --git a/Userland/Libraries/LibManual/SubsectionNode.h b/Userland/Libraries/LibManual/SubsectionNode.h
index 93a4334f97..4ab6fda183 100644
--- a/Userland/Libraries/LibManual/SubsectionNode.h
+++ b/Userland/Libraries/LibManual/SubsectionNode.h
@@ -6,6 +6,7 @@
#pragma once
+#include <LibManual/PageNode.h>
#include <LibManual/SectionNode.h>
namespace Manual {
@@ -13,7 +14,7 @@ namespace Manual {
// A non-toplevel (i.e. not numbered) manual section.
class SubsectionNode : public SectionNode {
public:
- SubsectionNode(NonnullRefPtr<SectionNode const> parent, StringView name);
+ SubsectionNode(NonnullRefPtr<SectionNode const> parent, StringView name, RefPtr<PageNode> page = {});
virtual ~SubsectionNode() = default;
virtual Node const* parent() const override;
@@ -23,6 +24,9 @@ public:
protected:
NonnullRefPtr<SectionNode const> m_parent;
+
+private:
+ RefPtr<PageNode> m_page;
};
}