#include "link_page.h" #include "name.h" #include #include namespace NYql::NDocs { TMaybe MatchSingleFunctionHeader(TStringBuf header) { return NormalizedName(TString(header)); } TVector SplitBy(TStringBuf delim, const TVector& strings) { TVector parts; for (const TString& s : strings) { StringSplitter(s).SplitByString(delim).AddTo(&parts); } return parts; } TVector SplitByPunctuation(TStringBuf header) { TVector parts = {TString(header)}; parts = SplitBy(" и ", parts); parts = SplitBy(" / ", parts); parts = SplitBy(", ", parts); return parts; } TVector MatchMultiFunctionHeader(TStringBuf header) { TVector names = SplitByPunctuation(header); for (TString& name : names) { TMaybe normalized = NormalizedName(std::move(name)); if (!normalized) { return {}; } name = std::move(*normalized); } return names; } TVector ExtractNormalized(TStringBuf header) { if (auto single = MatchSingleFunctionHeader(header)) { return {*single}; } if (auto multi = MatchMultiFunctionHeader(header)) { return multi; } return {}; } void EnrichFromMarkdown(TLinks& links, const TString& path, const TMarkdownHeader& header) { for (const TString& name : ExtractNormalized(header.Content)) { links[name] = { .RelativePath = path, .Anchor = header.Anchor, }; } } void EnrichFromMarkdown(TLinks& links, const TString& path, const TMarkdownPage& page) { for (const auto& [anchor, section] : page.SectionsByAnchor) { const TMarkdownHeader& header = section.Header; EnrichFromMarkdown(links, path, header); } } void EnrichFromMarkdown(TLinks& links, const TPages& pages) { for (const auto& [path, page] : pages) { EnrichFromMarkdown(links, path, page); } } TLinks GetLinksFromPages(const TPages& pages) { TLinks links; EnrichFromMarkdown(links, pages); return links; } TPages Stripped(TPages&& pages, const TLinks& links) { THashSet usedPaths; THashMap> usedAnchors; for (const auto& [_, link] : links) { TString anchor = link.Anchor.GetOrElse(""); usedAnchors[link.RelativePath].emplace(std::move(anchor)); } THashSet unusedPaths; THashMap> unusedAnchors; for (const auto& [path, page] : pages) { for (const auto& [anchor, _] : page.SectionsByAnchor) { if (!usedAnchors.contains(path)) { unusedPaths.emplace(path); } else if (!usedAnchors[path].contains(anchor)) { unusedAnchors[path].emplace(anchor); } } } for (const auto& [path, anchors] : unusedAnchors) { for (const auto& anchor : anchors) { pages[path].SectionsByAnchor.erase(anchor); } } for (const auto& path : unusedPaths) { pages.erase(path); } return pages; } } // namespace NYql::NDocs