From e2ea308100cec588144bed4746b51ff2d9fd8e0c Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 19 Sep 2023 16:04:39 +0200 Subject: [PATCH] [mujs] element.style (getter) --- src/ecmascript/libdom/mujs/Makefile | 3 +- src/ecmascript/libdom/mujs/element.c | 17 +++ src/ecmascript/libdom/mujs/mapa.cpp | 124 ++++++++++++++++ src/ecmascript/libdom/mujs/mapa.h | 5 + src/ecmascript/libdom/mujs/meson.build | 2 +- src/ecmascript/libdom/mujs/style.c | 196 +++++++++++++++++++++++++ src/ecmascript/mujs/style.h | 16 ++ 7 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 src/ecmascript/libdom/mujs/style.c create mode 100644 src/ecmascript/mujs/style.h diff --git a/src/ecmascript/libdom/mujs/Makefile b/src/ecmascript/libdom/mujs/Makefile index 099ffc51..7bb7e1fd 100644 --- a/src/ecmascript/libdom/mujs/Makefile +++ b/src/ecmascript/libdom/mujs/Makefile @@ -1,6 +1,7 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.config -OBJS = attr.o attributes.o collection.o console.o document.o element.o form.o forms.o history.o implementation.o input.o keyboard.o localstorage.o location.o mapa.obj message.o navigator.o nodelist.o screen.o unibar.o window.o xhr.o +OBJS = attr.o attributes.o collection.o console.o document.o element.o form.o forms.o history.o implementation.o input.o \ + keyboard.o localstorage.o location.o mapa.obj message.o navigator.o nodelist.o screen.o style.o unibar.o window.o xhr.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/libdom/mujs/element.c b/src/ecmascript/libdom/mujs/element.c index c124e212..8aac2566 100644 --- a/src/ecmascript/libdom/mujs/element.c +++ b/src/ecmascript/libdom/mujs/element.c @@ -36,6 +36,7 @@ #include "ecmascript/mujs/element.h" #include "ecmascript/mujs/keyboard.h" #include "ecmascript/mujs/nodelist.h" +#include "ecmascript/mujs/style.h" #include "ecmascript/mujs/window.h" #include "intl/libintl.h" #include "main/select.h" @@ -700,6 +701,21 @@ mjs_element_get_property_previousSibling(js_State *J) mjs_push_element(J, node); } +static void +mjs_element_get_property_style(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + dom_node *el = (dom_node *)(mjs_getprivate(J, 0)); + + if (!el) { + js_pushnull(J); + return; + } + mjs_push_style(J, el); +} + static void mjs_element_get_property_tagName(js_State *J) { @@ -2402,6 +2418,7 @@ mjs_push_element(js_State *J, void *node) addproperty(J, "parentNode", mjs_element_get_property_parentNode, NULL); addproperty(J, "previousElementSibling", mjs_element_get_property_previousElementSibling, NULL); addproperty(J, "previousSibling", mjs_element_get_property_previousSibling, NULL); + addproperty(J, "style", mjs_element_get_property_style, NULL); addproperty(J, "tagName", mjs_element_get_property_tagName, NULL); addproperty(J, "textContent", mjs_element_get_property_textContent, NULL); addproperty(J, "title", mjs_element_get_property_title, mjs_element_set_property_title); diff --git a/src/ecmascript/libdom/mujs/mapa.cpp b/src/ecmascript/libdom/mujs/mapa.cpp index 75f313e4..9256bec1 100644 --- a/src/ecmascript/libdom/mujs/mapa.cpp +++ b/src/ecmascript/libdom/mujs/mapa.cpp @@ -272,3 +272,127 @@ get_output_header(const char *header_name, struct mjs_xhr *x) return NULL; } + +const std::map good = { + { "background", true }, + { "background-color", true }, + { "color", true }, + { "display", true }, + { "font-style", true }, + { "font-weight", true }, + { "list-style", true }, + { "list-style-type", true }, + { "text-align", true }, + { "text-decoration", true }, + { "white-space", true } +}; + +static std::string +trimString(std::string str) +{ + const std::string whiteSpaces = " \t\n\r\f\v"; + // Remove leading whitespace + size_t first_non_space = str.find_first_not_of(whiteSpaces); + str.erase(0, first_non_space); + // Remove trailing whitespace + size_t last_non_space = str.find_last_not_of(whiteSpaces); + str.erase(last_non_space + 1); + + return str; +} + +void * +set_elstyle(const char *text) +{ + if (!text || !*text) { + return NULL; + } + std::stringstream str(text); + std::string word; + std::string param, value; + std::map *css = NULL; + + while (!str.eof()) { + getline(str, word, ';'); + std::stringstream params(word); + getline(params, param, ':'); + getline(params, value, ':'); + param = trimString(param); + value = trimString(value); + + if (good.find(param) != good.end()) { + if (!css) { + css = new std::map; + } + if (css) { + (*css)[param] = value; + } + } + } + + return (void *)css; +} + +const char * +get_elstyle(void *m) +{ + std::map *css = static_cast *>(m); + std::string delimiter(""); + std::stringstream output(""); + std::map::iterator it; + + for (it = css->begin(); it != css->end(); it++) { + output << delimiter << it->first << ":" << it->second; + delimiter = ";"; + } + return stracpy(output.str().c_str()); +} + +const char * +get_css_value(const char *text, const char *param) +{ + void *m = set_elstyle(text); + char *res = NULL; + + if (!m) { + return stracpy(""); + } + + std::map *css = static_cast *>(m); + + if (css->find(param) != css->end()) { + res = stracpy((*css)[param].c_str()); + } else { + res = stracpy(""); + } + css->clear(); + delete css; + + return res; +} + +const char * +set_css_value(const char *text, const char *param, const char *value) +{ + void *m = set_elstyle(text); + std::map *css = NULL; + + if (m) { + css = static_cast *>(m); + + if (good.find(param) != good.end()) { + (*css)[param] = value; + } + return get_elstyle(m); + } + + if (good.find(param) != good.end()) { + css = new std::map; + if (!css) { + return stracpy(""); + } + (*css)[param] = value; + return get_elstyle((void *)css); + } + return stracpy(""); +} diff --git a/src/ecmascript/libdom/mujs/mapa.h b/src/ecmascript/libdom/mujs/mapa.h index 2593f8f2..02bc7ea3 100644 --- a/src/ecmascript/libdom/mujs/mapa.h +++ b/src/ecmascript/libdom/mujs/mapa.h @@ -47,6 +47,11 @@ void set_xhr_header(char *normalized_value, const char *h_name, struct mjs_xhr * const char *get_output_headers(struct mjs_xhr *x); const char *get_output_header(const char *header_name, struct mjs_xhr *x); +const char *get_elstyle(void *m); +void *set_elstyle(const char *text); +const char *get_css_value(const char *text, const char *param); +const char *set_css_value(const char *text, const char *param, const char *value); + #ifdef __cplusplus } #endif diff --git a/src/ecmascript/libdom/mujs/meson.build b/src/ecmascript/libdom/mujs/meson.build index 9b5dca23..45f20645 100644 --- a/src/ecmascript/libdom/mujs/meson.build +++ b/src/ecmascript/libdom/mujs/meson.build @@ -1,2 +1,2 @@ srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'document.c', 'element.c', 'form.c', 'forms.c', 'history.c', 'implementation.c', 'input.c', 'keyboard.c', -'localstorage.c', 'location.c', 'mapa.cpp', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'unibar.c', 'window.c', 'xhr.c') +'localstorage.c', 'location.c', 'mapa.cpp', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'style.c', 'unibar.c', 'window.c', 'xhr.c') diff --git a/src/ecmascript/libdom/mujs/style.c b/src/ecmascript/libdom/mujs/style.c new file mode 100644 index 00000000..c9fe611d --- /dev/null +++ b/src/ecmascript/libdom/mujs/style.c @@ -0,0 +1,196 @@ +/* The MuJS attr object implementation. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef CONFIG_LIBDOM +#include +#include +#endif + +#include "elinks.h" + +#include "document/libdom/corestrings.h" +#include "ecmascript/ecmascript.h" +#include "ecmascript/libdom/mujs/mapa.h" +#include "ecmascript/mujs.h" +#include "ecmascript/mujs/style.h" + +static void +mjs_style(js_State *J, const char *property) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + dom_exception exc; + dom_node *el = (struct dom_node *)js_touserdata(J, 0, "style"); + dom_string *style = NULL; + const char *res = NULL; + + if (!el) { + js_pushnull(J); + return; + } + exc = dom_element_get_attribute(el, corestring_dom_style, &style); + + if (exc != DOM_NO_ERR) { + js_pushstring(J, ""); + return; + } + + if (!style || !dom_string_length(style)) { + js_pushstring(J, ""); + + if (style) { + dom_string_unref(style); + } + return; + } + + res = get_css_value(dom_string_data(style), property); + dom_string_unref(style); + + if (!res) { + js_pushstring(J, ""); + return; + } + js_pushstring(J, res); + mem_free(res); +} + +static void +mjs_style_get_property_background(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "background"); +} + +static void +mjs_style_get_property_backgroundColor(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "background-color"); +} + +static void +mjs_style_get_property_color(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "color"); +} +static void +mjs_style_get_property_display(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "display"); +} + +static void +mjs_style_get_property_fontStyle(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "font-style"); +} + +static void +mjs_style_get_property_fontWeight(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "font-weight"); +} + +static void +mjs_style_get_property_listStyle(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "list-style"); +} + +static void +mjs_style_get_property_listStyleType(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "list-style-type"); +} + +static void +mjs_style_get_property_textAlign(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "text-align"); +} + +static void +mjs_style_get_property_textDecoration(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "text-decoration"); +} + +static void +mjs_style_get_property_whiteSpace(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + mjs_style(J, "white-space"); +} + + +static void +mjs_style_toString(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + js_pushstring(J, "[style object]"); +} + +static +void mjs_style_finalizer(js_State *J, void *node) +{ +} + +void +mjs_push_style(js_State *J, void *node) +{ + js_newobject(J); + { + js_newuserdata(J, "style", node, mjs_style_finalizer); + addmethod(J, "toString", mjs_style_toString, 0); + addproperty(J, "background", mjs_style_get_property_background, NULL); + addproperty(J, "backgroundColor", mjs_style_get_property_backgroundColor, NULL); + addproperty(J, "color", mjs_style_get_property_color, NULL); + addproperty(J, "display", mjs_style_get_property_display, NULL); + addproperty(J, "fontStyle", mjs_style_get_property_fontStyle, NULL); + addproperty(J, "fontWeight", mjs_style_get_property_fontWeight, NULL); + addproperty(J, "listStyle", mjs_style_get_property_listStyle, NULL); + addproperty(J, "listStyleType", mjs_style_get_property_listStyleType, NULL); + addproperty(J, "textAlign", mjs_style_get_property_textAlign, NULL); + addproperty(J, "textDecoration", mjs_style_get_property_textDecoration, NULL); + addproperty(J, "whiteSpace", mjs_style_get_property_whiteSpace, NULL); + } +} diff --git a/src/ecmascript/mujs/style.h b/src/ecmascript/mujs/style.h new file mode 100644 index 00000000..e2cb876c --- /dev/null +++ b/src/ecmascript/mujs/style.h @@ -0,0 +1,16 @@ +#ifndef EL__ECMASCRIPT_MUJS_STYLE_H +#define EL__ECMASCRIPT_MUJS_STYLE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void mjs_push_style(js_State *J, void *node); + +#ifdef __cplusplus +} +#endif + +#endif