# Build everything necessary to compile the wiki.
-SUBDIRS = posts/yacc2dot posts/Xmodmap posts/XSLT/chapter posts/XSLT/code
+SUBDIRS = posts/rel-vcs posts/yacc2dot posts/Xmodmap \
+ posts/XSLT/chapter posts/XSLT/code
TARGETS = all clean
all :
--- /dev/null
+Since I publish a lot of [[Git]] packages, I was interested to read
+about [Joey Hess][]' [rel=vcs-* microformat][format]. I think
+recording the location of the repo sorcing a page is a great idea, but
+with the link stashed in the page header, I could easily browse on by
+without ever noticing that the link existed.
+
+This looks like the same sort of problem that the [Semantic Radar][SR]
+extension was designed to solve, except the SR extension notifies you
+about RDF files (SIOC, FOAF, DOAP, etc.). I've altered the SR
+extension to identify the `rel=vcs-*` tags.
+
+The [[rel-vcs|rel-vcs.xpi]] extension places an icon in your Firefox
+statusbar which goes "hot" when a page has `rel=vcs-*` tags and "cold"
+otherwise. When the icon is "hot", you can click on it to pop up a
+list of rel-vcs links. Clicking on an item in the list will open that
+URI in a new tab. Since Firefox can't speak `git://` etc., the new
+tab will mostly be useful as a source of the URI for copy/pasting into
+a `git clone ...` call or similar. Alternatively, you can consider
+the "hot" icon as a suggestion to use `webcheckout` or other
+`rel=vcs-*` consumer on the source page.
+
+[Joey Hess]: http://kitenet.net/~joey/
+[format]: http://kitenet.net/~joey/rfc/rel-vcs/
+[SR]: http://sioc-project.org/firefox
--- /dev/null
+all : rel-vcs.xpi
+
+clean :
+ rm -f rel-vcs.xpi
+
+rel-vcs.xpi : $(shell find rel-vcs)
+ zip -r $@ rel-vcs
+
+.PHONY : all clean
--- /dev/null
+Firefox extension adding a notification icon for pages with
+`rel=vcs-*` tags. See the [specs][] for details on the format.
+
+When the icon is "hot", you can click on it to pop up a list of
+rel-vcs links. Clicking on an item in the list will open that URI in
+a new tab. Since Firefox can't speak `git://` etc., the new tab will
+mostly be useful as a source of the URI for copy/pasting into a `git
+clone ...` call or similar. Alternatively, you can consider the "hot"
+icon as a suggestion to use `webcheckout` or other `rel=vcs-*`
+consumer on the source page.
+
+This plugin was initially based on the source for the [Semantic
+Radar][SR] plugin.
+
+[specs]: http://kitenet.net/~joey/rfc/rel-vcs/
+[SR]: http://sioc-project.org/firefox
--- /dev/null
+overlay chrome://browser/content/browser.xul chrome://rel-vcs/content/overlay.xul
+
+content rel-vcs chrome/content/
+skin rel-vcs classic/1.0 chrome/skin/classic/
+locale rel-vcs en-US chrome/locale/en-US/
+
+style chrome://global/content/customizeToolbar.xul chrome://rel-vcs/skin/overlay.css
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?xml-stylesheet href="chrome://rel-vcs/skin/about.css" type="text/css"?>\r
+<!DOCTYPE prefwindow SYSTEM "chrome://rel-vcs/locale/about.dtd">\r
+\r
+<window class="dialog"\r
+ title="rel-vcs - About"\r
+ orient="vertical"\r
+ autostretch="always"\r
+ onload="sizeToContent()"\r
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">\r
+ <groupbox align="center" orient="horizontal">\r
+ <vbox>\r
+ <hbox>\r
+ <text value="rel-vcs" style="font-weight: bold; font-size: x-large;"/>\r
+ <spring flex="1"/>\r
+ <image src="chrome://rel-vcs/skin/logo.png"/>\r
+ </hbox>\r
+ <text value="ver. 1.0"/>\r
+ <separator class="thin"/>\r
+ <text value="Created By:" style="font-weight: bold;"/>\r
+ <hbox orient="horizontal">\r
+ <text value="W. Trevor King" class="text-link"\r
+ onclick="window.open('http://www.physics.drexel.edu/~wking/'); window.close();"/>\r
+ </hbox>\r
+ <separator class="thin"/>\r
+ <text value="Home Page:" style="font-weight: bold;"/>\r
+ <text value="http://www.physics.drexel.edu/~wking/unfolding-disasters/posts/rel-vcs/"\r
+ class="text-link"\r
+ onclick="window.open('http://www.physics.drexel.edu/~wking/unfolding-disasters/posts/rel-vcs/'); window.close();"/>\r
+ <separator class="thin"/>\r
+ </vbox>\r
+ </groupbox>\r
+ <hbox>\r
+ <spacer flex="1"/>\r
+ <button label="Close" oncommand="window.close();"/>\r
+ </hbox>\r
+</window>\r
--- /dev/null
+<?xml version="1.0"?>\r
+\r
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+ xmlns:chrome="http://www.mozilla.org/rdf/chrome#">\r
+ <RDF:Seq RDF:about="urn:mozilla:package:root">\r
+ <RDF:li RDF:resource="urn:mozilla:package:rel-vcs"/>\r
+ </RDF:Seq>\r
+ <RDF:Seq RDF:about="urn:mozilla:overlays">\r
+ <RDF:li RDF:resource="chrome://browser/content/browser.xul"/>\r
+ <RDF:li RDF:resource="chrome://navigator/content/navigator.xul"/>\r
+ </RDF:Seq>\r
+ <RDF:Seq RDF:about="chrome://browser/content/browser.xul">\r
+ <RDF:li>chrome://rel-vcs/content/overlay.xul</RDF:li>\r
+ </RDF:Seq>\r
+ <RDF:Seq RDF:about="chrome://navigator/content/navigator.xul">\r
+ <RDF:li>chrome://rel-vcs/content/overlay.xul</RDF:li>\r
+ </RDF:Seq>\r
+ <RDF:Description RDF:about="urn:mozilla:package:rel-vcs"\r
+ chrome:displayName="rel-vcs 1.0"\r
+ chrome:author="W. Trevor King"\r
+ chrome:authorURL="mailto:wking@drexel.edu"\r
+ chrome:name="rel-vcs"\r
+ chrome:extension="true"\r
+ chrome:description="Displays an icon to indicate presence of rel-vcs data in the web page.">\r
+ </RDF:Description>\r
+</RDF:RDF>\r
--- /dev/null
+// Log to console (see http://plasmasturm.org/log/186/)
+function _rel_vcs_log_console(msg) {
+ var debug_flag = false;
+
+ if (debug_flag) {
+ Components
+ .classes["@mozilla.org/consoleservice;1" ]
+ .getService(Components.interfaces["nsIConsoleService"])
+ .logStringMessage(msg);
+ }
+}
+
+function get_HTML_by_tag_name(tag) {
+ // from https://developer.mozilla.org/en/Writing_JavaScript_for_XHTML
+ if (content.document.documentElement.namespaceURI !== null) { // tag soup
+ return content.document.getElementsByTagName(tag);
+ } else { // xml document
+ return content.document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", tag);
+ }
+}
+
+// Find links to rel-vcs data
+function get_rel_vcs() {
+ var links = new Array();
+ if (content === null) {
+ return links;
+ }
+
+ var all_links = get_HTML_by_tag_name('link');
+ var i = 0;
+ for (i=0; i < all_links.length; i++) {
+ var link = all_links[i];
+ _rel_vcs_log_console("check "+link.rel+" ? "+String(link.rel.match("^vcs-")));
+ if (link.rel.match("^vcs-")) {
+ links.push(link.cloneNode(false));
+ }
+ }
+
+ var all_links = get_HTML_by_tag_name('a');
+ for (i=0; i < all_links.length; i++) {
+ var link = all_links[i];
+ _rel_vcs_log_console("check "+link.rel+" ? "+String(link.rel.match("^vcs-")));
+ if (link.rel.match("^vcs-")) {
+ // Todo, read in tag body if title attribute is missing
+ links.push(link.cloneNode(false));
+ }
+ }
+
+ return links;
+}
+
+function detect_rel_vcs(event) {
+ var has_rel_vcs = (get_rel_vcs().length > 0);
+ rel_vcs_display_status(has_rel_vcs);
+}
+
+// Extension status
+function rel_vcs_display_status(has_rel_vcs) {
+ _rel_vcs_log_console("has rel-vcs? "+String(has_rel_vcs));
+ var item = document.getElementById("rel-vcs-icon");
+ if (has_rel_vcs) {
+ item.setAttribute("state", "on");
+ } else {
+ item.setAttribute("state", "off");
+ }
+}
+
+function rel_vcs_about_dialog() {
+ window.openDialog("chrome://rel-vcs/content/about.xul",
+ "rel-vcs-about-dialog",
+ "centerscreen,chrome,modal,resizable");
+}
+
+function rel_vcs_exec_action(button) {
+ var links = get_rel_vcs();
+ rel_vcs_popup_dialog(button, links);
+}
+
+function rel_vcs_popup_dialog(button, links) {
+ if (links.length == 0) {
+ return;
+ }
+
+ var popmenu = document.getElementById("rel-vcs-popmenu");
+ var icons = {
+ "logo": "chrome://rel-vcs/skin/logo.png"
+ };
+
+ // clean the popup
+ while (popmenu.childNodes.length > 0) {
+ popmenu.removeChild(popmenu.lastChild);
+ }
+
+ // add all new items
+ for (key in links) {
+ var link = links[key];
+ var rel = link.rel;
+ var uri = link.href;
+ var title = link.title;
+ var menuitem = document.createElement('menuitem');
+ menuitem.setAttribute('label', title+' ('+uri+')');
+ menuitem.setAttribute('tooltiptext', 'Click to view '+uri);
+ menuitem.setAttribute('onclick', 'rel_vcs_open_uri("'+uri+'", "'+rel+'")');
+ menuitem.setAttribute('class', 'menuitem-iconic ' + rel);
+ menuitem.setAttribute('image', icons['logo']); // icons[rel]
+ popmenu.appendChild(menuitem);
+ }
+
+ // NOTE: wait only for DOM to load before running check for rel-vcs content
+ popmenu.showPopup(button, -1, -1, 'popup', 'topright' , 'bottomright');
+}
+
+function rel_vcs_open_uri(uri, rel) {
+ var newTab = getBrowser().addTab(uri);
+ getBrowser().selectedTab = newTab; // change the focused tab, feel free to delete
+}
+
+function init() {
+ _rel_vcs_log_console("init rel-vcs");
+ // Listen for Page loads
+ getBrowser().addEventListener("load", detect_rel_vcs, true);
+ // Listen for Tab switches
+ getBrowser().addEventListener("select", detect_rel_vcs, true);
+}
+
+init();
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://rel-vcs/skin/overlay.css" type="text/css"?>
+<!DOCTYPE overlay SYSTEM "chrome://rel-vcs/locale/rel-vcs.dtd">
+
+<overlay id="rel-vcs"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/x-javascript" src="chrome://rel-vcs/content/overlay.js" />
+
+ <!-- rel-vcs status bar overlay -->
+ <statusbar id="status-bar">
+ <popupset>
+ <menupopup id="rel-vcs-popmenu" />
+ </popupset>
+ <statusbarpanel
+ id="rel-vcs-icon"
+ class="statusbarpanel-iconic"
+ tooltiptext="&rel-vcs.statusbar.icon;"
+ oncommand="rel_vcs_exec_action(this);"
+ insertafter="livemark-button"
+ state="on"
+ />
+ </statusbar>
+
+
+ <!-- rel-vcs menu overlay -->
+ <menupopup id="menu_ToolsPopup">
+ <menu label="&rel-vcs.menu.label;"
+ accesskey="&rel-vcs.menu.accesskey;"
+ image="chrome://rel-vcs/skin/logo.png"
+ insertafter="devToolsSeparator"
+ id="rel-vcs-toolspopup-menu">
+ <menupopup>
+ <menuitem label="&rel-vcs.menu.item.about.label;"
+ accesskey="&rel-vcs.menu.item.about.accesskey;"
+ tooltiptext="&rel-vcs.menu.item.about.tooltiptext;"
+ oncommand="rel_vcs_about_dialog();"
+ disabled="false" />
+ </menupopup>
+ </menu>
+ </menupopup>
+</overlay>
--- /dev/null
+<?xml version="1.0"?>
+
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
+ <RDF:Seq RDF:about="urn:mozilla:locale:root">
+ <RDF:li RDF:resource="urn:mozilla:locale:en-US"/>
+ </RDF:Seq>
+ <RDF:Description RDF:about="urn:mozilla:locale:en-US"
+ chrome:author="W. Trevor King"
+ chrome:displayName="English(US)"
+ chrome:name="en-US">
+ <chrome:packages>
+ <RDF:Seq about="urn:mozilla:locale:en-US:packages">
+ <RDF:li resource="urn:mozilla:locale:en-US:rel-vcs"/>
+ </RDF:Seq>
+ </chrome:packages>
+ </RDF:Description>
+</RDF:RDF>
--- /dev/null
+<!ENTITY rel-vcs.name "rel-vcs">
+
+<!ENTITY rel-vcs.statusbar.icon "Click to view rel-vcs data">
+
+<!ENTITY rel-vcs.menu.label "rel-vcs">
+<!ENTITY rel-vcs.menu.accesskey "R">
+<!ENTITY rel-vcs.menu.item.about.label "About">
+<!ENTITY rel-vcs.menu.item.about.accesskey "A">
+<!ENTITY rel-vcs.menu.item.about.tooltiptext "About rel-vcs">
--- /dev/null
+@import url("chrome://global/skin/");
+@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+#rel-vcs-about-dialog {
+ width: 20em;
+}
+
+#rel-vcs-title {
+ font-weight: bold;
+ font-size: x-large;
+}
+
+#rel-vcs-version {
+ font-size: 0.8em;
+}
+
+.important {
+ font-weight: bold;
+}
--- /dev/null
+<?xml version="1.0"?>\r
+\r
+<RDF:RDF xmlns:chrome="http://www.mozilla.org/rdf/chrome#"\r
+ xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\r
+ <RDF:Seq about="urn:mozilla:skin:root">\r
+ <RDF:li resource="urn:mozilla:skin:classic/1.0" />\r
+ </RDF:Seq>\r
+ <RDF:Description about="urn:mozilla:skin:classic/1.0">\r
+ <chrome:packages>\r
+ <RDF:Seq about="urn:mozilla:skin:classic/1.0:packages">\r
+ <RDF:li resource="urn:mozilla:skin:classic/1.0:rel-vcs"/>\r
+ </RDF:Seq>\r
+ </chrome:packages>\r
+ </RDF:Description>\r
+</RDF:RDF>\r
--- /dev/null
+@import url("chrome://global/skin/");
+@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+.rel-vcs {
+ padding-left: 0;
+}
+
+#rel-vcs-icon[state="on"] {
+ list-style-image: url("chrome://rel-vcs/skin/logo.png");
+}
+
+#rel-vcs-icon[state="off"] {
+ list-style-image: url("chrome://rel-vcs/skin/logo_cold.png");
+}
--- /dev/null
+<?xml version="1.0"?>\r
+\r
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">\r
+ <Description about="urn:mozilla:install-manifest">\r
+ <em:id>f65e832a-9b45-453a-9fb7-d04334b605e7@invalid.net</em:id>\r
+ <em:version>1.0</em:version>\r
+ <em:type>2</em:type> <!-- 2 designates an extension (vs. theme, etc.) -->\r
+\r
+ <!-- Front End MetaData -->\r
+ <em:name>rel-vcs</em:name>\r
+ <em:description>Displays an icon to indicate presence of a rel-vcs link in the web page.</em:description>\r
+ <em:creator>W. Trevor King</em:creator>\r
+ <em:homepageURL>http://www.physics.drexel.edu/~wking/unfolding-disasters/posts/rel-vcs/</em:homepageURL>\r
+\r
+ <em:iconURL>chrome://rel-vcs/skin/logo.png</em:iconURL>\r
+ <em:aboutURL>chrome://rel-vcs/content/about.xul</em:aboutURL>\r
+ <!-- <em:updateURL>http://rdfs.org/rel-vcs/updates.rdf</em:updateURL> -->\r
+ <em:file>\r
+ <Description about="urn:mozilla:extension:file:rel-vcs.jar">\r
+ <em:package>content/</em:package>\r
+ <em:skin>skin/classic/</em:skin>\r
+ <em:locale>locale/en-US/</em:locale>\r
+ </Description>\r
+ </em:file>\r
+ \r
+ <!-- Target Applications this extension can install into, \r
+ with minimum and maximum supported versions. --> \r
+\r
+ <em:targetApplication> <!-- Firefox -->\r
+ <Description>\r
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>\r
+ <em:minVersion>1.5</em:minVersion>\r
+ <em:maxVersion>3.6.*</em:maxVersion>\r
+ </Description>\r
+ </em:targetApplication>\r
+\r
+ <!--em:targetApplication> < ! - - Mozilla Suite - - >\r
+ <Description>\r
+ <em:id>{86c18b42-e466-45a9-ae7a-9b95ba6f5640}</em:id>\r
+ <em:minVersion>1.5</em:minVersion>\r
+ <em:maxVersion>1.7+</em:maxVersion>\r
+ </Description>\r
+ </em:targetApplication-->\r
+\r
+ <!--em:targetApplication> < ! - - Flock - - >\r
+ <Description>\r
+ <em:id>{a463f10c-3994-11da-9945-000d60ca027b}</em:id>\r
+ <em:minVersion>1.0</em:minVersion>\r
+ <em:maxVersion>2.5</em:maxVersion>\r
+ </Description>\r
+ </em:targetApplication-->\r
+\r
+ </Description>\r
+</RDF>\r