Entry

CSS の自動生成をナゲヤリに出してみる

2007年05月26日

あー……なんだか,最近忙しいもんで,なかなか自前のモノを作る機会がありません。……とか,言っていてもどうにもならないので,一応,昨日書いた,CSS 作りの道具を上げてみます。てか,骨組みしかないし……。

ソースは後掲を参照してもらうとして,コンパイルはこんな風にします(ファイル名は style.c)。コンパイルするには,LibXML2 が必要なので,適宜インストールしてからビルドすることになります。あとは,聞くまでもないですけど,当然,UN*X 環境ですよね?うちでは FreeBSD 6.1R で動かしました。

% cc style.c `xml2-config --cflags` `xml2-config --libs` -o style

どうやって使うかというと,こんな風に XHTML を食べさせます。標準出力に CSS の雛形が出力されるという寸法です。

% ./style sample.html

sample.html は,XML を使っていることが前提になっているので,XHTML に準拠した HTML を書いてください。id や class なんかをボチボチ見ながら,それっぽく読んで,その HTML に必要そうな CSS の雛形をそれっぽく出力してくれます(あくまでもそれっぽく)。

そういうわけで,ソースはこちら。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/xmlstring.h>

static void
printSelector(const xmlNodePtr cur)
{
    xmlChar *xmlString = NULL;
    
    printf("%s", cur->name);
    if ((xmlString = xmlGetProp(cur, "id")) != NULL) {
        printf("#%s", xmlString);
        xmlFree(xmlString);
        xmlString = NULL;
    }
    if ((xmlString = xmlGetProp(cur, "class")) != NULL) {
        printf(".%s", xmlString);
        xmlFree(xmlString);
        xmlString = NULL;
    }
    printf(" ");
    return;
}

static void
printDefaultProp(void)
{
    puts("    margin     : ");
    puts("    padding    : ");
    puts("    border     : ");
    puts("    background : ");
    puts("    font       : ");
    return;
}

static void
printElementStyles(const xmlNodePtr parent)
{
    xmlNodePtr cur = NULL;

    for (cur = parent; cur != NULL; cur = cur->next) {
        if (cur->type == XML_ELEMENT_NODE) {
            printSelector(cur);
            puts("{");
            printDefaultProp();
            puts("}");
        }
        printElementStyles(cur->children);
    }
    
    return;
}

static xmlNodePtr
getElementByName(const xmlNodePtr parent, const xmlChar *name)
{
    xmlNodePtr cur = NULL;
    xmlNodePtr ret = NULL;

    for (cur = parent; cur != NULL; cur = cur->next) {
        if (cur->type == XML_ELEMENT_NODE &&
            xmlStrcmp(name, cur->name) == 0) {
            ret = cur;
            break;
        }
        ret = getElementByName(cur->children, name);
    }

    return ret;
}

int
main(int argc, char *argv[])
{
    xmlDocPtr doc   = NULL;
    xmlNodePtr root  = NULL;
    xmlNodePtr cur  = NULL;

    if (argc < 2) {
        fprintf(stderr, "arg error\n");
        exit(-1);
    }
    doc = xmlParseFile(argv[1]);
    root = xmlDocGetRootElement(doc);
    if (root == NULL) {
        fprintf(stderr, "parse error\n");
        exit(-1);
    }
    cur = getElementByName(root, "body");
    printElementStyles(cur);
    
    xmlFreeDoc(doc);
    xmlCleanupParser();
    return 0;    
}

普通に DOM ツリーを走査しているだけなので,あまり難しいことはしていません。てか,Perl なんかで書いた方が楽だったかも。

ソースは昨日書いたままイヂッテないので,今日考えたあれこれは,これからボチボチ作っていこうと思います。けど,なんだか,「道具作ってる暇があるならモノを作れ」な感じになっているような,いないような……。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN