Earlier today I blogged about
the browser search plugins for SunWikis and Confluence.
This is how it all works:
1. Create the descriptor file
Create an
OpenSearch descriptor (OSD) file:
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>SunWikis</ShortName>
<Description>SunWikis (wikis.sun.com) Search</Description>
<InputEncoding>UTF-8</InputEncoding>
<OutputEncoding>UTF-8</OutputEncoding>
<Image width="16" height="16" type="image/x-icon">http://wikis.sun.com/favicon.ico</Image>
<Url type="text/html" method="GET"
template="http://wikis.sun.com/dosearchsite.action?searchQuery.queryString={searchTerms}&searchQuery.spaceKey=conf_global&searchQuery.lastModified="/>
</OpenSearchDescription>
Download
Check out the
template
attribute - the
{searchTerms}
will get replaced with the keyword typed into browser's search box. Keep in mind that if your template url contains an
"&"
character, it needs to be escaped as
&
, otherwise your XML will not be well formated.
2. Host the descriptor file
Once you have the file ready, host it on your server e.g. as
wikis.sun.com/search/wikis-osd.xml
3. Expose the descriptor file
Now you need to let browsers know about the descriptor. You can do this by placing a snippet like this somewhere between the
head
HTML tags.
<link rel="search" type="application/opensearchdescription+xml"
title="SunWikis" href="$req.contextPath/search/osd.xml">
In the case of using Confluence, you can do this by editing your template.
The
$req.contextPath
part is Confluence specific. Replace it with a piece of code that retrieves the context path or replace it with static context path e.g.
/myapplication
.
4. Bonus: Click-to-install link
Firefox and IE support the installation of search engines via JavaScript, which can be handy if you want to provide an "install" link.
As usual, both browsers use a different approach, and to be fair IE is ahead of Firefox in this one. :-/
Here is a JavaScript I put together based on
some resources
function addEngine(srcUrl, osdUrl, faviconUrl, fullName, category)
{
if ((typeof window.sidebar == "object") && (typeof window.sidebar.addSearchEngine == "function")) /* Firefox */
{
window.sidebar.addSearchEngine(
srcUrl, /* engine URL */
faviconUrl, /* icon URL */
fullName, /* engine name */
category); /* category name */
} else { /* IE */
if (window.external.AddSearchProvider) {
window.external.AddSearchProvider(osdUrl);
}
}
}
Download
For some weird reason (legacy?), Firefox uses
Apple's Sherlock format for JavaScript installation instead of OpenSearch descriptors. For this reason you need to create a Shrelock descriptor based on your OpenSearch descriptor. Keep in mind that the Shrelock descriptor filename must end with a
.src
extension.
In my case, my sherlock.src looks like this:
<search
version="1.0"
name="SunWikis"
description="SunWikis (wikis.sun.com) Search"
action="http://wikis.sun.com/dosearchsite.action"
searchForm="http://wikis.sun.com/dosearchsite.action"
queryCharset="UTF-8"
method="GET">
<input name="searchQuery.queryString" user>
<input name="searchQuery.spaceKey" value="conf_global">
<input name="searchQuery.lastModified" value="&">
</search>
It's not perfect because it is deliberately missing the
browser
element, but it will do. :)
The
user
attribute is an equivalent of the
{searchTerms}
variable in OpenSearch specification.
Once the file is created, upload it to your site, e.g.
wikis.sun.com/search/sherlock.src
.
And now you can create the link on a page that contains the JavaScript code mentioned above:
<a onclick="addEngine('/search/sherlock.src',
'/search/osd.xml', '/favicon.ico', 'SunWikis Search', 'Wiki')"
href="#">Install
</a>
For more information on this topic check out
this blog, but watch out for an
XSS hole - the
searchTerms
variable in the JavaScript snippet in the section "Step 3: The Search" must be url-encoded before it is used later in the script.
Some extra Confluece-specific stuff
You can create OSD files that search in all the spaces of your Confluence instance or in one space only. You can specify this via the
Url
attribute in the OSD file.
<Url type="text/html" method="GET"
template="http://wikis.sun.com/dosearchsite.action?searchQuery.queryString={searchTerms}&searchQuery.spaceKey=conf_global&searchQuery.lastModified="/>
The
searchQuery.spaceKey=conf_global
part means - search in all Confluence spaces (with the exception of personal spaces IIRC).
You can replace
conf_global
with a space key and you get a descriptor for space specific search.
For example, the url for a descriptor for our
About space would look like this:
<Url type="text/html" method="GET"
template="http://wikis.sun.com/dosearchsite.action?searchQuery.queryString={searchTerms}&searchQuery.spaceKey=About&searchQuery.lastModified="/>
If you want to get really fancy you can use the power of the
Lucene search engine (used in Confluence) to craft all kinds of interesting descriptors. For example this one that searches all the Confluence related spaces (the
DOC,
DISC, and
CONFEXT) at
confluence.atlassian.com by specifying the spaces in the
earchQuery.queryString
parameter instead of the
searchQuery.spaceKey
, which accepts only one space key.
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Confluence Extras</ShortName>
<Description>Documentation for the latest version of Confluence and Confluence Community + Confluence Extension Docs</Description>
<InputEncoding>UTF-8</InputEncoding>
<OutputEncoding>UTF-8</OutputEncoding>
<Image width="16" height="16" type="image/x-icon">http://confluence.atlassian.com/favicon.ico</Image>
<Url type="text/html" method="GET"
template="http://confluence.atlassian.com/dosearchsite.action?searchQuery.queryString=spacekey%3A%28DOC+OR+DISC+OR+CONFEXT%29+AND+%28{searchTerms}%29&searchQuery.lastModified="/>
</OpenSearchDescription>
Download
This OSD is based on a wicked Lucene search query that looks like this:
spacekey:(DOC OR DISC OR CONFEXT) AND({searchTerms})
You can find out more about Lucene goodies
here.
The last word of advice - instead of creating n+1 descriptors, one for each space + one for the search in all the spaces, use a JSP page to dynamically render the OSD file - that's how I implemented it for SunWikis.