Initial revision

This commit is contained in:
Robert Gaggl 2001-06-18 08:57:33 +00:00
parent 1ba4e8011b
commit bbfcb3d4f4
104 changed files with 3100 additions and 0 deletions

View file

@ -0,0 +1,9 @@
<TABLE BGCOLOR="#FF9900" BORDER="0" CELLSPACING="0" CELLPADDING="2">
<TR>
<TD NOWRAP><% this.link to="main" text="&bull;&nbsp;home" %></TD>
<TD NOWRAP><% this.link to="edit" text="&bull;&nbsp;preferences" %></TD>
<TD NOWRAP><% this.link to="create" text="&bull;&nbsp;create story" %></TD>
<TD NOWRAP><% this.link to="images" text="&bull;&nbsp;image editor" %></TD>
<TD NOWRAP><% this.link to="skins" text="&bull;&nbsp;skin editor" %></TD>
</TR>
</TABLE>

20
code/Site/calendar.skin Normal file
View file

@ -0,0 +1,20 @@
<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="2" BGCOLOR="#CCCCCC" CLASS="calendar">
<TR>
<TD COLSPAN="7" ALIGN="CENTER" CLASS="calendarHeader" NOWRAP><% param.month %>&nbsp;<% param.year %></TD>
</TR>
<TR>
<TD CLASS="calendarDay" NOWRAP>Mo</TD>
<TD CLASS="calendarDay" NOWRAP>Tu</TD>
<TD CLASS="calendarDay" NOWRAP>We</TD>
<TD CLASS="calendarDay" NOWRAP>Th</TD>
<TD CLASS="calendarDay" NOWRAP>Fr</TD>
<TD CLASS="calendarDay" NOWRAP>Sa</TD>
<TD CLASS="calendarDay" NOWRAP>Su</TD>
</TR>
<% param.calendar %>
<TR>
<TD COLSPAN="3" ALIGN="RIGHT" CLASS="calendarFooter" NOWRAP><% param.back %></TD>
<TD CLASS="calendarFooter" NOWRAP>&nbsp;</TD>
<TD COLSPAN="3" CLASS="calendarFooter" NOWRAP><% param.forward %></TD>
</TR>
</TABLE>

View file

@ -0,0 +1 @@
<TD CLASS="calendarDay" NOWRAP><% param.day %></TD>

View file

@ -0,0 +1 @@
<TD CLASS="calendarSelectedDay" NOWRAP><% param.day %></TD>

View file

@ -0,0 +1,3 @@
<TR>
<% param.week %>
</TR>

14
code/Site/create.hac Normal file
View file

@ -0,0 +1,14 @@
// check if user is allowed to edit this story
this.checkPermissions();
if (req.data.submit == "cancel")
res.redirect(this.href());
res.skin = "main";
res.title = "Antville - " + this.title;
res.head = this.renderSkinAsString("style");
newStory = this.evalNewStory();
res.body = this.renderSkinAsString("header");
res.body += newStory.renderSkinAsString("edit");

14
code/Site/edit.hac Normal file
View file

@ -0,0 +1,14 @@
// check if user is logged in and is the owner of this weblog
this.checkPermissions();
if (req.data.submit == "cancel")
res.redirect(this.href());
else if (req.data.submit == "save")
this.updateWeblog();
res.skin = "main";
res.title = "Antville - " + this.title;
res.head = this.renderSkinAsString("style");
res.body = this.renderSkinAsString("header");
res.body += this.renderSkinAsString("edit");

20
code/Site/edit.skin Normal file
View file

@ -0,0 +1,20 @@
<P><FORM METHOD="POST">
Title:&nbsp;<% this.title as="editor" width="40" %><BR>
Tagline:&nbsp;<% this.tagline as="editor" width="40" %><BR>
Birthdate:&nbsp;<% this.birthdate as="editor" %><BR>
Background color:&nbsp;<% this.bgcolor as="editor" width="10" %><BR>
Textfont:&nbsp;<% this.textfont as="editor" width="40" %><BR>
Textsize:&nbsp;<% this.textsize as="editor" width="10" %><BR>
Textcolor:&nbsp;<% this.textcolor as="editor" width="10" %><BR>
Linkcolor:&nbsp;<% this.linkcolor as="editor" width="10" %><BR>
ALinkcolor:&nbsp;<% this.alinkcolor as="editor" width="10" %><BR>
VLinkcolor:&nbsp;<% this.vlinkcolor as="editor" width="10" %><BR>
Titlefont:&nbsp;<% this.titlefont as="editor" width="40" %><BR>
Titlesize:&nbsp;<% this.titlesize as="editor" width="10" %><BR>
Titlecolor:&nbsp;<% this.titlecolor as="editor" width="10" %><BR>
show days:&nbsp;<% this.showdays as="editor" width="5"%><BR>
online:&nbsp;<% this.online as="editor" %><BR>
hasDiscussions:&nbsp;<% this.hasdiscussions as="editor" %><BR>
enable archive:&nbsp;<% this.showarchive as="editor" %><BR>
<% this.input type="button" value="save" %>&nbsp;<% this.input type="button" value="cancel" %>
</FORM></P>

6
code/Site/header.skin Normal file
View file

@ -0,0 +1,6 @@
<P><FONT SIZE="+3"><B><% this.title %></B></FONT>&nbsp;<FONT SIZE="-1" COLOR="#FF0000"><% response.message %></FONT>
<% this.age prefix="<BR>online since:&nbsp;" show="days" suffix=" Days" %>
<% this.lastupdate prefix="<BR>last updated:&nbsp;" format="EEEE, dd.MM.yyyy, HH:mm" suffix="&nbsp;Uhr" %></P>
<% this.loginstatus %>
<% this.navigation %>

411
code/Site/macros.js Normal file
View file

@ -0,0 +1,411 @@
/**
* macro rendering title of weblog
*/
function title_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("title",param));
else {
if (param && param.linkto) {
this.openLink(param);
res.write(this.title);
this.closeLink(param);
} else
res.write(this.title);
}
renderSuffix(param);
}
/**
* macro rendering alias of weblog
*/
function alias_macro(param) {
renderPrefix(param);
res.write(this.alias);
renderSuffix(param);
}
/**
* macro rendering tagline of weblog
*/
function tagline_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("tagline",param));
else
res.write(this.tagline);
renderSuffix(param);
}
/**
* macro rendering birthdate of weblog
*/
function birthdate_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderDateDropdown(this.createInputParam("birthdate",param));
else
res.write(this.birthdate.format());
renderSuffix(param);
}
/**
* macro rendering bgcolor of weblog
*/
function bgcolor_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("bgcolor",param));
else
res.write(this.bgcolor);
renderSuffix(param);
}
/**
* macro rendering textfont of weblog
*/
function textfont_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("textfont",param));
else
res.write(this.textfont);
renderSuffix(param);
}
/**
* macro rendering textsize of weblog
*/
function textsize_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("textsize",param));
else
res.write(this.textsize);
renderSuffix(param);
}
/**
* macro rendering textcolor of weblog
*/
function textcolor_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("textcolor",param));
else
res.write(this.textcolor);
renderSuffix(param);
}
/**
* macro rendering linkcolor of weblog
*/
function linkcolor_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("linkcolor",param));
else
res.write(this.linkcolor);
renderSuffix(param);
}
/**
* macro rendering alinkcolor of weblog
*/
function alinkcolor_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("alinkcolor",param));
else
res.write(this.alinkcolor);
renderSuffix(param);
}
/**
* macro rendering vlinkcolor of weblog
*/
function vlinkcolor_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("vlinkcolor",param));
else
res.write(this.vlinkcolor);
renderSuffix(param);
}
/**
* macro rendering titlefont of weblog
*/
function titlefont_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("titlefont",param));
else
res.write(this.titlefont);
renderSuffix(param);
}
/**
* macro rendering titlesize of weblog
*/
function titlesize_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("titlesize",param));
else
res.write(this.titlesize);
renderSuffix(param);
}
/**
* macro rendering titlecolor of weblog
*/
function titlecolor_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("titlecolor",param));
else
res.write(this.titlecolor);
renderSuffix(param);
}
/**
* macro rendering lastupdate of weblog
*/
function lastupdate_macro(param) {
if (this.lastUpdate) {
renderPrefix(param);
if (param.format)
res.write(this.lastupdate.format(param.format));
else
res.write(this.lastupdate.format("yyyy.MM.dd HH:mm"));
renderSuffix(param);
}
}
/**
* macro rendering online-status of weblog
*/
function online_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputCheckbox(this.createInputParam("online",param));
else
res.write(this.online ? "yes" : "no");
renderSuffix(param);
}
/**
* macro rendering discussion-flag of weblog
*/
function hasdiscussions_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputCheckbox(this.createInputParam("discussions",param));
else
res.write(parseInt(this.discussions,10) ? "yes" : "no");
renderSuffix(param);
}
/**
* macro rendering nr. of days to show on weblog-fontpage
*/
function showdays_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputText(this.createInputParam("days",param));
else
res.write(this.days);
renderSuffix(param);
}
/**
* macro rendering archive-flag of weblog
*/
function showarchive_macro(param) {
renderPrefix(param);
if (param.as == "editor")
this.renderInputCheckbox(this.createInputParam("archive",param));
else
res.write(parseInt(this.archive,10) ? "yes" : "no");
renderSuffix(param);
}
/**
* macro rendering loginStatus of user
* valid params: - loginSkin
* - logoutSkin
*/
function loginstatus_macro(param) {
if (user.uid)
this.members.renderSkin("statusloggedin");
else if (getActionName() != "login")
this.members.renderSkin("statusloggedout");
}
/**
* macro rendering two different navigation-skins
* depending on user-status & rights
*/
function navigation_macro(param) {
renderPrefix(param);
if (this.owner == user) {
// hey, this is the admin, so give him the admin-navigation
this.renderSkin("adminnavigation");
} else {
// normal user, so we take the normal navigation
this.renderSkin("usernavigation");
}
renderSuffix(param);
}
/**
* macro rendering storylist
* but check if story is online ...
* if not, we only display it when owner is viewing
*/
function storylist_macro() {
if (this.size() > 0) {
var idx = 0;
var days = parseInt(this.days) ? parseInt(this.days) : 2;
if (req.data.show) {
var currGroup = this.get(req.data.show);
if (currGroup) {
idx = this.contains(currGroup);
days = 1;
}
}
for (var i=idx;i<idx + days;i++) {
var currDay = this.get(i);
if (currDay) {
for (var j=0;j<currDay.size();j++) {
var currStory = currDay.get(j);
currStory.setParent(currDay);
if (currStory.isOnline() || currStory.author == user)
currStory.renderSkin("preview");
}
}
}
} else
this.renderSkin("welcome");
}
/**
* macro renders a calendar
*/
function calendar_macro() {
// define variables needed in this function
var now = new Date();
var calParam = new HopObject();
calParam.calendar = "";
var dayParam = new HopObject();
var weekParam = new HopObject();
// create new calendar-object
var cal = new java.util.GregorianCalendar();
cal.set(java.util.Calendar.DATE,1);
if (req.data.show) {
var reqYear = parseInt(req.data.show.substring(0,4),10);
var reqMonth = parseInt(req.data.show.substring(4,6),10) - 1;
if (reqYear && reqMonth) {
cal.set(java.util.Calendar.YEAR,reqYear);
cal.set(java.util.Calendar.MONTH,reqMonth);
}
}
var lastDay = cal.getActualMaximum(java.util.Calendar.DATE);
var startAt = cal.get(java.util.Calendar.DAY_OF_WEEK) - cal.getFirstDayOfWeek();
var currMonth = cal.get(java.util.Calendar.MONTH);
calParam.month = cal.getTime().format("MMMM");
calParam.year = cal.getTime().format("yyyy");
calParam.back = this.renderLinkToPrev(cal.clone());
for (var i=0;i<Math.ceil((startAt + lastDay) / 7);i++) {
weekParam.week = "";
for (var j=0;j<7;j++) {
if(i==0 && j<startAt) {
dayParam.day = "&nbsp;";
} else {
if (cal.get(java.util.Calendar.MONTH) != currMonth) {
dayParam.day = "&nbsp;";
} else {
var currGroupname = cal.getTime().format("yyyyMMdd");
dayParam.day = this.renderCalendarDay(currGroupname,cal.get(java.util.Calendar.DATE));
}
// check which skin we should render
if (req.data.show && cal.getTime().format("yyyyMMdd") == req.data.show)
dayParam.useskin = "calendarselday";
else
dayParam.useskin = "calendarday";
// render the link to next month (if it makes sense)
if (cal.get(java.util.Calendar.DATE) == lastDay)
calParam.forward = this.renderLinkToNext(cal.clone());
cal.add(java.util.Calendar.DATE,1);
}
weekParam.week += this.renderSkinAsString((dayParam.useskin ? dayParam.useskin : "calendarday"),dayParam);
}
calParam.calendar += this.renderSkinAsString("calendarweek",weekParam);
}
this.renderSkin("calendar",calParam);
}
/**
* macro renders age of weblog
*/
function age_macro(param) {
if (this.birthdate) {
renderPrefix(param);
if (param && param.format)
res.write(this.birthdate.format(param.format));
else if (param && param.show == "days")
res.write(Math.floor((new Date() - this.birthdate) / 86400000));
else
res.write(this.birthdate);
renderSuffix(param);
}
}
/**
* macro renders an image out of image-pool
* either as plain image or as image-link
* overrideable parameters: width,height,alttext,border
* additional parameters: align, valign
*/
function image_macro(param) {
if (param && param.name) {
renderPrefix(param);
this.renderImage(param);
renderSuffix(param);
}
}

6
code/Site/main.hac Normal file
View file

@ -0,0 +1,6 @@
res.skin = "main";
res.title = "Antville - " + this.title;
res.head = this.renderSkinAsString("style");
res.body = this.renderSkinAsString("main");

5
code/Site/main.skin Normal file
View file

@ -0,0 +1,5 @@
<% this.skin name="header" %>
<% this.calendar %>
<% this.storylist %>

View file

@ -0,0 +1,158 @@
/**
* function checks if story fits to the minimal needs (must have at least a text ;-)
*/
function evalNewStory() {
var newStory = new story();
if (req.data.text) {
newStory.weblog = this;
newStory.title = req.data.title;
newStory.text = req.data.text;
newStory.online = parseInt(req.data.online) ? parseInt(req.data.online) : 0;
newStory.author = user;
newStory.createtime = new Date();
newStory.day = newStory.createtime.format("yyyyMMdd");
this.add(newStory);
this.lastupdate = newStory.createtime;
res.message = "The story was created successfully!";
res.redirect(this.href());
} else
return (newStory);
}
/**
* check if there are any stories in the previous month
*/
function renderLinkToPrev(cal) {
if (!this.size())
return ("&nbsp;");
if (parseInt(this.get(this.size()-1).groupname,10) < parseInt(cal.getTime().format("yyyyMMdd"),10)) {
// there are any stories left back in history, so try to get them ...
prevDay = false;
while (!prevDay) {
cal.add(java.util.Calendar.DATE,-1);
if (this.get(cal.getTime().format("yyyyMMdd")))
prevDay = this.get(cal.getTime().format("yyyyMMdd"));
}
return ("<A HREF=\"" + this.href("main") + "?show="+ prevDay.groupname + "\">" + cal.getTime().format("MMMM") + "</A>");
} else {
return ("&nbsp;");
}
}
/**
* check if there are any stories in the previous month
*/
function renderLinkToNext(cal) {
if (!this.size())
return ("&nbsp;");
if (parseInt(this.get(0).groupname,10) > parseInt(cal.getTime().format("yyyyMMdd"),10)) {
// there are any stories, so try to get them ...
nextDay = false;
while (!nextDay) {
cal.add(java.util.Calendar.DATE,1);
if (this.get(cal.getTime().format("yyyyMMdd")))
nextDay = this.get(cal.getTime().format("yyyyMMdd"));
}
return ("<A HREF=\"" + this.href("main") + "?show="+ nextDay.groupname + "\">" + cal.getTime().format("MMMM") + "</A>");
} else {
return ("&nbsp;");
}
}
/**
* delete a story
*/
function deleteStory(currStory) {
currStory.setParent(this);
if (this.remove(currStory))
res.message = "The story was deleted successfully!";
else
res.message = "Ooops! Couldn't delete the story!";
res.redirect(this.href("main"));
}
/**
* function saves new properties of weblog
*/
function updateWeblog() {
this.title = req.data.title;
this.tagline = req.data.tagline;
this.bgcolor = req.data.bgcolor;
this.textfont = req.data.textfont;
this.textsize = req.data.textsize;
this.textcolor = req.data.textcolor;
this.linkcolor = req.data.linkcolor;
this.alinkcolor = req.data.alinkcolor;
this.vlinkcolor = req.data.vlinkcolor;
this.titlefont = req.data.titlefont;
this.titlesize = req.data.titlesize;
this.titlecolor = req.data.titlecolor;
this.days = parseInt(req.data.days,10);
this.online = parseInt(req.data.online,10);
this.discussions = parseInt(req.data.discussions,10);
this.archive = parseInt(req.data.archive,10);
this.birthdate = this.checkdate("birthdate");
res.message = "The changes were saved successfully!";
res.redirect(this.href());
}
/**
* function takes postdate of story, checks it and
* returns Date-object
*/
function checkdate(prefix) {
if (req.data[prefix + "Year"] && req.data[prefix + "Month"] && req.data[prefix + "Date"] && req.data[prefix + "Hours"] && req.data[prefix + "Minutes"]) {
var pd = new Date();
pd.setYear(parseInt(req.data[prefix + "Year"],10));
pd.setMonth(parseInt(req.data[prefix + "Month"],10));
pd.setDate(parseInt(req.data[prefix + "Date"],10));
pd.setHours(parseInt(req.data[prefix + "Hours"],10));
pd.setMinutes(parseInt(req.data[prefix + "Minutes"],10));
return (pd);
} else
return (new Date());
}
/**
* function returns true if discussions are enabled
* for this weblog
*/
function hasDiscussions() {
if (parseInt(this.discussions,10))
return true;
res.message = "Sorry, posting comments is not enabled here!";
return false;
}
/**
* function returns true if weblog is online
* otherwise false
*/
function isOnline() {
if (parseInt(this.online,10))
return true;
return false;
}
/**
* function creates the directory that will contain the images of this weblog
*/
function createImgDirectory() {
var dir = new File(getProperty("imgPath") + this.alias + "/");
return (dir.mkdir());
}

1
code/Site/preview.skin Normal file
View file

@ -0,0 +1 @@
&bull;<% this.title linkto="main" %> (last updated: <% this.lastupdate format="EEEE, dd.MM.yyyy HH:mm" %>)<BR>

View file

@ -0,0 +1,55 @@
/**
* function checks if a link to the given group makes sense
*/
function renderCalendarDay(currGroupname,text) {
var now = new Date();
var currGroup = this.get(currGroupname);
if (currGroup && currGroup.size()) {
if (user == this.owner)
var linkit = true;
else {
var linkit = false;
if (currGroupname <= now.format("yyyyMMdd")) {
for (var i=0;i<currGroup.size();i++) {
if (currGroup.get(i).isOnline())
linkit = true;
}
}
}
if (linkit) {
var text = "<A HREF=\"" + this.href("main") + "?show=" + currGroupname + "\">" + text + "</A>";
/*
if (!req.data.show && currGroupname == now.format("yyyyMMdd"))
text = "<B>" + text + "</B>";
else if (req.data.show && req.data.show == currGroupname)
text = "<B>" + text + "</B>";
*/
}
}
return (text);
}
/**
* function renders an image
*/
function renderImage(param) {
if (param.linkto)
this.openLink(param);
var img = this.images.get(param.name);
if (img) {
res.write("<IMG SRC=\"" + getProperty("imgUrl") + this.alias + "/" + img.filename + "." + img.fileext + "\"");
res.write(" WIDTH=\"" + (param.width ? param.width : img.width) + "\"");
res.write(" HEIGHT=\"" + (param.height ? param.height : img.height) + "\"");
res.write(" ALT=\"" + (param.alttext ? param.alttext : img.alttext) + "\"");
if (param.align)
res.write(" ALIGN=\"" + param.align + "\"");
if (param.valign)
res.write(" VALIGN=\"" + param.valign + "\"");
res.write(" BORDER=\"" + (param.border ? param.border : 0) + "\">");
}
if (param.linkto)
this.closeLink(param);
}

View file

@ -0,0 +1,14 @@
/**
* function checks if user is allowed to add a story to this weblog
*/
function checkPermissions() {
if (!user.uid) {
res.message = "Please login before editing a new story!";
user.cache.referer = this.href("create");
res.redirect(this.members.href("login"));
} else if (this.owner != user) {
res.message = "Sorry, you're not allowed to add a story!";
res.redirect(this.href());
}
}

45
code/Site/style.skin Normal file
View file

@ -0,0 +1,45 @@
<STYLE TYPE="text/css">
<!--
body { font-family: <% this.textfont %>;
font-size: <% this.textsize %>;
font-weight: normal;
color: #<% this.textcolor %>;
}
.title { font-family: <% this.titlefont %>;
font-size: <% this.titlesize %>;
color: <% this.titlecolor %>;
font-weight: bold;
}
.calendar { border: 1px solid black;
}
.calendarHeader { font-size: 8pt;
font-weight: bold;
color: #FFFFFF;
background-color: #666666;
}
.calendarDay { font-size: 8pt;
font-weight: normal;
border: 1px solid #666666;
text-align: center;
}
.calendarSelectedDay { font-size: 8pt;
font-weight: normal;
border: 1px solid #666666;
background-color: #FFFFFF;
text-align: center;
}
.calendarFooter { font-size: 8pt;
font-weight: bold;
color: #FFFFFF;
background-color: #999999;
}
// -->
</STYLE>

45
code/Site/type.properties Normal file
View file

@ -0,0 +1,45 @@
_datasource=antville
_tablename=WEBLOG
_subnodes=<story.WEBLOG_ID
_subnodes.groupby=DAY
_subnodes.order=CREATETIME DESC
_subnodes.groupby.order=CREATETIME DESC
_id=ID
owner=OWNER_ID>user.ID
title=TITLE
alias=ALIAS
tagline=TAGLINE
birthdate=BIRTHDATE
bgcolor=BGCOLOR
textfont=TEXTFONT
textcolor=TEXTCOLOR
textsize=TEXTSIZE
linkcolor=LINKCOLOR
alinkcolor=ALINKCOLOR
vlinkcolor=VLINKCOLOR
titlefont=TITLEFONT
titlecolor=TITLECOLOR
titlesize=TITLESIZE
online=ISONLINE
lastupdate=LASTUPDATE
blocked=ISBLOCKED
discussions=HASDISCUSSIONS
days=SHOWDAYS
archive=SHOWARCHIVE
createtime=CREATETIME
creator=CREATOR>user.ID
modifytime=MODIFYTIME
modifier=MODIFIER>user.ID
skinmanager=[virtual]skin.NAME
skinmanager.subnodeRelation=<skin.WEBLOG_ID
skinmanager.areSubnodes=true
skinmanager.groupby=PROTO
members=[mountpoint]membership
images=[mountpoint]imagemgr
skins=[mountpoint]skinmgr

View file

@ -0,0 +1,5 @@
<TABLE BGCOLOR="#FF9900" BORDER="0" CELLSPACING="0" CELLPADDING="2">
<TR>
<TD NOWRAP><% this.link to="main" text="&bull;&nbsp;home" %></TD>
</TR>
</TABLE>

1
code/Site/welcome.skin Normal file
View file

@ -0,0 +1 @@
<P>This is a completely empty weblog, but who nows? Maybe sometimes ...</P>