LibWebView: Use LibSyntax to highlight document source

This has no visible effect, but internally it's also highlighting any
CSS and JS embedded in the page, which will be made use of later. We'll
also be able to use this code for highlighting CSS or JS files directly
in the future.

It's not a perfect fit - the syntax highlighters give specific styles to
their spans, which we then ignore and just use their data integer to
figure out which CSS class to give to the span. It feels cleaner to me
to produce HTML styled that way, instead of every token having
`style="color: ...; font-weight: ...; text-decoration: ...;"` set on
it.

Most of this new `to_html_string()` code is adapted from Serenity's
`TextEditor::paint_event()`, so it should be pretty solid.
This commit is contained in:
Sam Atkins 2024-09-24 15:50:15 +01:00 committed by Sam Atkins
commit 1db243c006
Notes: github-actions[bot] 2024-09-30 07:54:46 +00:00
3 changed files with 258 additions and 66 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -8,9 +9,65 @@
#include <AK/String.h>
#include <AK/StringView.h>
#include <LibSyntax/Document.h>
#include <LibSyntax/HighlighterClient.h>
#include <LibSyntax/Language.h>
namespace WebView {
class SourceDocument final : public Syntax::Document {
public:
static NonnullRefPtr<SourceDocument> create(StringView source)
{
return adopt_ref(*new (nothrow) SourceDocument(source));
}
virtual ~SourceDocument() = default;
StringView text() const { return m_source; }
size_t line_count() const { return m_lines.size(); }
// ^ Syntax::Document
virtual Syntax::TextDocumentLine const& line(size_t line_index) const override;
virtual Syntax::TextDocumentLine& line(size_t line_index) override;
private:
SourceDocument(StringView source);
// ^ Syntax::Document
virtual void update_views(Badge<Syntax::TextDocumentLine>) override { }
StringView m_source;
Vector<Syntax::TextDocumentLine> m_lines;
};
class SourceHighlighterClient final : public Syntax::HighlighterClient {
public:
SourceHighlighterClient(StringView source, Syntax::Language);
virtual ~SourceHighlighterClient() = default;
String to_html_string(URL::URL const&) const;
private:
// ^ Syntax::HighlighterClient
virtual Vector<Syntax::TextDocumentSpan> const& spans() const override;
virtual void set_span_at_index(size_t index, Syntax::TextDocumentSpan span) override;
virtual Vector<Syntax::TextDocumentFoldingRegion>& folding_regions() override;
virtual Vector<Syntax::TextDocumentFoldingRegion> const& folding_regions() const override;
virtual ByteString highlighter_did_request_text() const override;
virtual void highlighter_did_request_update() override;
virtual Syntax::Document& highlighter_did_request_document() override;
virtual Syntax::TextPosition highlighter_did_request_cursor() const override;
virtual void highlighter_did_set_spans(Vector<Syntax::TextDocumentSpan>) override;
virtual void highlighter_did_set_folding_regions(Vector<Syntax::TextDocumentFoldingRegion>) override;
StringView class_for_token(u64 token_type) const;
SourceDocument& document() const { return *m_document; }
NonnullRefPtr<SourceDocument> m_document;
OwnPtr<Syntax::Highlighter> m_highlighter;
};
String highlight_source(URL::URL const&, StringView);
constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~(