diff options
author | robot-piglet <[email protected]> | 2025-07-16 10:20:41 +0300 |
---|---|---|
committer | robot-piglet <[email protected]> | 2025-07-16 10:34:35 +0300 |
commit | 620507e761ed6b11758e43a6e4ff5cc4d6c2e2cb (patch) | |
tree | 91020fe5f2d55ee0174cefad8f1f4a56aa64a190 /yql/essentials/utils/docs/markdown.cpp | |
parent | 37a359136f861e7e9de7fc1755779e731d9ff0fe (diff) |
Intermediate changes
commit_hash:5aaa14131e1a44bd5ff318aaed16345258d4c42e
Diffstat (limited to 'yql/essentials/utils/docs/markdown.cpp')
-rw-r--r-- | yql/essentials/utils/docs/markdown.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/yql/essentials/utils/docs/markdown.cpp b/yql/essentials/utils/docs/markdown.cpp new file mode 100644 index 00000000000..4af1357f1fe --- /dev/null +++ b/yql/essentials/utils/docs/markdown.cpp @@ -0,0 +1,74 @@ +#include "markdown.h" + +#include <yql/essentials/utils/yql_panic.h> + +#include <contrib/libs/re2/re2/re2.h> + +#include <util/generic/yexception.h> + +namespace NSQLComplete { + + class TMarkdownParser { + public: + void Parse(IInputStream& markdown, TMarkdownCallback&& onSection) { + for (TString line; markdown.ReadLine(line) != 0;) { + if (IsSkipping_) { + if (IsSectionHeader(line)) { + ResetSection(std::move(line)); + IsSkipping_ = false; + } else { + // Skip + } + } else { + if (IsSectionHeader(line)) { + onSection(std::move(Section_)); + ResetSection(std::move(line)); + } else { + Section_.Body.append(std::move(line)); + } + } + } + + if (!IsSkipping_) { + onSection(std::move(Section_)); + } + } + + private: + void ResetSection(TString&& line) { + Section_ = TMarkdownSection(); + + TString content; + std::optional<TString> dummy; + std::optional<TString> anchor; + YQL_ENSURE( + RE2::FullMatch(line, SectionHeaderRegex_, &content, &dummy, &anchor), + "line '" << line << "' does not match regex '" + << SectionHeaderRegex_.pattern() << "'"); + + Section_.Header.Content = std::move(content); + if (anchor) { + Section_.Header.Anchor = std::move(*anchor); + } + } + + bool IsSectionHeader(TStringBuf line) const { + return HeaderDepth(line) == 2; + } + + size_t HeaderDepth(TStringBuf line) const { + size_t pos = line.find_first_not_of('#'); + return pos != TStringBuf::npos ? pos : 0; + } + + RE2 SectionHeaderRegex_{R"re(## ([^#]+)(\s+{(#[a-z\-_]+)})?)re"}; + bool IsSkipping_ = true; + TMarkdownSection Section_; + }; + + void ParseMarkdown(IInputStream& markdown, TMarkdownCallback&& onSection) { + TMarkdownParser parser; + parser.Parse(markdown, std::forward<TMarkdownCallback>(onSection)); + } + +} // namespace NSQLComplete |