css: use css code in a file with HTML <link> label master
authoryu.dongliang <18588496441@163.com>
Tue, 31 Mar 2026 15:58:07 +0000 (23:58 +0800)
committeryu.dongliang <18588496441@163.com>
Tue, 31 Mar 2026 15:58:07 +0000 (23:58 +0800)
examples/css.html
examples/style.css [new file with mode: 0644]
html/abc_css.c
html/abc_html.c
html/abc_io.h
html/abc_io_util.c
html/abc_obj.h
js/util/scf_string.c
js/util/scf_string.h
ui/abc_layout.c
ui/abc_render.c

index 5fe90691a7216fe871b33d45a3d9d0f8315f17ce..9b738ff25c400179d32b6fbfbeea65504cdcfe7c 100644 (file)
@@ -1,18 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
 <!DOCTYPE html>
 <html>
 <head>
-<style>
-#a /*css comment*/
-{
-       color:blue;
-       text-align:center;
-}
-
-p.red
-{
-       color:red;
-}
-</style>
+<link rel="stylesheet" type="text/css" href="style.css">
 </head>
 
 <body>
 </head>
 
 <body>
diff --git a/examples/style.css b/examples/style.css
new file mode 100644 (file)
index 0000000..9306941
--- /dev/null
@@ -0,0 +1,10 @@
+#a /*css comment*/
+{
+       color:blue;
+       text-align:center;
+}
+
+p.red
+{
+       color:red;
+}
index 33d386d301f31466e4af78afc3a13269134d9830..c7394d2c71f32c05bcb0eb7ffa8e3088e5e90d7f 100644 (file)
@@ -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)
 {
 
 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;
 
        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;
 
        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;
 
        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*  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;
 
        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;
 
                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 (!attr)
                                continue;
 
-                       if (strcmp(attr->value->data, label->text->data + label->css_dot + 1))
+                       if (strcmp(attr->value->data, "text/css"))
                                continue;
 
                                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;
                                        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);
+                       }
                }
        }
 
                }
        }
 
index fa99b2a0ea1e841ba58f321ecbae62eb2f48ffc5..6ab0fbabfd78beb3f32acff0811e43f011d5d98e 100644 (file)
@@ -2,6 +2,7 @@
 
 // HTML attrs
 static char* src_keys[]        = {"src",        "源",       NULL};
 
 // 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};
 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* 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};
 
 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},
 };
 
        {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},
 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},
 
        {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},
 
        {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;
 {
        html_label_t* label;
        abc_obj_t*    obj;
+       abc_obj_t*    type;
 
        scf_string_t* key = scf_string_cstr_len(c->utf8, c->len);
 
 
        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;
 
                                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:
                        break;
 
                case ABC_HTML_VIDEO:
index c5ca2dbca4d9f53ba30ee7958634e6a40f09dd78..7092e64ffcce5bdbf96d8ac02c2d3cf6b323a0d0 100644 (file)
@@ -45,7 +45,8 @@ struct abc_io_s
        int           (*post )(abc_io_t* io, const char* path, scf_string_t* content);
 };
 
        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
 
 #endif
index dd1fa0b0791918e0e3f42f132d7458c33bbcfff5..fc86416d0f2474525136308beecace648f693b4f 100644 (file)
@@ -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;
 }
        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;
+}
index 567ad02dd6cbdc57d11e19e69f8ceff840cf77de..2701a74b03a8351710ef8fae9678d224ee6427d6 100644 (file)
@@ -57,6 +57,7 @@ enum abc_objs
 
        ABC_HTML_SCRIPT,
        ABC_HTML_STYLE,
 
        ABC_HTML_SCRIPT,
        ABC_HTML_STYLE,
+       ABC_HTML_LINK,
 
        ABC_HTML_B,
        ABC_HTML_I,
 
        ABC_HTML_B,
        ABC_HTML_I,
@@ -71,6 +72,7 @@ enum abc_objs
 
        ABC_HTML_ATTR_HREF,
        ABC_HTML_ATTR_SRC,
 
        ABC_HTML_ATTR_HREF,
        ABC_HTML_ATTR_SRC,
+       ABC_HTML_ATTR_REL,
 
        ABC_HTML_ATTR_FOR,
 
 
        ABC_HTML_ATTR_FOR,
 
index 1da63667ab007305b07603df3b27d68921be1c1e..249bb2bc9efc0e7de7bbf005a51d5152d3c48b62 100644 (file)
@@ -148,6 +148,21 @@ int        scf_string_copy(scf_string_t* s0, const scf_string_t* s1)
        return 0;
 }
 
        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)
 int    scf_string_cat(scf_string_t* s0, const scf_string_t* s1)
 {
        if (!s0 || !s1 || !s0->data || !s1->data)
index cbf87172f861c040a4769c3d86f048ab64b4c42d..ca06d945fc986ca1eab06bf35691c298aa413fc0 100644 (file)
@@ -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_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);
 
 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);
index de0a2869cbc2e498275b76d1641833356ebf431e..d2a41c6c6eed405d0843e5054d93298093d3f300 100644 (file)
@@ -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_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,
 
        [ABC_HTML_B]        = abc_layout_h1,
        [ABC_HTML_I]        = abc_layout_h1,
index 095548db85ff0d26e3b184c7fba15247ecf371a2..45f209cc8719854ecec5966e5443ec3d8965ce74 100644 (file)
@@ -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_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,
 
        [ABC_HTML_B]        = &abc_render_h1,
        [ABC_HTML_I]        = &abc_render_h1,