Monday, November 08, 2010 at 12:05 AM.

system.verbs.builtins.radio.html.drawNavigatorLinks

on drawNavigatorLinks (renderedFileExtension="html") {
	<<Changes
		<<8/14/03; 5:33:30 PM by JES
			<<Fix a bug where links which include an anchor would in some cases be rendered without the anchor part.
		<<10/24/02; 11:48:03 PM by JES
			<<Wrap non-linked items (items for the current page) in a span with a CSS class of navigatorLinkCurrent.
		<<6/30/02; 3:43:07 PM by JES
			<<Added CSS classes to links: class="navigatorLink".
		<<4/11/02; 3:05:28 AM by JES
			<<Process macros before returning the navigator HTML -- the navigator is inserted into the page after normal macro processing, so macros need to be processed separately here.
		<<2/13/02; 1:39:00 PM by JES
			<<Get the item and separator format using a call to radio.weblog.getThemePref.
		<<1/24/02; 8:00:04 PM by JES
			<<If pta^.renderedFileExtension is defined, use it instead of the value of the archiveFileExtension parameter.
		<<1/19/02; 8:12:08 PM by JES
			<<Rewrote the code that generates links in static pages, to fix two bugs, one where the links would be to an index file, even though you specified a folder path, and another where the links would have a .txt extension even though the file in the cloud has a .html extension. Added an optional parameter, renderedFileExtension, which defaults to .html.
		<<1/2/02; 12:25:42 AM by JES
			<<Decode entities in the name attribute, to allow for entity-encoded accented characters.
		<<12/12/01; 2:37:21 PM by JES
			<<When linking to a folder, don't cause an error if the user forgot the trailing slash character.
		<<11/28/01; 6:26:13 PM by DW
			<<Instead of getting filetext from the cache, read it from the file.
			<<Instead of using outlineAsString, coerce the outline to a string.
		<<11/26/01; 12:27:50 PM by JES
			<<If an error occurs, return a macro error. Errors in this script were causing the desktop website home page to break.
		<<11/19/01; 12:24:07 AM by JES
			<<Created. Renders the links from a navigatorLinks.xml files. Implements a smart cache in temp.radio.navigatorLinksCache.
	local (htmltext);
	try { //if an error occurs, return a macro error
		local (pta = html.getPageTableAddress ());
		if defined (pta^.renderedFileExtension) {
			renderedFileExtension = pta^.renderedFileExtension};
		if not (renderedFileExtension beginsWith ".") {
			renderedFileExtension = "." + renderedFileExtension};
		local (pc = file.getPathChar ());
		if not defined (pta^.radioResponder.atts.navigatorLinks) { //return the empty string
			return ("")};
		local (indentlevel = 0);
		on add (s) {
			htmltext = htmltext + s};
		local (f = pta^.radioResponder.atts.navigatorLinks);
		local (fmodified = file.modified (f));
		local (adrblog = radio.weblog.init ());
		local (itemFormat = radio.weblog.getThemePref ("navigator.itemFormat", adrblog));
		local (separatorFormat = radio.weblog.getThemePref ("navigator.separatorFormat", adrblog));
		local (adrcache);
		bundle { //set adrcache, possibly return the cached HTML
			local (adrcachetable = @system.temp.radio.navigatorLinksCache);
			if not defined (adrcachetable^) {
				new (tableType, adrcachetable)};
			if pta^.radioResponder.flStaticRendering {
				adrcachetable = @system.temp.radio.navigatorLinksCache.static}
			else {
				adrcachetable = @system.temp.radio.navigatorLinksCache.dynamic};
			if not defined (adrcachetable^) {
				new (tableType, adrcachetable)};
			local (cachename = pta^.radioResponder.fileBeingRendered);
			adrcache = @adrcachetable^.[cachename];
			if defined (adrcache^) { //return the cached HTML if possible
				if adrcache^.fileLastModified == fmodified { //return the cached text
					if (adrcache^.itemFormat == itemFormat) and (adrcache^.separatorFormat == separatorFormat) {
						return (adrcache^.renderedText)}}}};
		local (adrfile);
		radio.file.getFileAttributes (f, @adrfile);
		local (mimetype = adrfile^.mimeType);
		case mimetype {
			"text/xml" { //parse the xml and use it to generate the links
				local (xtable);
				xml.compile (file.readwholefile (f), @xtable);
				local (adrnav = xml.getAddress (@xtable, "navigator"));
				local (adritem, ctitems = 0);
				for adritem in adrnav { //loop over all the <item>s in <navigator>
					if xml.convertToDisplayName (nameOf (adritem^)) == "item" { //ignore anything that's not an <item>
						local (linktext);
						local (name = xml.getAttributeValue (adritem, "name"));
						name = radio.string.decodeEntities (name, false);
						local (pagename = "");
						try {pagename = xml.getAttributeValue (adritem, "pagename")};
						local (anchor = "");
						if pagename contains "#" {
							anchor = "#" + string.nthField (pagename, "#", 2);
							pagename = string.nthField (pagename, "#", 1)};
						if pagename contains ":" { //absolute link
							<<linktext = html.getLink (name, pagename)
							linktext = "<a href=\"" + pagename + anchor + "\" class=\"navigatorLink\">" + name + "</a>"}
						else { //relative link
							if pagename == "" {
								linktext = name}
							else {
								if pta^.radioResponder.flStaticRendering { //link to the pages in the cloud
									bundle { //new code
										local (flerror = false, flpopindexfile = false);
										on locateIndexFile (folderPath, adrfindex) {
											local (adr, findex);
											for adr in @user.radio.prefs.indexFileNames {
												findex = filebeinglinked + adr^;
												if file.exists (findex) {
													adrfindex^ = findex;
													return (true)}};
											return (false)};
										local (filebeinglinked = radio.file.getAbsolutePath (pagename));
										if (pagename endsWith "/") { //try to locate the index file
											if locateIndexFile (filebeinglinked, @filebeinglinked) {
												flpopindexfile = true}}
										else { //locate the file, ignoring its extension
											if not radio.file.locateFileIgnoringExtension (radio.file.getAbsolutePath (pagename), @filebeinglinked) {
												if file.exists (filebeinglinked) { //check to see if this is a folder
													if file.isFolder (filebeinglinked) {
														if not (filebeinglinked endsWith pc) {
															pagename = pagename + "/";
															filebeinglinked = filebeinglinked + pc;
															if locateIndexFile (filebeinglinked, @filebeingrendered) {
																flpopindexfile = true}}}}
												else { //error
													flerror = true}}};
										if not flerror {
											if string.lower (filebeinglinked) == string.lower (pta^.radioResponder.fileBeingRendered) { //bold, not a link
												<<linktext = "<b>" + name + "</b>"
												linktext = "<b><span class=\"navigatorLinkCurrent\">" + name + "</span></b>"}
											else { //link to it
												local (url);
												url = radio.upstream.getFileUrl (fileBeingLinked);
												if flpopindexfile { //link to a folder -- strip off the "index.html"
													url = string.popSuffix (url, "/") + "/"}
												else { //link to a file, not to a folder -- possibly patch the file extension
													local (lowerurl = string.lower (url));
													if (lowerurl endsWith ".txt") or (lowerurl endsWith ".opml") {
														local (flrendered = true);
														if (lowerurl endswith "/directory.opml") {
															if file.exists (file.folderFromPath (filebeinglinked) + radio.data.fileNames.upstreamFileName) {
																flrendered = false}}
														else { //gather attributes, to see if the file is rendered or not
															local (atts);
															radio.webserver.gatherAttributes (filebeinglinked, @atts, @atts);
															if defined (atts.flRender) {
																flrendered = atts.flRender}};
														if flRendered {
															url = string.popSuffix (url) + renderedFileExtension}}};
												<<linktext = html.getLink (name, url + anchor)
												linktext = "<a href=\"" + url + anchor + "\" class=\"navigatorLink\">" + name + "</a>"}};
										if flerror { //put an error in place of the link so the webmaster can fix the problem
											linktext = "<b>Error: Can't find file, \"" + pagename + "\".</b>"}}}
									<<bundle //original code
										<<local (flerror = false, flfolder = false)
										<<local (filebeinglinked = radio.file.getAbsolutePath (pagename))
										<<if (pagename endsWith "/") //try to locate the index file
											<<local (adr, findex)
											<<for adr in @user.radio.prefs.indexFileNames
												<<findex = filebeinglinked + adr^
												<<if file.exists (findex)
													<<filebeinglinked = findex
													<<break
										<<else //locate the file, ignoring its extension
											<<if not radio.file.locateFileIgnoringExtension (radio.file.getAbsolutePath (pagename), @filebeinglinked)
												<<if file.exists (filebeinglinked) //check to see if this is a folder
													<<if file.isFolder (filebeinglinked)
														<<if not (filebeinglinked endsWith pc)
															<<pagename = pagename + "/"
															<<filebeinglinked = filebeinglinked + pc
															<<flfolder = true
												<<else //error
													<<flerror = true
										<<if not flerror
											<<if string.lower (filebeinglinked) == string.lower (pta^.radioResponder.fileBeingRendered) //bold, not a link
												<<linktext = "<b>" + name + "</b>"
											<<else //link to it
												<<local (url)
												<<url = radio.upstream.getFileUrl (fileBeingLinked)
												<<linktext = html.getLink (name, url + anchor)
										<<if flerror //put an error in place of the link so the webmaster can fix the problem
											<<linktext = "<b>Error: Can't find file, \"" + pagename + "\"."
								else { //link to the local dynamic pages
									if not (pagename beginsWith "/") { //always link from the top of the site
										pagename = "/" + pagename};
									if string.lower (pta^.uri) == string.lower (pagename) {
										linktext = "<b><span class=\"navigatorLinkCurrent\">" + name + "</span></b>"}
									else { //link to it
										<<linktext = html.getLink (name, pagename + anchor)
										linktext = "<a href=\"" + pagename + anchor + "\" class=\"navigatorLink\">" + name + "</a>"}}}};
						add (string.replace (itemFormat, "<%item%>", linktext, false) + separatorFormat);
						ctitems++}};
				if ctitems > 0 {
					htmltext = string.mid (htmltext, 1, sizeOf (htmltext) - sizeOf (separatorFormat))}};
			"text/opml" {
				htmltext = string (adrfile^.outline)}}
		else { //include the file as is
			htmltext = string (file.readwholefile (f))};
		bundle { //update the cache
			if not defined (adrcache^) {
				new (tableType, adrcache)};
			adrcache^.itemFormat = itemFormat;
			adrcache^.separatorFormat = separatorFormat;
			adrcache^.renderedText = htmltext;
			adrcache^.fileLastModified = fmodified};
		htmltext = html.processMacros (htmltext)}
	else { //bad XML -- macro error
		htmltext = "[Macro error: Can't render navigator links because an error occurred: \"" + string.replaceAll (tryError, "<", "<") + "\".]"};
	return (htmltext)}
<<bundle //debugging
	<<new (tableType, @temp.radio.navigatorLinksCache)
	<<local (pagetable = workspace.pt)
	<<html.setPageTableAddress (@pagetable)
	<<wp.newTextObject (drawNavigatorLinks (), @scratchpad.navLinks); edit (@scratchpad.navLinks)
	<<html.deletePageTableAddress ()



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.