mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibWebView: Highlight CSS and JS in view-source
The colors and categories here could probably be better, but it works. :^)
This commit is contained in:
parent
66c39f3da4
commit
bd6fdbf312
Notes:
github-actions[bot]
2024-09-30 07:54:36 +00:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/LadybirdBrowser/ladybird/commit/bd6fdbf312b Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1513
2 changed files with 135 additions and 17 deletions
|
@ -6,7 +6,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <LibJS/SyntaxHighlighter.h>
|
||||||
|
#include <LibJS/Token.h>
|
||||||
#include <LibURL/URL.h>
|
#include <LibURL/URL.h>
|
||||||
|
#include <LibWeb/CSS/Parser/Token.h>
|
||||||
|
#include <LibWeb/CSS/SyntaxHighlighter/SyntaxHighlighter.h>
|
||||||
#include <LibWeb/HTML/SyntaxHighlighter/SyntaxHighlighter.h>
|
#include <LibWeb/HTML/SyntaxHighlighter/SyntaxHighlighter.h>
|
||||||
#include <LibWebView/SourceHighlighter.h>
|
#include <LibWebView/SourceHighlighter.h>
|
||||||
|
|
||||||
|
@ -40,9 +44,15 @@ SourceHighlighterClient::SourceHighlighterClient(StringView source, Syntax::Lang
|
||||||
Gfx::Palette dummy_palette { palette_impl };
|
Gfx::Palette dummy_palette { palette_impl };
|
||||||
|
|
||||||
switch (language) {
|
switch (language) {
|
||||||
|
case Syntax::Language::CSS:
|
||||||
|
m_highlighter = make<Web::CSS::SyntaxHighlighter>();
|
||||||
|
break;
|
||||||
case Syntax::Language::HTML:
|
case Syntax::Language::HTML:
|
||||||
m_highlighter = make<Web::HTML::SyntaxHighlighter>();
|
m_highlighter = make<Web::HTML::SyntaxHighlighter>();
|
||||||
break;
|
break;
|
||||||
|
case Syntax::Language::JavaScript:
|
||||||
|
m_highlighter = make<JS::SyntaxHighlighter>();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -111,24 +121,115 @@ String highlight_source(URL::URL const& url, StringView source)
|
||||||
|
|
||||||
StringView SourceHighlighterClient::class_for_token(u64 token_type) const
|
StringView SourceHighlighterClient::class_for_token(u64 token_type) const
|
||||||
{
|
{
|
||||||
switch (static_cast<Web::HTML::AugmentedTokenKind>(token_type)) {
|
auto class_for_css_token = [](u64 token_type) {
|
||||||
case Web::HTML::AugmentedTokenKind::AttributeName:
|
switch (static_cast<Web::CSS::Parser::Token::Type>(token_type)) {
|
||||||
return "attribute-name"sv;
|
case Web::CSS::Parser::Token::Type::Invalid:
|
||||||
case Web::HTML::AugmentedTokenKind::AttributeValue:
|
case Web::CSS::Parser::Token::Type::BadString:
|
||||||
return "attribute-value"sv;
|
case Web::CSS::Parser::Token::Type::BadUrl:
|
||||||
case Web::HTML::AugmentedTokenKind::OpenTag:
|
return "invalid"sv;
|
||||||
case Web::HTML::AugmentedTokenKind::CloseTag:
|
case Web::CSS::Parser::Token::Type::Ident:
|
||||||
return "tag"sv;
|
return "identifier"sv;
|
||||||
case Web::HTML::AugmentedTokenKind::Comment:
|
case Web::CSS::Parser::Token::Type::Function:
|
||||||
return "comment"sv;
|
return "function"sv;
|
||||||
case Web::HTML::AugmentedTokenKind::Doctype:
|
case Web::CSS::Parser::Token::Type::AtKeyword:
|
||||||
return "doctype"sv;
|
return "at-keyword"sv;
|
||||||
case Web::HTML::AugmentedTokenKind::__Count:
|
case Web::CSS::Parser::Token::Type::Hash:
|
||||||
default:
|
return "hash"sv;
|
||||||
break;
|
case Web::CSS::Parser::Token::Type::String:
|
||||||
}
|
return "string"sv;
|
||||||
|
case Web::CSS::Parser::Token::Type::Url:
|
||||||
|
return "url"sv;
|
||||||
|
case Web::CSS::Parser::Token::Type::Number:
|
||||||
|
case Web::CSS::Parser::Token::Type::Dimension:
|
||||||
|
case Web::CSS::Parser::Token::Type::Percentage:
|
||||||
|
return "number"sv;
|
||||||
|
case Web::CSS::Parser::Token::Type::Whitespace:
|
||||||
|
return "whitespace"sv;
|
||||||
|
case Web::CSS::Parser::Token::Type::Delim:
|
||||||
|
case Web::CSS::Parser::Token::Type::Colon:
|
||||||
|
case Web::CSS::Parser::Token::Type::Semicolon:
|
||||||
|
case Web::CSS::Parser::Token::Type::Comma:
|
||||||
|
case Web::CSS::Parser::Token::Type::OpenSquare:
|
||||||
|
case Web::CSS::Parser::Token::Type::CloseSquare:
|
||||||
|
case Web::CSS::Parser::Token::Type::OpenParen:
|
||||||
|
case Web::CSS::Parser::Token::Type::CloseParen:
|
||||||
|
case Web::CSS::Parser::Token::Type::OpenCurly:
|
||||||
|
case Web::CSS::Parser::Token::Type::CloseCurly:
|
||||||
|
return "delimiter"sv;
|
||||||
|
case Web::CSS::Parser::Token::Type::CDO:
|
||||||
|
case Web::CSS::Parser::Token::Type::CDC:
|
||||||
|
return "comment"sv;
|
||||||
|
case Web::CSS::Parser::Token::Type::EndOfFile:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ""sv;
|
||||||
|
};
|
||||||
|
|
||||||
return "unknown"sv;
|
auto class_for_js_token = [](u64 token_type) {
|
||||||
|
auto category = JS::Token::category(static_cast<JS::TokenType>(token_type));
|
||||||
|
switch (category) {
|
||||||
|
case JS::TokenCategory::Invalid:
|
||||||
|
return "invalid"sv;
|
||||||
|
case JS::TokenCategory::Number:
|
||||||
|
return "number"sv;
|
||||||
|
case JS::TokenCategory::String:
|
||||||
|
return "string"sv;
|
||||||
|
case JS::TokenCategory::Punctuation:
|
||||||
|
return "punctuation"sv;
|
||||||
|
case JS::TokenCategory::Operator:
|
||||||
|
return "operator"sv;
|
||||||
|
case JS::TokenCategory::Keyword:
|
||||||
|
return "keyword"sv;
|
||||||
|
case JS::TokenCategory::ControlKeyword:
|
||||||
|
return "control-keyword"sv;
|
||||||
|
case JS::TokenCategory::Identifier:
|
||||||
|
return "identifier"sv;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ""sv;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (m_highlighter->language()) {
|
||||||
|
case Syntax::Language::CSS:
|
||||||
|
return class_for_css_token(token_type);
|
||||||
|
case Syntax::Language::JavaScript:
|
||||||
|
return class_for_js_token(token_type);
|
||||||
|
case Syntax::Language::HTML: {
|
||||||
|
// HTML has nested CSS and JS highlighters, so we have to decode their token types.
|
||||||
|
|
||||||
|
// HTML
|
||||||
|
if (token_type < Web::HTML::SyntaxHighlighter::JS_TOKEN_START_VALUE) {
|
||||||
|
switch (static_cast<Web::HTML::AugmentedTokenKind>(token_type)) {
|
||||||
|
case Web::HTML::AugmentedTokenKind::AttributeName:
|
||||||
|
return "attribute-name"sv;
|
||||||
|
case Web::HTML::AugmentedTokenKind::AttributeValue:
|
||||||
|
return "attribute-value"sv;
|
||||||
|
case Web::HTML::AugmentedTokenKind::OpenTag:
|
||||||
|
case Web::HTML::AugmentedTokenKind::CloseTag:
|
||||||
|
return "tag"sv;
|
||||||
|
case Web::HTML::AugmentedTokenKind::Comment:
|
||||||
|
return "comment"sv;
|
||||||
|
case Web::HTML::AugmentedTokenKind::Doctype:
|
||||||
|
return "doctype"sv;
|
||||||
|
case Web::HTML::AugmentedTokenKind::__Count:
|
||||||
|
default:
|
||||||
|
return ""sv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// JS
|
||||||
|
if (token_type < Web::HTML::SyntaxHighlighter::CSS_TOKEN_START_VALUE) {
|
||||||
|
return class_for_js_token(token_type - Web::HTML::SyntaxHighlighter::JS_TOKEN_START_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS
|
||||||
|
return class_for_css_token(token_type - Web::HTML::SyntaxHighlighter::CSS_TOKEN_START_VALUE);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return "unknown"sv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String generate_style()
|
static String generate_style()
|
||||||
|
|
|
@ -84,6 +84,8 @@ constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~(
|
||||||
--name-color: orange;
|
--name-color: orange;
|
||||||
--value-color: deepskyblue;
|
--value-color: deepskyblue;
|
||||||
--internal-color: darkgrey;
|
--internal-color: darkgrey;
|
||||||
|
--string-color: goldenrod;
|
||||||
|
--error-color: red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +96,8 @@ constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~(
|
||||||
--name-color: darkorange;
|
--name-color: darkorange;
|
||||||
--value-color: blue;
|
--value-color: blue;
|
||||||
--internal-color: dimgrey;
|
--internal-color: dimgrey;
|
||||||
|
--string-color: darkgoldenrod;
|
||||||
|
--error-color: darkred;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +122,19 @@ constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~(
|
||||||
.internal {
|
.internal {
|
||||||
color: var(--internal-color);
|
color: var(--internal-color);
|
||||||
}
|
}
|
||||||
|
.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);
|
||||||
|
}
|
||||||
)~~~"sv;
|
)~~~"sv;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue