2020-08-01 03:05:43 +01:00
/*
2021-04-28 22:46:44 +02:00
* Copyright ( c ) 2020 , the SerenityOS developers .
2023-07-28 02:20:57 +01:00
* Copyright ( c ) 2023 , Luke Wilde < lukew @ serenityos . org >
2020-08-01 03:05:43 +01:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-08-01 03:05:43 +01:00
*/
2024-11-05 09:12:11 +01:00
# include <AK/GenericLexer.h>
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/HTMLMetaElementPrototype.h>
2022-09-30 17:16:16 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2023-09-19 01:51:48 +02:00
# include <LibWeb/CSS/Parser/Parser.h>
# include <LibWeb/CSS/PropertyID.h>
2024-08-14 16:37:02 +01:00
# include <LibWeb/CSS/StyleValues/CSSColorValue.h>
2025-01-04 09:59:57 +11:00
# include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
2023-07-28 02:20:57 +01:00
# include <LibWeb/DOM/Document.h>
2020-08-01 03:05:43 +01:00
# include <LibWeb/HTML/HTMLMetaElement.h>
2023-09-19 01:51:48 +02:00
# include <LibWeb/Infra/CharacterTypes.h>
# include <LibWeb/Page/Page.h>
2020-08-01 03:05:43 +01:00
namespace Web : : HTML {
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( HTMLMetaElement ) ;
2023-11-19 19:47:52 +01:00
2022-02-18 21:00:52 +01:00
HTMLMetaElement : : HTMLMetaElement ( DOM : : Document & document , DOM : : QualifiedName qualified_name )
2021-02-07 11:20:15 +01:00
: HTMLElement ( document , move ( qualified_name ) )
2020-08-01 03:05:43 +01:00
{
}
2022-03-14 13:21:51 -06:00
HTMLMetaElement : : ~ HTMLMetaElement ( ) = default ;
2020-08-01 03:05:43 +01:00
2023-08-07 08:41:28 +02:00
void HTMLMetaElement : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( HTMLMetaElement ) ;
2025-04-20 16:22:57 +02:00
Base : : initialize ( realm ) ;
2023-01-10 06:28:20 -05:00
}
2023-07-28 02:20:57 +01:00
Optional < HTMLMetaElement : : HttpEquivAttributeState > HTMLMetaElement : : http_equiv_state ( ) const
{
2024-01-16 19:04:45 +01:00
auto value = get_attribute_value ( HTML : : AttributeNames : : http_equiv ) ;
2023-07-28 02:20:57 +01:00
# define __ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTE(keyword, state) \
2024-09-13 11:35:34 +02:00
if ( value . equals_ignoring_ascii_case ( keyword # # sv ) ) \
2023-07-28 02:20:57 +01:00
return HTMLMetaElement : : HttpEquivAttributeState : : state ;
ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTES
# undef __ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTE
return OptionalNone { } ;
}
2025-01-04 09:59:57 +11:00
void HTMLMetaElement : : update_metadata ( Optional < String > const & old_name )
{
if ( name ( ) . has_value ( ) ) {
2025-01-04 09:59:57 +11:00
if ( name ( ) - > equals_ignoring_ascii_case ( " theme-color " sv ) ) {
document ( ) . obtain_theme_color ( ) ;
} else if ( name ( ) - > equals_ignoring_ascii_case ( " color-scheme " sv ) ) {
2025-01-04 09:59:57 +11:00
document ( ) . obtain_supported_color_schemes ( ) ;
return ;
}
}
if ( old_name . has_value ( ) ) {
2025-01-04 09:59:57 +11:00
if ( old_name - > equals_ignoring_ascii_case ( " theme-color " sv ) ) {
document ( ) . obtain_theme_color ( ) ;
} else if ( old_name - > equals_ignoring_ascii_case ( " color-scheme " sv ) ) {
2025-01-04 09:59:57 +11:00
document ( ) . obtain_supported_color_schemes ( ) ;
return ;
}
}
}
2023-07-28 02:20:57 +01:00
void HTMLMetaElement : : inserted ( )
{
Base : : inserted ( ) ;
2025-01-04 09:59:57 +11:00
update_metadata ( ) ;
2023-07-28 02:20:57 +01:00
// https://html.spec.whatwg.org/multipage/semantics.html#pragma-directives
// When a meta element is inserted into the document, if its http-equiv attribute is present and represents one of
// the above states, then the user agent must run the algorithm appropriate for that state, as described in the
// following list:
auto http_equiv = http_equiv_state ( ) ;
if ( http_equiv . has_value ( ) ) {
switch ( http_equiv . value ( ) ) {
2024-09-13 11:44:35 +02:00
case HttpEquivAttributeState : : EncodingDeclaration :
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type
// The Encoding declaration state is just an alternative form of setting the charset attribute: it is a character encoding declaration.
// This state's user agent requirements are all handled by the parsing section of the specification.
break ;
2023-07-28 02:20:57 +01:00
case HttpEquivAttributeState : : Refresh : {
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh
// 1. If the meta element has no content attribute, or if that attribute's value is the empty string, then return.
// 2. Let input be the value of the element's content attribute.
if ( ! has_attribute ( AttributeNames : : content ) )
break ;
2024-01-16 19:04:45 +01:00
auto input = get_attribute_value ( AttributeNames : : content ) ;
2023-07-28 02:20:57 +01:00
if ( input . is_empty ( ) )
break ;
// 3. Run the shared declarative refresh steps with the meta element's node document, input, and the meta element.
document ( ) . shared_declarative_refresh_steps ( input , this ) ;
break ;
}
2024-09-13 11:44:35 +02:00
case HttpEquivAttributeState : : SetCookie :
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-set-cookie
// This pragma is non-conforming and has no effect.
// User agents are required to ignore this pragma.
break ;
case HttpEquivAttributeState : : XUACompatible :
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-x-ua-compatible
// In practice, this pragma encourages Internet Explorer to more closely follow the specifications.
// For meta elements with an http-equiv attribute in the X-UA-Compatible state, the content attribute must have a value that is an ASCII case-insensitive match for the string "IE=edge".
// User agents are required to ignore this pragma.
break ;
2024-11-05 09:12:11 +01:00
case HttpEquivAttributeState : : ContentLanguage : {
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-language
// 1. If the meta element has no content attribute, then return.
if ( ! has_attribute ( AttributeNames : : content ) )
break ;
// 2. If the element's content attribute contains a U+002C COMMA character (,) then return.
auto content = get_attribute_value ( AttributeNames : : content ) ;
if ( content . contains ( " , " sv ) )
break ;
// 3. Let input be the value of the element's content attribute.
// 4. Let position point at the first character of input.
GenericLexer lexer { content } ;
// 5. Skip ASCII whitespace within input given position.
lexer . ignore_while ( Web : : Infra : : is_ascii_whitespace ) ;
// 6. Collect a sequence of code points that are not ASCII whitespace from input given position.
// 7. Let candidate be the string that resulted from the previous step.
auto candidate = lexer . consume_until ( Web : : Infra : : is_ascii_whitespace ) ;
// 8. If candidate is the empty string, return.
if ( candidate . is_empty ( ) )
break ;
// 9. Set the pragma-set default language to candidate.
auto language = String : : from_utf8_without_validation ( candidate . bytes ( ) ) ;
document ( ) . set_pragma_set_default_language ( language ) ;
break ;
}
2023-07-28 02:20:57 +01:00
default :
2024-01-16 19:04:45 +01:00
dbgln ( " FIXME: Implement '{}' http-equiv state " , get_attribute_value ( AttributeNames : : http_equiv ) ) ;
2023-07-28 02:20:57 +01:00
break ;
}
}
}
2025-01-23 17:37:18 +01:00
void HTMLMetaElement : : removed_from ( Node * old_parent , Node & old_root )
2025-01-04 09:59:57 +11:00
{
2025-01-23 17:37:18 +01:00
Base : : removed_from ( old_parent , old_root ) ;
2025-01-04 09:59:57 +11:00
update_metadata ( ) ;
}
void HTMLMetaElement : : attribute_changed ( FlyString const & local_name , Optional < String > const & old_value , Optional < String > const & value , Optional < FlyString > const & namespace_ )
{
Base : : attribute_changed ( local_name , old_value , value , namespace_ ) ;
if ( local_name = = HTML : : AttributeNames : : name ) {
update_metadata ( old_value ) ;
} else {
update_metadata ( ) ;
}
}
2020-08-01 03:05:43 +01:00
}