myportal in XML
Michael Urman <[email protected]>
| Newsgroups | gmane.comp.web.galeon.devel |
|---|---|
| Message-ID | <[email protected]> |
I've patched galeon (debian's 20030216 snapshot) to use XML for the
myportal handler. What i like about it is that the myportal xml source
is much cleaner, although it does depend on javascript for links and
forms. What i dislike is that it is noticeably slower on my personal
batch of way too many bookmarks (around 400-500).
Attached are the patch to mozilla/MyportalProtocolHandler.cpp,
the totally redone myportal.css, and the new myportal.js.
If you're curious how this actually looks and don't want to rebuild for
it, see http://zeta.dtdns.net/~mu/galportal/ in which you'll find:
galportal.xml
a small test file used to figure out the current layout
myportal.xml
an edited output of the new handler, reflecting the local .css
and .js links (and removing personal bookmarks)
stripped.xml
like myportal.xml, but stripped of indentation for a "better"
file-size comparison; it's still about 3/2 the size of the html,
which is considerably better than the 5/2 it is beforehand.
myportal.css, myportal.js [see note]
the final versions of the above included files
myportal.html
a matching edited output of the old handler
galportal.css
the corresponding css for the html file
galeonportal.png
a screenshot of a the html version before i started the xml
MyportalProtocolHandler.diff
the diff i've included
I'd appreciate any feedback, or suggestions, particularly if there are
better ways to handle the links, forms, or to regain the lost speed.
[ Note: the javascript is strongly based on examples at
http://developer.apple.com/internet/css/xmltransformations.html. I
personally feel the given snippets are small enough to be devoid of
copyright, but i'd rather let someone knowledgeable decide that.
Everything else is either my original code and thus available under
the GPL, or directly derived or modified GPL code. ]
-m
--
Michael Urman [- [email protected] -]
MyportalProtocolHandler.diff
(text/plain, 10.4 KB)
--- MyportalProtocolHandler.cpp.orig 2003-02-20 14:31:46.000000000 -0600
+++ MyportalProtocolHandler.cpp 2003-02-20 14:31:57.000000000 -0600
@@ -58,8 +58,8 @@
const char *prefix, gint depth);
static void render_folder (OutStream *stream, GbFolder *b,
const char *prefix, gint depth);
-static void render_url (OutStream *stream, GbSite *b);
-static void render_search_form (OutStream *stream, GbSmartSite *b);
+static void render_url (OutStream *stream, GbSite *b, gint depth);
+static void render_search_form (OutStream *stream, GbSmartSite *b, gint depth);
/* hackish shorthand to render HTML into the browser */
#if USE_INTERMEDIATE_FILE
@@ -192,11 +192,13 @@
/* get the stylesheet filename */
gchar *stylesheet_filename =
gul_general_user_file ("myportal.css", FALSE);
+ gchar *javascript_filename =
+ gul_general_user_file ("myportal.js", FALSE);
/* open the rendering stream */
#if USE_INTERMEDIATE_FILE
gchar *filename = g_strconcat (g_get_home_dir (),
- "/.galeon/myportal.html",
+ "/.galeon/myportal.xml",
NULL);
gchar *myportalURI = g_strconcat ("file://",filename, NULL);
FILE *stream = fopen (filename, "w");
@@ -204,6 +206,7 @@
{
g_warning ("unable to create `%s'", filename);
g_free (stylesheet_filename);
+ g_free (javascript_filename);
g_free (filename);
return NS_ERROR_FAILURE;
}
@@ -222,28 +225,19 @@
/* render the complete portal */
gchar full_path[PATH_MAX];
gchar* myportal_utfstr = _("My Portal");
- RENDER ("<html><head>\n");
- RENDER ("<link rel=\"stylesheet\" href=\"file:");
+ RENDER ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ RENDER ("<?xml-stylesheet href=\"file://");
RENDER (realpath (stylesheet_filename, full_path));
- RENDER ("\" type=\"text/css\">\n");
- RENDER ("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=utf-8\">\n");
- RENDER ("<title>");
+ RENDER ("\" type=\"text/css\"?>\n");
+ RENDER ("<myportal root=\"\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\n");
+ RENDER (" <title>");
RENDER (myportal_utfstr);
- RENDER ("</title>");
- RENDER("</head>\n");
- RENDER ("<body>\n");
- /* RENDER ("<a href=\"" GALEON_HOMEPAGE_URL "\">"
- "<img class=\"logo\" src=\"file:" SHARE_DIR
- "/logo.png\" alt=\"\"></a>"); */
- RENDER ("<div class=\"top_bar\"><table cellpadding=\"2\" cellspacing=\"0\" width=\"100%\" border=0><tr><td><img src=\"file:" SHARE_DIR "/galeon.png\">myportal:</td>\n")
- RENDER ("<td valign=\"top\" align=\"right\" class=\"slogan\"></td></tr></table></div>\n")
- RENDER ("<div class=\"top2\"><a href=\"http://galeon.sourceforge.net\"><img class=\"logo\" src=\"file:" SHARE_DIR "/logo.png\" alt=\"\"></a></div>\n")
- RENDER ("<p><br></p> \n")
- RENDER("<!-- BOOKMARKS -->\n\n");
+ RENDER ("</title>\n\n");
render_from_path (stream, PromiseFlatCString(path).get());
- RENDER("\n\n<!-- END -->");
- RENDER ("<div class=\"bottom_bar\"><center><b>Galeon</b> : <i>the web, the only web</i></center></div>");
- RENDER ("</body></html>\n");
+ RENDER ("\n <xhtml:script type=\"text/javascript\" src=\"file://");
+ RENDER (realpath (javascript_filename, full_path));
+ RENDER ("\"/>\n");
+ RENDER ("</myportal>\n");
// g_free(myportal_utfstr);
/* finish the rendering */
@@ -265,7 +259,7 @@
#if MOZILLA_SNAPSHOT > 4
rv = NS_NewInputStreamChannel(getter_AddRefs(mChannel), mURI,
- iStream, NS_LITERAL_CSTRING("text/html"),
+ iStream, NS_LITERAL_CSTRING("text/xml"),
NS_LITERAL_CSTRING("utf-8"));
#else
PRUint32 size;
@@ -392,19 +386,26 @@
if (b == NULL)
return;
+
/* otherwise do the appropriate thing */
if (GB_IS_FOLDER(b)) {
- RENDER ("<blockquote>");
+ gchar *indent, *indent2;
+ indent = g_strdup_printf("%*s", (depth+1)*4, " ");
+ indent2 = g_strdup_printf("%*s", (depth+2)*4, " ");
+ RENDER (indent);
+ RENDER ("<folder>\n");
strippedname = gul_string_strip_uline_accel (b->name);
- RENDER ("<a class=\"heading\" ");
id = g_strdup_printf ("%lu", (gulong) b);
if (!GB_IS_ALIAS_PLACEHOLDER(b))
{
- RENDER ("name=\"");
+ RENDER (indent2);
+ RENDER ("<id>");
RENDER (id);
- RENDER ("\" ");
+ RENDER ("</id>\n");
}
- RENDER ("href=\"");
+
+ RENDER (indent2);
+ RENDER ("<link>")
if (depth == 0)
{
newprefix = g_strdup (prefix);
@@ -416,36 +417,43 @@
g_free(escapedname);
}
RENDER (newprefix);
- RENDER ("\">");
- RENDER ("<strong>");
+ RENDER ("</link>\n");
+
+ RENDER (indent2);
+ RENDER ("<label>");
RENDER (strippedname);
- RENDER ("</strong>");
g_free (strippedname);
- RENDER ("</a>");
+ RENDER ("</label>\n");
+
if (GB_IS_ALIAS_PLACEHOLDER(b))
{
/* we point to the root portal since 1) the real bm might not
* be in this same level we are viewing, and 2) relative
* anchors don't seem to work with myportal:// ;) */
- RENDER (" -> <a href=\"myportal://#");
- RENDER (id);
- RENDER ("\">#");
+ RENDER (indent2);
+ RENDER ("<ref>");
RENDER (id);
- RENDER ("</a>");
+ RENDER ("</ref>\n");
}
g_free (id);
- RENDER ("<br>");
+
if (!GB_IS_ALIAS_PLACEHOLDER(b) || depth==0)
render_folder (stream, GB_FOLDER(b),
newprefix, depth+1);
g_free (newprefix);
- RENDER ("</div></blockquote>\n");
+ RENDER (indent);
+ RENDER ("</folder>\n");
+ g_free (indent);
+ g_free (indent2);
} else if (GB_IS_SMART_SITE(b)) {
- render_search_form (stream, GB_SMART_SITE(b));
+ render_search_form (stream, GB_SMART_SITE(b), depth);
} else if (GB_IS_SITE(b)) {
- render_url (stream, GB_SITE(b));
+ render_url (stream, GB_SITE(b), depth);
} else if (GB_IS_SEPARATOR(b)) {
- RENDER ("<br>\n");
+ gchar *indent;
+ indent = g_strdup_printf("%*s", (depth+1)*4, " ");
+ RENDER (indent);
+ RENDER ("<br/>\n");
}
}
@@ -468,11 +476,17 @@
* render_url: render a bookmark url
*/
static void
-render_url (OutStream *stream, GbSite *b)
+render_url (OutStream *stream, GbSite *b, gint depth)
{
- gchar *url;
-
- RENDER ("<a href=\"");
+ gchar *url, *url2;
+ gchar *indent, *indent2;
+ indent = g_strdup_printf("%*s", (depth+1)*4, " ");
+ indent2 = g_strdup_printf("%*s", (depth+2)*4, " ");
+
+ RENDER (indent);
+ RENDER ("<bookmark>\n");
+ RENDER (indent2);
+ RENDER ("<link>");
/* If url has no preceding "http://" or "ftp://" presume "http://" */
/* FIXME cant we just test for : ? */
@@ -488,11 +502,18 @@
}
/* escape quotes, so we don't accidentally break out of the URI */
- url = gul_string_strdup_replace (b->url, "\"", """);
+ url2 = gul_string_strdup_replace (b->url, "&", "&");
+
+ url = gul_string_strdup_replace(url2, "\"", """);
+ if (url2) g_free (url2); url2 = url;
+ url = gul_string_strdup_replace(url2, "<", "<");
+ if (url2) g_free (url2); url2 = url;
+ url = gul_string_strdup_replace(url2, ">", ">");
+ if (url2) g_free (url2);
RENDER (url);
if (url) g_free (url);
+ RENDER ("</link>\n");
- RENDER ("\">");
if (gb_bookmark_get_image(GB_BOOKMARK(b)) == NULL)
{
gchar *name, *name2;
@@ -514,21 +535,31 @@
}
/* escape some more characters */
- name2 = gul_string_strdup_replace (name, "<", "<");
+ name2 = gul_string_strdup_replace (name, "&", "&");
if (name) g_free (name);
name = gul_string_strdup_replace (name2, ">", ">");
if (name2) g_free (name2);
+ name2 = name;
+ name = gul_string_strdup_replace (name2, "<", "<");
+ if (name2) g_free (name2);
+ RENDER (indent2);
+ RENDER ("<label>");
RENDER (name);
if (name) g_free (name);
+ RENDER ("</label>\n");
}
else
{
- RENDER ("<img src=\"file://");
+ RENDER (indent2);
+ RENDER ("<xhtml:img src=\"file://");
RENDER (GB_BOOKMARK(b)->pixmap_file);
- RENDER ("\">");
+ RENDER ("\"/>\n");
}
- RENDER ("</a>\n");
+ RENDER (indent);
+ RENDER ("</bookmark>\n");
+ g_free(indent);
+ g_free(indent2);
}
/**
@@ -536,12 +567,13 @@
* FIXME: tidy
*/
static void
-render_search_form (OutStream *stream, GbSmartSite *b)
+render_search_form (OutStream *stream, GbSmartSite *b, gint depth)
{
gchar *path; /* static part of URL */
gchar **query; /* query string, broken into parameters */
int num_inputs = 0, pathlen;
gchar *tmp;
+ gchar *indent, *indent2;
int i;
/* parse URL to separate static parts from parts needing user input */
@@ -552,15 +584,21 @@
return;
}
+ indent = g_strdup_printf("%*s", (depth+1)*4, " ");
+ indent2 = g_strdup_printf("%*s", (depth+2)*4, " ");
+
pathlen = tmp - b->smarturl;
path = g_strndup (b->smarturl, pathlen);
- RENDER ("<form action=\"");
+ RENDER (indent);
+ RENDER ("<xhtml:form>\n");
+ RENDER (indent2);
+ RENDER ("<link>");
if (!strstr (b->smarturl, "://"))
{
RENDER ("http://");
}
RENDER (path);
- RENDER ("\" method=get>");
+ RENDER ("</link>\n");
g_free (path);
/* count occurrences of %s in b->smarturl */
@@ -577,8 +615,8 @@
if (strcmp (query[i], "%s") == 0)
{
/* anonymous field */
- RENDER ("<input type=text name=\"\" size=");
- RENDER (num_inputs>1?"10>":"30>");
+ RENDER (indent2);
+ RENDER ("<xhtml:input name=\"\">\n");
/* skip the remaining logic */
continue;
}
@@ -589,24 +627,24 @@
gchar *val=g_strdup_printf ("%.*s%s", smtpos-param[1],
param[1],param[1]+(smtpos-param[1]+2));
/* add a form input */
- RENDER (num_inputs>1?param[0]:"");
- RENDER ("<input type=text name=\"");
+ RENDER (indent2);
+ RENDER ("<xhtml:input name=\"");
RENDER (param[0]);
RENDER ("\" value=\"");
RENDER (val);
- RENDER ("\" size=");
- RENDER (num_inputs>1?"10>":"30>");
+ RENDER ("\"/>\n");
g_free (val);
}
else
{
/* add the static parts of URL as hidden form inputs */
- RENDER ("<input type=hidden name=\"");
+ RENDER (indent2);
+ RENDER ("<xhtml:input hidden=\"");
RENDER (param[0]);
RENDER ("\" value=\"");
if (param[1])
RENDER (param[1]);
- RENDER ("\">");
+ RENDER ("\"/>\n");
}
g_strfreev (param);
}
@@ -616,16 +654,23 @@
{
gchar *strippedname =
gul_string_strip_uline_accel (GB_BOOKMARK(b)->name);
- RENDER ("<input type=submit value=\"");
+ RENDER (indent2);
+ RENDER ("<xhtml:input label=\"");
RENDER (strippedname);
g_free (strippedname);
+ RENDER ("\"/>\n");
}
else
{
- RENDER ("<input type=image src=\"file://");
- RENDER (GB_BOOKMARK(b)->pixmap_file);
+ RENDER (indent2);
+ RENDER ("<xhtml:input image=\"file://");
+ RENDER (GB_BOOKMARK(b)->pixmap_file);
+ RENDER ("\"/>\n");
}
- RENDER ("\"></form>\n");
+ RENDER (indent);
+ RENDER ("</xhtml:form>\n");
+ g_free(indent);
+ g_free(indent2);
}
#undef RENDER
myportal.css
(text/css, 3.4 KB)
@namespace xlink url(http://www.w3.org/1999/xlink);
myportal
{
display: block;
margin: 0 4px;
background-color: #444;
border-top: 30px solid #97b1d8;
}
myportal:before
{
display: block;
font-size: x-large;
font-style: italic;
background-color: white;
border: 1px solid black;
border-top-width: 2px;
padding: 3px;
margin-bottom: 0.5em;
content: url(file:/usr/share/galeon-snapshot/galeon.png)
" myportal://"attr(root);
}
myportal:after
{
display: block;
font-weight: bold;
font-style: italic;
content: "Galeon: the web, the only web";
background-color: #97b1d8;
border-color: 1px solid black;
text-align: center;
margin: 0px 200px;
margin-top: 10px;
}
myportal > title
{
display: none;
}
/*
myportal > folder:before
{
content: url(file:/usr/share/galeon-snapshot/logo.png);
position: relative;
left: -20px;
}
*/
folder
{
display: block;
margin-top: 1em;
margin-left: 8px;
padding-left: 4px;
margin-right: 0px;
padding-bottom: 4px;
border-left: solid 5px black;
border-top: solid 5px black;
border-bottom: solid 4px #888;
-moz-border-left-colors: #444 #666 #888 #aaa #ccc;
-moz-border-top-colors: #444 #666 #888 #aaa #ccc;
-moz-border-bottom-colors: #666 #888 #aaa #ccc;
-moz-border-radius-bottomleft: 1px;
background-color: #f0f0f0;
}
folder>folder { background-color: #e8e8e8; }
folder>folder>folder { background-color: #e0e0e0; }
folder>folder>folder>folder { background-color: #d8d8d8; }
folder>folder>folder>folder>folder { background-color: #d0d0d0; }
folder>folder>folder>folder>folder>folder { background-color: #c8c8c8; }
folder > id
{
display: none;
}
folder > label
{
display: inline;
border: 2px solid black;
padding-bottom: 2px;
padding-top 0px;
padding-right: 1em;
padding-left: 1em;
margin-left: -16px;
margin-top: 3em;
margin-bottom: -1px;
color: black;
background-color: #97b1d8;
font-size: 120%;
font-weight: bold;
-moz-border-radius-bottomleft: 6px;
-moz-border-radius-topleft: 12px;
-moz-border-radius-topright: 6px;
-moz-border-radius-bottomright: 12px;
position: relative;
top: -5px;
}
folder > label:hover
{
color: white;
background-color: black;
}
folder > link
{
display: none;
}
bookmark
{
cursor: pointer;
display: inline;
border-bottom: 1px solid gray;
content: attr(xlink:label);
}
bookmark + bookmark
{
margin-left: 1em;
}
bookmark > label:hover
{
border-bottom: 1px solid black;
color: blue;
}
bookmark > link
{
display: none;
}
form /* really should be xhtml|form, i think... */
{
display: block;
}
form > link
{
display: none;
}
input[type="text"]
{
border-style: groove;
background-color: transparent;
}
input[type="text"]:focus
{
border-style: inset;
background-color: auto;
}
input[type="submit"]
{
border: none;
padding: 0px;
background-color: transparent;
border-bottom: 1px solid gray;
}
input[type="submit"]:hover
{
color: blue;
cursor: pointer;
border-bottom: solid 1px black;
}
input[type="hidden"]
{
display: none;
}
/*
smartbookmark
{
display: block;
margin-top: 5px;
margin-bottom: 5px;
}
smartbookmark + smartbookmark
{
margin-top: 10px;
}
smartbookmark > link
{
display: none;
}
smartbookmark > submit:after
{
display: inline;
}
smartbookmark > input
{
padding: 1px 2px;
border: 3px inset gray;
width: 30px;
}
*/
myportal.js
(application/x-javascript, 2.5 KB) - not displayed