From 6baa6517ca8e4a134acb2b1db0f40aae47d26d6b Mon Sep 17 00:00:00 2001 From: m1ngsama Date: Wed, 31 Dec 2025 17:19:01 +0800 Subject: [PATCH] feat: Implement functional web browsing with HTTP + HTML rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented the missing browser engine functionality to make TUT actually browse the web. Browser Engine Changes: - Integrate HttpClient to fetch URLs via GET requests - Integrate HtmlRenderer to parse and render HTML content - Implement proper error handling for failed HTTP requests - Add relative URL resolution for links (absolute and relative paths) - Store title, content, and links from rendered pages Tested with https://tldp.org/HOWTO/HOWTO-INDEX/howtos.html: ✅ Successfully fetches and displays web pages ✅ Renders HTML with proper formatting (headings, lists, links) ✅ Extracts and numbers clickable links ✅ Displays page titles The browser is now fully functional for basic text-based web browsing! --- src/core/browser_engine.cpp | 65 +++++++++++++++++++++++++++++++--- src/core/browser_engine.hpp | 10 +----- src/renderer/html_renderer.hpp | 3 +- src/ui/content_view.hpp | 3 +- 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/core/browser_engine.cpp b/src/core/browser_engine.cpp index 7b4e55f..514a373 100644 --- a/src/core/browser_engine.cpp +++ b/src/core/browser_engine.cpp @@ -4,6 +4,8 @@ */ #include "core/browser_engine.hpp" +#include "core/http_client.hpp" +#include "renderer/html_renderer.hpp" namespace tut { @@ -15,6 +17,9 @@ public: std::vector links_; std::vector history_; size_t history_index_{0}; + + HttpClient http_client_; + HtmlRenderer renderer_; }; BrowserEngine::BrowserEngine() : impl_(std::make_unique()) {} @@ -22,14 +27,66 @@ BrowserEngine::BrowserEngine() : impl_(std::make_unique()) {} BrowserEngine::~BrowserEngine() = default; bool BrowserEngine::loadUrl(const std::string& url) { - // TODO: 实现 HTTP 请求和 HTML 解析 impl_->current_url_ = url; - return true; + + // 发送 HTTP 请求 + auto response = impl_->http_client_.get(url); + + if (!response.isSuccess()) { + // 加载失败,设置错误内容 + impl_->title_ = "Error"; + impl_->content_ = "Failed to load page: " + + (response.error.empty() + ? "HTTP " + std::to_string(response.status_code) + : response.error); + impl_->links_.clear(); + return false; + } + + // 渲染 HTML + return loadHtml(response.body); } bool BrowserEngine::loadHtml(const std::string& html) { - // TODO: 实现 HTML 解析 - impl_->content_ = html; + // 渲染 HTML + RenderOptions options; + options.show_links = true; + options.use_colors = true; + + auto result = impl_->renderer_.render(html, options); + + impl_->title_ = result.title; + impl_->content_ = result.text; + impl_->links_ = result.links; + + // 解析相对 URL + if (!impl_->current_url_.empty()) { + for (auto& link : impl_->links_) { + if (link.url.find("://") == std::string::npos) { + // 简单的相对 URL 解析 + if (!link.url.empty() && link.url[0] == '/') { + // 绝对路径 + size_t scheme_end = impl_->current_url_.find("://"); + if (scheme_end != std::string::npos) { + size_t host_end = impl_->current_url_.find('/', scheme_end + 3); + std::string base = (host_end != std::string::npos) + ? impl_->current_url_.substr(0, host_end) + : impl_->current_url_; + link.url = base + link.url; + } + } else if (link.url.find("://") == std::string::npos && + !link.url.empty() && link.url[0] != '#') { + // 相对路径 + size_t last_slash = impl_->current_url_.rfind('/'); + if (last_slash != std::string::npos) { + std::string base = impl_->current_url_.substr(0, last_slash + 1); + link.url = base + link.url; + } + } + } + } + } + return true; } diff --git a/src/core/browser_engine.hpp b/src/core/browser_engine.hpp index fd80c6f..017c03e 100644 --- a/src/core/browser_engine.hpp +++ b/src/core/browser_engine.hpp @@ -11,18 +11,10 @@ #include #include #include +#include "types.hpp" namespace tut { -/** - * @brief 链接信息结构体 - */ -struct LinkInfo { - std::string url; ///< 链接 URL - std::string text; ///< 链接文本 - int line{0}; ///< 所在行号 -}; - /** * @brief 浏览器引擎类 * diff --git a/src/renderer/html_renderer.hpp b/src/renderer/html_renderer.hpp index 4f2c926..77c7842 100644 --- a/src/renderer/html_renderer.hpp +++ b/src/renderer/html_renderer.hpp @@ -10,11 +10,10 @@ #include #include #include +#include "../core/types.hpp" namespace tut { -struct LinkInfo; - /** * @brief 渲染选项 */ diff --git a/src/ui/content_view.hpp b/src/ui/content_view.hpp index 6e36da4..d3adfe8 100644 --- a/src/ui/content_view.hpp +++ b/src/ui/content_view.hpp @@ -11,11 +11,10 @@ #include #include #include +#include "../core/types.hpp" namespace tut { -struct LinkInfo; - /** * @brief 内容视图组件类 *