diff options
-rw-r--r-- | Userland/Libraries/LibManual/SectionNode.cpp | 39 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/SubsectionNode.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/SubsectionNode.h | 6 |
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; }; } |