From b3524eba1e0780912a3dd9ed44f164d64431b556 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Tue, 31 Mar 2026 23:58:07 +0800 Subject: [PATCH] css: use css code in a file with HTML label --- examples/css.html | 13 +------ examples/style.css | 10 +++++ html/abc_css.c | 93 +++++++++++++++++++++++++++++++++++--------- html/abc_html.c | 27 ++++++++++--- html/abc_io.h | 5 ++- html/abc_io_util.c | 86 ++++++++++++++++++++++++++++++++++++++++ html/abc_obj.h | 2 + js/util/scf_string.c | 15 +++++++ js/util/scf_string.h | 9 +++-- ui/abc_layout.c | 1 + ui/abc_render.c | 1 + 11 files changed, 219 insertions(+), 43 deletions(-) create mode 100644 examples/style.css diff --git a/examples/css.html b/examples/css.html index 5fe9069..9b738ff 100644 --- a/examples/css.html +++ b/examples/css.html @@ -1,18 +1,7 @@ - + diff --git a/examples/style.css b/examples/style.css new file mode 100644 index 0000000..9306941 --- /dev/null +++ b/examples/style.css @@ -0,0 +1,10 @@ +#a /*css comment*/ +{ + color:blue; + text-align:center; +} + +p.red +{ + color:red; +} diff --git a/html/abc_css.c b/html/abc_css.c index 33d386d..c7394d2 100644 --- a/html/abc_css.c +++ b/html/abc_css.c @@ -358,9 +358,42 @@ static int __css_parse_obj(abc_obj_t* css, abc_char_t* c) int abc_css_parse(abc_obj_t* css) { - abc_char_t* c; - abc_char_t* c2; - abc_io_t* io = abc_io_array[ABC_PROTO_STR]; + scf_string_t* spath = NULL; + abc_char_t* c; + abc_char_t* c2; + abc_io_t* io = NULL; + abc_obj_t* href; + char* path; + int n; + + switch (css->type) + { + case ABC_HTML_STYLE: + if (!css->text) + return 0; + + n = 0; + io = abc_io_array[ABC_PROTO_STR]; + path = css->text->data; + break; + + case ABC_HTML_LINK: + href = abc_obj_get_attr(css, ABC_HTML_ATTR_HREF); + if (!href) + return 0; + + n = __io_url_path(&io, &spath, css->file->data, href->value->data); + if (n < 0) + return n; + + path = spath->data; + break; + default: + return 0; + break; + }; + + scf_logw("css->file: %s, path: %s\n", css->file->data, path); css->io.proto = io->proto; css->io.priv = NULL; @@ -372,7 +405,11 @@ int abc_css_parse(abc_obj_t* css) css->text_line = 1; css->text_pos = 0; - int ret = io->open(&css->io, css->text->data); + int ret = io->open(&css->io, path + n); + if (spath) { + scf_string_free(spath); + spath = NULL; + } if (ret < 0) return ret; @@ -434,38 +471,56 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj) scf_list_t* l; scf_list_t* l2; + scf_list_t* l3; + abc_obj_t* head; abc_obj_t* css; abc_obj_t* label; abc_obj_t* attr; - css = abc_obj_find_type(html->root, ABC_HTML_STYLE); - if (!css) + head = abc_obj_find_type(html->root, ABC_HTML_HEAD); + if (!head) return 0; - for (l = scf_list_head(&css->childs); l != scf_list_sentinel(&css->childs); l = scf_list_next(l)) { - label = scf_list_data(l, abc_obj_t, list); + for (l = scf_list_head(&head->childs); l != scf_list_sentinel(&head->childs); l = scf_list_next(l)) { + css = scf_list_data(l, abc_obj_t, list); - if (ABC_CSS_ID == label->type || ABC_CSS_CLASS == label->type) + if (ABC_HTML_LINK == css->type) { - attr = abc_obj_get_attr(obj, label->type); + attr = abc_obj_get_attr(css, ABC_HTML_ATTR_TYPE); if (!attr) continue; - if (strcmp(attr->value->data, label->text->data + label->css_dot + 1)) + if (strcmp(attr->value->data, "text/css")) continue; - if (label->css_dot > 0) { - if (strncmp(obj->keys[0], label->text->data, label->css_dot)) + } else if (ABC_HTML_STYLE != css->type) + continue; + + for (l2 = scf_list_head(&css->childs); l2 != scf_list_sentinel(&css->childs); l2 = scf_list_next(l2)) { + label = scf_list_data(l2, abc_obj_t, list); + + if (ABC_CSS_ID == label->type || ABC_CSS_CLASS == label->type) + { + attr = abc_obj_get_attr(obj, label->type); + if (!attr) continue; - } - } else if (label->type != obj->type) - continue; + if (strcmp(attr->value->data, label->text->data + label->css_dot + 1)) + continue; + + if (label->css_dot > 0) { + if (strncmp(obj->keys[0], label->text->data, label->css_dot)) + continue; + } - for (l2 = scf_list_head(&label->attrs); l2 != scf_list_sentinel(&label->attrs); l2 = scf_list_next(l2)) { - attr = scf_list_data(l2, abc_obj_t, list); + } else if (label->type != obj->type) + continue; - abc_recursive_set_attr(obj, attr->type, attr->value->data); + for (l3 = scf_list_head(&label->attrs); l3 != scf_list_sentinel(&label->attrs); l3 = scf_list_next(l3)) { + attr = scf_list_data(l3, abc_obj_t, list); + + abc_recursive_set_attr(obj, attr->type, attr->value->data); + } } } diff --git a/html/abc_html.c b/html/abc_html.c index fa99b2a..6ab0fba 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -2,6 +2,7 @@ // HTML attrs static char* src_keys[] = {"src", "源", NULL}; +static char* rel_keys[] = {"rel", "关系", NULL}; static char* href_keys[] = {"href", "地址", NULL}; static char* width_keys[] = {"width", "宽度", NULL}; @@ -43,6 +44,7 @@ static char* html_keys[] = {"html", "网页", NULL}; static char* head_keys[] = {"head", "头部", NULL}; static char* body_keys[] = {"body", "主体", NULL}; static char* form_keys[] = {"form", "表单", NULL}; +static char* link_keys[] = {"link", "链接", NULL}; static char* div_keys[] = {"div", "分区", NULL}; static char* img_keys[] = {"img", "图片", NULL}; @@ -208,6 +210,13 @@ static html_attr_t a_attrs[] = {font_color_keys, "blue", ABC_HTML_ATTR_FONT_COLOR, 0}, }; +static html_attr_t link_attrs[] = +{ + {rel_keys, "", ABC_HTML_ATTR_REL, ABC_HTML_FLAG_SHOW}, + {type_keys, "", ABC_HTML_ATTR_TYPE, ABC_HTML_FLAG_SHOW}, + {href_keys, "", ABC_HTML_ATTR_HREF, ABC_HTML_FLAG_SHOW}, +}; + static html_attr_t img_attrs[] = { {src_keys, "", ABC_HTML_ATTR_SRC, ABC_HTML_FLAG_SHOW}, @@ -294,6 +303,7 @@ static html_label_t html_labels[] = {a_keys, ABC_HTML_A, abc_number_of(a_attrs), a_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, {img_keys, ABC_HTML_IMG, abc_number_of(img_attrs), img_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE | ABC_HTML_FLAG_SHOW}, + {link_keys, ABC_HTML_LINK, abc_number_of(link_attrs), link_attrs, ABC_HTML_FLAG_OPEN | ABC_HTML_FLAG_SHOW}, {form_keys, ABC_HTML_FORM, abc_number_of(form_attrs), form_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, {input_keys, ABC_HTML_INPUT, abc_number_of(input_attrs), input_attrs, ABC_HTML_FLAG_OPEN | ABC_HTML_FLAG_SHOW}, @@ -1098,6 +1108,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) { html_label_t* label; abc_obj_t* obj; + abc_obj_t* type; scf_string_t* key = scf_string_cstr_len(c->utf8, c->len); @@ -1216,13 +1227,17 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) return -1; break; - case ABC_HTML_STYLE: - if (obj->text) { - scf_logi("\033[33mcss: %s\033[0m\n", obj->text->data); + case ABC_HTML_LINK: + type = abc_obj_get_attr(obj, ABC_HTML_ATTR_TYPE); + if (!type) + break; - if (abc_css_parse(obj) < 0) - return -1; - } + if (strcmp(type->value->data, "text/css")) + break; + + case ABC_HTML_STYLE: + if (abc_css_parse(obj) < 0) + return -1; break; case ABC_HTML_VIDEO: diff --git a/html/abc_io.h b/html/abc_io.h index c5ca2db..7092e64 100644 --- a/html/abc_io.h +++ b/html/abc_io.h @@ -45,7 +45,8 @@ struct abc_io_s int (*post )(abc_io_t* io, const char* path, scf_string_t* content); }; -abc_char_t* __io_pop_char (abc_io_t* io); -void __io_push_char(abc_io_t* io, abc_char_t* c); +abc_char_t* __io_pop_char (abc_io_t* io); +void __io_push_char(abc_io_t* io, abc_char_t* c); +int __io_url_path (abc_io_t** io, scf_string_t** spath, const char* main, const char* current); #endif diff --git a/html/abc_io_util.c b/html/abc_io_util.c index dd1fa0b..fc86416 100644 --- a/html/abc_io_util.c +++ b/html/abc_io_util.c @@ -95,3 +95,89 @@ void __io_push_char(abc_io_t* io, abc_char_t* c) c->next = io->tmp_list; io->tmp_list = c; } + +int __io_url_path(abc_io_t** io, scf_string_t** spath, const char* main, const char* current) +{ + scf_string_t* path = scf_string_alloc(); + if (!path) + return -ENOMEM; + + int prefix = -1; + int proto; + int ret; + + if (main) { + if ('.' == main[0] || '/' == main[0]) { + prefix = 0; + proto = ABC_PROTO_FILE; + + } else if (!strncmp(main, "file://", 7)) { + prefix = 7; + proto = ABC_PROTO_FILE; + + } else if (!strncmp(main, "http://", 7)) { + prefix = 7; + proto = ABC_PROTO_HTTP; + } else { + scf_loge("proto of '%s' NOT support\n", main); + + scf_string_free(path); + return -EINVAL; + } + + const char* p = main + prefix; + const char* p2 = NULL; + + while (*p) { + if ('/' == *p) + p2 = p; + p++; + } + + if (!p2) + p2 = p; + + ret = scf_string_cat_cstr_len(path, main, (size_t)(p2 - main)); + if (ret < 0) { + scf_string_free(path); + return ret; + } + } + + if (!strncmp(current, "file://", 7)) { + prefix = 7; + proto = ABC_PROTO_FILE; + + ret = scf_string_copy_cstr(path, current); + + } else if (!strncmp(current, "http://", 7)) { + prefix = 7; + proto = ABC_PROTO_HTTP; + + ret = scf_string_copy_cstr(path, current); + } else { + if (prefix < 0) { + prefix = 0; + proto = ABC_PROTO_FILE; + + } else if ('/' != current[0]) { + + ret = scf_string_cat_cstr_len(path, "/", 1); + if (ret < 0) { + scf_string_free(path); + return ret; + } + } + + ret = scf_string_cat_cstr(path, current); + } + + if (ret < 0) { + scf_string_free(path); + return ret; + } + + *io = abc_io_array[proto]; + *spath = path; + return prefix; +} diff --git a/html/abc_obj.h b/html/abc_obj.h index 567ad02..2701a74 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -57,6 +57,7 @@ enum abc_objs ABC_HTML_SCRIPT, ABC_HTML_STYLE, + ABC_HTML_LINK, ABC_HTML_B, ABC_HTML_I, @@ -71,6 +72,7 @@ enum abc_objs ABC_HTML_ATTR_HREF, ABC_HTML_ATTR_SRC, + ABC_HTML_ATTR_REL, ABC_HTML_ATTR_FOR, diff --git a/js/util/scf_string.c b/js/util/scf_string.c index 1da6366..249bb2b 100644 --- a/js/util/scf_string.c +++ b/js/util/scf_string.c @@ -148,6 +148,21 @@ int scf_string_copy(scf_string_t* s0, const scf_string_t* s1) return 0; } +int scf_string_copy_cstr_len(scf_string_t* s0, const char* str, size_t len) +{ + scf_string_t s1; + s1.capacity = -1; + s1.len = len; + s1.data = (char*)str; + + return scf_string_copy(s0, &s1); +} + +int scf_string_copy_cstr(scf_string_t* s0, const char* str) +{ + return scf_string_copy_cstr_len(s0, str, strlen(str)); +} + int scf_string_cat(scf_string_t* s0, const scf_string_t* s1) { if (!s0 || !s1 || !s0->data || !s1->data) diff --git a/js/util/scf_string.h b/js/util/scf_string.h index cbf8717..ca06d94 100644 --- a/js/util/scf_string.h +++ b/js/util/scf_string.h @@ -31,12 +31,13 @@ int scf_string_cmp_cstr(const scf_string_t* s0, const char* str); int scf_string_cmp_cstr_len(const scf_string_t* s0, const char* str, size_t len); int scf_string_copy(scf_string_t* s0, const scf_string_t* s1); +int scf_string_cat (scf_string_t* s0, const scf_string_t* s1); -int scf_string_cat(scf_string_t* s0, const scf_string_t* s1); +int scf_string_copy_cstr(scf_string_t* s0, const char* str); +int scf_string_cat_cstr (scf_string_t* s0, const char* str); -int scf_string_cat_cstr(scf_string_t* s0, const char* str); - -int scf_string_cat_cstr_len(scf_string_t* s0, const char* str, size_t len); +int scf_string_copy_cstr_len(scf_string_t* s0, const char* str, size_t len); +int scf_string_cat_cstr_len (scf_string_t* s0, const char* str, size_t len); int scf_string_match_kmp(const scf_string_t* T, const scf_string_t* P, scf_vector_t* offsets); int scf_string_match_kmp_cstr(const uint8_t* T, const uint8_t* P, scf_vector_t* offsets); diff --git a/ui/abc_layout.c b/ui/abc_layout.c index de0a286..d2a41c6 100644 --- a/ui/abc_layout.c +++ b/ui/abc_layout.c @@ -64,6 +64,7 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] = [ABC_HTML_SCRIPT] = abc_layout_empty, [ABC_HTML_STYLE] = abc_layout_empty, + [ABC_HTML_LINK] = abc_layout_empty, [ABC_HTML_B] = abc_layout_h1, [ABC_HTML_I] = abc_layout_h1, diff --git a/ui/abc_render.c b/ui/abc_render.c index 095548d..45f209c 100644 --- a/ui/abc_render.c +++ b/ui/abc_render.c @@ -66,6 +66,7 @@ static abc_render_t* abc_renders[ABC_HTML_NB] = [ABC_HTML_SCRIPT] = &abc_render_empty, [ABC_HTML_STYLE] = &abc_render_empty, + [ABC_HTML_LINK] = &abc_render_empty, [ABC_HTML_B] = &abc_render_h1, [ABC_HTML_I] = &abc_render_h1, -- 2.25.1