Monday, November 08, 2010 at 12:04 AM.
system.verbs.builtins.mainResponder.testing.hierarchyPage
on hierarchyPage () {
<<Dive into the XML #hierarchy structure and find and build a page
<<Changes:
<<10/13/99; 6:29:53 PM by PBS
<<Commented out code checking pta^.lastNomad. It appears to be unneeded code -- and actually causes the whole thing not to work on some systems.
<<Handle default directory items. In other words, http://docserver.userland.com/file/default works the same as http://docserver.userland.com/file/.
local (pta = html.getPageTableAddress ());
<<temp.pt = pta^
local (adrTable = pta^.hierarchy);
local (adrHierarchy = pta^.hierarchy);
local (path = pta^.remainingPath);
<<First be sure the last nomad pointed to the top of this site: if not, the object really can't be found.
<<if pta^.lastNomad != pta^.adrSiteRootTable and pta^.lastNomad != pta^.responderAttributes.objectNotFoundHandler //PBS 10/13/99: commented out: appears to be unneeded, in fact it causes a problem with some people's setups.
<<scriptError ("Can't process the request because there is no object named \"" + string.nthField (pta^.remainingPath, "/", string.countFields (pta^.remainingPath, "/")) + "\".")
bundle { //compile the XML outline if needed
<<The hierarchy table contains the XML outline (outline) and a compiled XML table (structure). They should be in synch. When editing, always edit the outline.
local (flCompile = true);
if defined (adrTable^.structure) {
if timeModified (@adrTable^.outline) <= timeModified (@adrTable^.structure) {
flCompile = false}};
if flCompile {
xml.compile (string (adrTable^.outline), @adrTable^.structure)}};
local (nomad = @adrTable^.structure [1]); //points to #hierarchy structure
on hierarchyDive (nomad, name) { //PBS 6/17/99: dive into an XML hierarchy table
local (lowerName = string.lower (name));
local (flFound = false);
bundle { //find the item pointed to by name
local (i);
for i = 1 to sizeOf (nomad^) {
local (oneName = nameOf (nomad^ [i]));
if not (oneName contains "\t") {
continue};
try {
local (itemName = xml.getAttributeValue (@nomad^ [i], "pathname"));
if string.lower (itemName) == lowerName {
nomad = @nomad^ [i];
flFound = true;
break}}}};
if not flFound { //we didn't find the item
local (defaults = list (pta^.responderAttributes.defaultDirectoryItems));
local (s = string.trimWhiteSpace (pta^.path));
if not (s endswith "/") and (string.lower (defaults) contains string.lower (string.nthField (s, "/", string.countFields (s, "/")))) {
return (nomad)};
scriptError ("Can't process the request because there is no object named \"" + name + "\".")};
<<return (nomad) //don't advance, this way we might at least find the right category, if not the right page
return (nomad)};
bundle { //loop through the remaining path, looking for the object in the #hierarchy structure to serve
while (sizeOf (path) > 0) {
local (pathPart = string.nthField (path, "/", 1));
nomad = hierarchyDive (nomad, pathPart);
path = string.delete (path, 1, sizeOf (pathPart));
path = string.popLeading (path, '/')};
<<If this is a category, make sure there's a trailing slash, unless the end of the path ends with a default directory item name.
if string.lower (string.nthField (nameOf (nomad^), '\t', 2)) == "category" {
if not (pta^.remainingPath endsWith "/") {
<<PBS 10/13/99: Handle default directory items.
local (lowerLastPathPart = string.lower (string.nthField (pta^.path, '/', string.countFields (pta^.path, '/'))));
local (i, flDefault = false);
for i = 1 to sizeOf (pta^.responderAttributes.defaultDirectoryItems) {
if lowerLastPathPart == string.lower (pta^.responderAttributes.defaultDirectoryItems [i]) {
flDefault = true;
break}};
if not flDefault {
scriptError ("!redirect " + pta^.path + "/")}}}
else { //it's not a category, it must not end with a slash.
if pta^.remainingPath endsWith "/" {
scriptError ("!redirect " + string.popTrailing (pta^.path, "/"))}}};
local (type);
type = string.lower (string.nthField (nameOf (nomad^), '\t', 2));
if type == "" {
type = "category"};
local (htmlText);
on displayMessage (msgNum) {
pta^.flReadMessageProcessMacros = false;
pta^.flReadMessageAutoParagraphs = false;
pta^.flReadMessageExpandUrls = false;
add (mainResponder.discuss.readMessage (msgNum, flResponses:false, flResponseForm:false, flShowMsgNums:false, flShowAuthor:false, flShowPostTime:false, flShowReads:false, flStoryHeaderOnly:false, flEditButtonsInHeader:false, flShowEnclosure:false, editPageUrl:"", flShowCowSkullLink:true));
local (adrMsgTable = mainResponder.discuss.getMessageTable (msgNum));
local (title = adrMsgTable^.subject);
title = string.replaceAll (title, "\"", """);
pta^.title = title;
pta^.adrMsgTable = adrMsgTable;
pta^.msgNum = msgNum;
return (true)};
on add (s) {
htmlText = htmlText + s};
case string.lower (type) {
"category" {
local (i);
local (categoryDescription);
try {categoryDescription = xml.getValue (nomad, "description")};
if categoryDescription != nil {
add (categoryDescription + "<p>")};
try {
local (msgNum = xml.getAttributeValue (nomad, "msgnum"));
displayMessage (msgNum)}
else {
for i = 1 to sizeOf (nomad^) {
local (adr = @nomad^ [i]);
local (oneName = nameOf (adr^));
if typeOf (adr^) == tableType {
if oneName contains "\t" {
local (linetext);
try {
linetext = xml.getAttributeValue (adr, "name")};
local (description);
local (itemType = string.lower (string.nthField (nameOf (adr^), '\t', 2)));
if itemType == "story" or itemType == "category" {
local (url = pta^.path);
if not (url endsWith "/") {
url = string.popSuffix (url, "/") + "/"};
local (name = xml.getAttributeValue (adr, "pathname"));
url = url + name;
add ("<li>");
local (ct);
if itemType == "category" {
ct = sizeOf (xml.getAddressList (adr, "category"));
ct = ct + sizeOf (xml.getAddressList (adr, "link"));
ct = ct + sizeOf (xml.getAddressList (adr, "story"));
ct = " (" + ct + ")"};
add (html.getLink (linetext, url));
if ct != nil {
add (ct)};
if itemType == "story" {
try {
description = xml.getValue (adr, "description")};
if description != nil {
add (" - " + description)}};
add ("<p>")}}}};
local (title);
try {title = xml.getAttributeValue (nomad, "name")};
title = string.replaceAll (title, "\"", """);
pta^.title = title}};
"story" {
local (msgNum = xml.getAttributeValue (nomad, "msgNum"));
displayMessage (msgNum)}};
<<Build hierarchy path.
bundle {
local (pathText);
local (adrTable = nomad);
local (pathBgColor = "beige");
local (flHierarchyPath = true);
bundle { //get hierarchy path prefs
if defined (adrHierarchy^.prefs.bgcolor) {
pathBgColor = adrHierarchy^.prefs.bgcolor}
else {
pathBgColor = pta^.bgColor};
if defined (adrHierarchy^.prefs.outlineColor) {
outlineColor = adrHierarchy^.prefs.outlineColor}
else {
outlineColor = "#CCCCCC"};
if defined (adrHierarchy^.prefs.flHierarchyPath) {
flHierarchyPath = adrHierarchy^.prefs.flHierarchyPath}};
on add (s) {
pathText = s + pathText};
local (ctPops = 1);
if flHierarchyPath {
ctPops = 0}
else {
nomad = parentOf (nomad^)};
if not (string.lower (nameOf (nomad^)) endsWith "\thierarchy") {
loop {
local (url = "");
if type == "category" {
if ctPops > 0 {
url = string.filledString ("../", ctPops)}}
else {
if ctPops > 1 {
url = string.filledString ("../", ctPops - 1) + "./"};
if ctPops == 1 {
url = "./"}};
local (lineText = xml.getAttributeValue (nomad, "name"));
add (html.getLink (lineText, url));
ctPops++;
if ctPops == 2 and not flHierarchyPath {
break};
nomad = parentOf (nomad^);
if string.lower (nameOf (nomad^)) endsWith "\thierarchy" {
break};
if flHierarchyPath {
add (" > ")}}};
if pathText != "" {
pathText = " | " + pathText};
bundle { //was: if ctPops > 0
if ctPops == 0 {
pathText = ""};
local (nextPrevLinks = "Prev | Next");
local (ix = 0);
local (i);
local (adrCategory = parentOf (adrTable^));
for i = 1 to sizeOf (adrCategory^) {
if nameOf (adrCategory^ [i]) == nameOf (adrTable^) {
ix = i;
break}};
on getNextLink () {
local (i);
for i = (ix + 1) to sizeOf (adrCategory^) {
local (linktype = string.nthField (nameOf (adrCategory^ [i]), "\t", 2));
case string.lower (linktype) {
"category" {
local (url = xml.getAttributeValue (@adrCategory^ [i], "pathname"));
local (title = xml.getAttributeValue (@adrCategory^ [i], "name"));
if type == "category" {
return ("<a href=\"../" + url + "/\" title=\"" + title + "\">Next</a>")};
return ("<a href=\"" + url + "/\" title=\"" + title + "\">Next</a>")};
"link" {
local (url = xml.getValue (@adrCategory^ [i], "url"));
local (title = xml.getValue (@adrCategory^ [i], "linetext"));
return ("<a href=\"" + url + "\" title=\"" + title + "\">Next</a>")};
"story" {
local (url = xml.getAttributeValue (@adrCategory^ [i], "pathname"));
local (title = xml.getAttributeValue (@adrCategory^ [i], "name"));
if type == "category" {
return ("<a href=\"../" + url + "\" title=\"" + title + "\">Next</a>")};
return ("<a href=\"" + url + "\" title=\"" + title + "\">Next</a>")}}};
return ("Next")};
on getPrevLink () {
local (i);
for i = (ix - 1) downTo 1 {
local (linktype = string.nthField (nameOf (adrCategory^ [i]), "\t", 2));
case string.lower (linktype) {
"category" {
local (url = xml.getAttributeValue (@adrCategory^ [i], "pathname"));
local (title = xml.getAttributeValue (@adrCategory^ [i], "name"));
if type == "category" {
return ("<a href=\"../" + url + "/\" title=\"" + title + "\">Prev</a>")};
return ("<a href=\"" + url + "/\" title=\"" + title + "\">Prev</a>")};
"story" {
local (url = xml.getAttributeValue (@adrCategory^ [i], "pathname"));
local (title = xml.getAttributeValue (@adrCategory^ [i], "name"));
if type == "category" {
return ("<a href=\"../" + url + "\" title=\"" + title + "\">Prev</a>")};
return ("<a href=\"" + url + "\" title=\"" + title + "\">Prev</a>")}}};
return ("Prev")};
nextPrevLinks = getPrevLink () + " | " + getNextLink ();
if pathText != "" {
pathText = "<table border=\"0\" cellpadding=\"2\" cellspacing=\"1\" bgcolor=\"" + outlineColor + "\"><tr><td bgcolor=\"" + pathBgColor + "\" align=\"left\"><font size=\"-1\">" + nextPrevLinks + pathText + "</font></td></tr></table>"};
pta^.hierarchyPath = pathText}};
return (htmlText)}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.