| 
									
										
										
										
											2023-08-28 14:47:29 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> | 
					
						
							| 
									
										
										
										
											2024-09-24 15:50:15 +01:00
										 |  |  |  * Copyright (c) 2024, Sam Atkins <sam@ladybird.org> | 
					
						
							| 
									
										
										
										
											2023-08-28 14:47:29 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <AK/String.h>
 | 
					
						
							|  |  |  | #include <AK/StringView.h>
 | 
					
						
							| 
									
										
										
										
											2024-09-24 15:50:15 +01:00
										 |  |  | #include <LibSyntax/Document.h>
 | 
					
						
							|  |  |  | #include <LibSyntax/HighlighterClient.h>
 | 
					
						
							|  |  |  | #include <LibSyntax/Language.h>
 | 
					
						
							| 
									
										
										
										
											2023-08-28 14:47:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace WebView { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-25 11:46:31 +01:00
										 |  |  | enum class HighlightOutputMode { | 
					
						
							|  |  |  |     FullDocument, // Include HTML header, title, style sheet, etc
 | 
					
						
							|  |  |  |     SourceOnly,   // Just the highlighted source
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-24 15:50:15 +01:00
										 |  |  | 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-25 11:46:31 +01:00
										 |  |  |     String to_html_string(String const&, HighlightOutputMode) const; | 
					
						
							| 
									
										
										
										
											2024-09-24 15:50:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-25 11:46:31 +01:00
										 |  |  | String highlight_source(String const&, StringView, Syntax::Language, HighlightOutputMode); | 
					
						
							| 
									
										
										
										
											2023-08-28 14:47:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 11:54:17 -05:00
										 |  |  | constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~( | 
					
						
							|  |  |  |     @media (prefers-color-scheme: dark) { | 
					
						
							|  |  |  |         /* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */ | 
					
						
							|  |  |  |         html { | 
					
						
							|  |  |  |             background-color: rgb(30, 30, 30); | 
					
						
							|  |  |  |             color: white; | 
					
						
							| 
									
										
										
										
											2024-09-25 11:58:39 +01:00
										 |  |  |             counter-reset: line; | 
					
						
							| 
									
										
										
										
											2023-11-22 11:54:17 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-09-24 16:19:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :root { | 
					
						
							|  |  |  |             --comment-color: lightgreen; | 
					
						
							|  |  |  |             --keyword-color: orangered; | 
					
						
							|  |  |  |             --name-color: orange; | 
					
						
							|  |  |  |             --value-color: deepskyblue; | 
					
						
							|  |  |  |             --internal-color: darkgrey; | 
					
						
							| 
									
										
										
										
											2024-09-24 16:30:23 +01:00
										 |  |  |             --string-color: goldenrod; | 
					
						
							|  |  |  |             --error-color: red; | 
					
						
							| 
									
										
										
										
											2024-09-25 11:58:39 +01:00
										 |  |  |             --line-number-color: darkgrey; | 
					
						
							| 
									
										
										
										
											2023-11-23 12:26:38 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-11-22 11:54:17 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @media (prefers-color-scheme: light) { | 
					
						
							| 
									
										
										
										
											2024-09-24 16:19:53 +01:00
										 |  |  |         :root { | 
					
						
							|  |  |  |             --comment-color: green; | 
					
						
							|  |  |  |             --keyword-color: red; | 
					
						
							|  |  |  |             --name-color: darkorange; | 
					
						
							|  |  |  |             --value-color: blue; | 
					
						
							|  |  |  |             --internal-color: dimgrey; | 
					
						
							| 
									
										
										
										
											2024-09-24 16:30:23 +01:00
										 |  |  |             --string-color: darkgoldenrod; | 
					
						
							|  |  |  |             --error-color: darkred; | 
					
						
							| 
									
										
										
										
											2024-09-25 11:58:39 +01:00
										 |  |  |             --line-number-color: dimgrey; | 
					
						
							| 
									
										
										
										
											2023-11-23 12:26:38 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-11-22 11:54:17 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-24 16:19:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     .html { | 
					
						
							|  |  |  |         font-size: 10pt; | 
					
						
							|  |  |  |         font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-25 11:58:39 +01:00
										 |  |  |     .line { | 
					
						
							|  |  |  |         counter-increment: line; | 
					
						
							|  |  |  |         white-space: pre; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .line::before { | 
					
						
							|  |  |  |         content: counter(line) " "; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         display: inline-block; | 
					
						
							|  |  |  |         width: 2.5em; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         padding-right: 0.5em; | 
					
						
							|  |  |  |         text-align: right; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         color: var(--line-number-color); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-24 16:19:53 +01:00
										 |  |  |     .tag { | 
					
						
							|  |  |  |         font-weight: 600; | 
					
						
							|  |  |  |         color: var(--keyword-color); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     .comment { | 
					
						
							|  |  |  |         color: var(--comment-color); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     .attribute-name { | 
					
						
							|  |  |  |         color: var(--name-color); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     .attribute-value { | 
					
						
							|  |  |  |         color: var(--value-color); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     .internal { | 
					
						
							|  |  |  |         color: var(--internal-color); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-24 16:30:23 +01:00
										 |  |  |     .invalid { | 
					
						
							|  |  |  |         color: var(--error-color); | 
					
						
							|  |  |  |         text-decoration: currentColor wavy underline; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     .at-keyword, .function, .keyword, .control-keyword, .url { | 
					
						
							|  |  |  |         color: var(--keyword-color); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     .number, .hash { | 
					
						
							|  |  |  |         color: var(--value-color); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     .string { | 
					
						
							|  |  |  |         color: var(--string-color); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-11-22 11:54:17 -05:00
										 |  |  | )~~~"sv; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-28 14:47:29 -04:00
										 |  |  | } |