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

system.verbs.builtins.html.data.standardMacros.opmlToBlogroll

on opmlToBlogroll (opmlUrl, flProcessMacros=true, cssPrefix="blogroll", cacheSeconds=60, flXmlButton=true, recentlyUpdatedLinkPrefix="", recentlyUpdatedLinkSuffix="") {
	<<Changes
		<<7/29/02; 2:06:22 AM by JES
			<<New optional parameters, recentlyUpdatedLinkPrefix and recentlyUpdatedLinkSuffix, specify snippets of HTML text to prepend and append to links generated from OPML elements that have an isRecent attribute whose value is true.
			<<Respect title and target attributes of outline elements if present, and include them in the link tag.
		<<6/2/02; 3:18:11 PM by DW
			<<Leave behind clues for the blogroll link.
			<<http://radio.userland.com/radioMacrosHeadLinks
		<<5/28/02; 2:25:05 PM by JES
			<<New optional parameter, flXmlButton specifies whether to add an XML button after the links. Defaults to true.
		<<5/22/02; 3:37:18 PM by JES
			<<Created. Renders blogroll links given the URL of an OPML file.
	
	bundle { //leave hint for link generator, 6/2/02 by DW
		local (pta = html.getpagetableaddress ());
		if not defined (pta^.blogRollUrls) {
			pta^.blogRollUrls = {}};
		pta^.blogRollUrls = pta^.blogRollUrls + {opmlUrl}};
	bundle { //make sure prefix and suffix don't contain un-necoded quite characters
		recentlyUpdatedLinkPrefix = string.replaceAll (recentlyUpdatedLinkPrefix, "\"", """);
		recentlyUpdatedLinkSuffix = string.replaceAll (recentlyUpdatedLinkSuffix, "\"", """)};
	
	local (htmltext = "", indentlevel = 0);
	on add (s) {
		htmltext = htmltext + (string.filledstring ("\t", indentlevel) + s + "\r");};
	
	local (miniMugIcon, miniXmlButton);
	bundle { //set miniMugIcon and miniXmlButton
		miniXmlButton = "<img src=\"http://static.userland.com/shortcuts/images/misc/miniXmlButton.gif\" width=\"19\" height=\"9\" border=\"0\" valign=\"middle\" alt=\"miniXmlButton.gif\" />";
		miniMugIcon = "<img src=\"http://static.userland.com/shortcuts/images/misc/miniXmlCoffeeMug.gif\" width=\"10\" height=\"10\" border=\"0\" valign=\"middle\" alt=\"miniXmlCoffeeMug.gif\" />"};
	
	local (adrincache);
	bundle { //set adrincache
		local (adrcache = @system.temp.blogrollCache);
		if not defined (adrcache^) {
			new (tableType, adrcache)};
		adrincache = @adrcache^.[opmlUrl];
		if not defined (adrincache^) {
			new (tableType, adrincache);
			adrincache^.whenLastRead = date (0);
			adrincache^.whenLastSizeCheck = date (0)}};
	
	bundle { //load the outline if necessary, and compile the xml
		local (lo);
		local (flRead = false);
		local (adrOpenUrlCache = @system.temp.Frontier.openUrlCache);
		if not defined (adrOpenUrlCache^) {
			flRead = true};
		if not defined (adrOpenUrlCache^.[opmlUrl]) {
			flRead = true};
		if not defined (adrOpenUrlCache^.[opmlUrl].outline) {
			flRead = true};
		if clock.now () > date (adrincache^.whenLastSizeCheck + cacheSeconds) { //only check size if cache is expired
			Frontier.tools.windowTypes.commands.openUrl (opmlUrl, adroutline:@lo);
			adrincache^.whenLastSizeCheck = clock.now ()};
		if timeModified (@adrOpenUrlCache^.[opmlUrl].outline) > adrincache^.whenLastRead {
			flRead = true};
		if not defined (adrincache^.xstruct) {
			flRead = true};
		if flRead { //read the outline, compile the xml and store it in the cache
			local (xtext = op.outlineToXml (@lo));
			xml.compile (xtext, @adrincache^.xstruct);
			adrincache^.whenLastRead = timeModified (@adrOpenUrlCache^.[opmlUrl].outline)}};
	
	on hasSubs (adr) {
		local (adritem);
		for adritem in adr {
			if not (nameOf (adritem^) beginsWith "/") {
				return (true)}};
		return (false)};
	on addItem (text, url, xmlurl, isRecent, target="", tooltip="") {
		local (xmllinks = "", targetstring = "", titlestring = "", prefix = "", suffix = "");
		if xmlurl != "" { //get coffee mug and xml button links
			xmllinks = "<a href=\"http://127.0.0.1:5335/system/pages/subscriptions?url=" + string.urlEncode (xmlurl) + "\" title=\"Click to subscribe to "" + string.replaceAll (text, "\"", """) + "" in Radio UserLand.\">" + miniMugIcon + "</a> ";
			xmllinks = xmllinks + "<a href=\"" + xmlurl + "\" title=\"Click to view the XML source for "" + string.replaceAll (text, "\"", """) + "".\">" + miniXmlButton + "</a> "};
		if url == "" { //not linked
			add ("<div class=\"" + cssPrefix + "Text\">" + xmllinks + text + "</div>")}
		else { // linked
			if sizeOf (target) > 0 {
				targetstring = " target=\"" + string.replaceAll (target, "\"", "") + "\""};
			if sizeOf (tooltip) > 0 {
				titlestring = " title=\"" + string.replaceAll (tooltip, "\"", "&") + "\""};
			if isRecent {
				prefix = recentlyUpdatedLinkPrefix;
				suffix = recentlyUpdatedLinkSuffix};
			text = prefix + "<a href=\"" + url + "\" class=\"" + cssPrefix + "Link\"" + targetstring + titlestring + ">" + text + "</a>" + suffix;
			add ("<div class=\"" + cssPrefix + "LinkedText\">" + xmllinks + text + "</div>")}};
	on renderOneLevel (adr) {
		local (text = "", url = "", xmlurl = "", isRecent = false, tooltip = "", target = "");
		local (adratts = @adr^.["/atts"]);
		if defined (adratts^) { //set text, url and xmlurl
			if defined (adratts^.text) {
				text = xml.entityDecode (adratts^.text, true)};
			if defined (adratts^.url) {
				url = adratts^.url};
			if defined (adratts^.htmlUrl) {
				url = adratts^.htmlUrl};
			if defined (adratts^.xmlUrl) {
				xmlurl = adratts^.xmlUrl};
			if defined (adratts^.isRecent) {
				if adratts^.isRecent {
					isRecent = true}};
			if defined (adratts^.title) {
				tooltip = adratts^.title};
			if defined (adratts^.target) {
				target = adratts^.target}};
		addItem (text, url, xmlurl, isRecent, target, tooltip);
		if hasSubs (adr) { //recurse
			indentlevel++;
			local (adrsub);
			for adrsub in adr {
				if not (nameOf (adrsub^) beginsWith "/") {
					renderOneLevel (adrsub)}};
			indentlevel--}};
	
	local (nomad = xml.getaddress (@adrincache^.xstruct, "opml"));
	nomad = xml.getaddress (nomad, "body");
	local (adr);
	for adr in nomad {
		renderOneLevel (adr)};
	if flProcessMacros {
		htmltext = html.processMacros (htmltext)};
	if flXmlButton { //add a link to the OPML source
		add ("<div class=\"" + cssPrefix + "LinkedText\"> <br /><a class=\"" + cssPrefix + "SourceLink\" href=\"" + opmlUrl + "\" title=\"Click on this icon to view the OPML source for these links.\"><img src=\"http://www.scripting.com/images/xmlIcon2.gif\" height=\"14\" width=\"36\" border=\"0\"></a></div>")};
	
	return (htmltext)};

<<bundle //test code
	<<local (f = user.radio.prefs.wwwFolder + "gems" + file.getPathChar () + "mySubscriptions.opml")
	<<local (url = radio.upstream.getFileUrl (f))
	<<local (startticks = clock.ticks ())
	<<blogroll (url, false)
	<<local (totalticks = clock.ticks () - startticks)
	<<dialog.notify (totalticks)



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.