Writing Extensions with DekiScript

In Deki Wiki 1.8.3, we’ve added the capability to write extensions in XML using the DekiScript service. This makes it a lot easier to write extensions for embedding widgets or using JavaScript APIs.

The idea is quite simple and intuitive.  An extension file contains functions.  Each function returns a HTML document that contains a <head>, <body>, and <tail> element.  For example, output of a function might look like this:

<html>

<head><script src="http://server/instant.js" type="text/javascript" /></head>

<body><img src="http://server/picture.png" class="instant ishadow33 icolorF0F4FF" /></body>

<tail></tail>

</html>

This output describes how to load the “instant.js” JavaScript file and then apply a polaroid effect to “picture.png”.  The <tail> element is empty for this example.  Its use is similar to <head> for loading/embedding JavaScript.  The difference is that code in the <tail> element is only run after the page has fully loaded.  When Deki Wiki receives this output, it merges the <head> and <tail> elements from each function invocation.  It also replaces the function call with the contents of the <body> element.  Once all functions have been invoked, the page is sent to the browser.  Simple and elegant!

Let’s create an XML file that describes the extension and its functions.  The following example describes an extension with one function called “instant”.  The function takes no parameters and simply returns the above document as a result.

<extension>

<title>Sample DekiScript Extension</title>

<description>This extension contains functions for adding picture effects.</description>

<uri.help>http://wiki.opengarden.org/Deki_Wiki/Extensions/Polaroid</uri.help>

<namespace>sample</namespace>

<function>

<name>instant</name>

<description>Add an instant picture effect (polaroid) with tilt to images.</description>

<return>

<html>

<head><script src="http://server/instant.js" type="text/javascript" /></head>

<body><img src="http://server/picture.png" class="instant ishadow33 icolorF0F4FF" />
</body>

<tail></tail>

</html>

</return>

</function>

</extension>

So far, our output is constant, which isn’t really interesting.  This is where DekiScript comes into play.  Instead, of returning a static document, we can use the same mechanism used by Deki Wiki to generate pages dynamically.  To make this work seamlessly, we take advantage of XML namespaces to mark parts of the document we wish to evaluate.

First, we need to declare the DekiScript namespace by adding xmlns:eval="http://mindtouch.com/2007/dekiscript" to the <html> element.  Next, we need to declare that our function takes four parameters: the image URI, shadow opacity, frame color, and tilt direction.  Finally, we need to replace the hard-coded values with DekiScript expressions.  To access the function arguments, we prefix their names with args.

Here is the final version of our sample extension:

<extension>

<title>Sample DekiScript Extension</title>

<namespace>sample</namespace>

<function>

<name>instant</name>

<description>Add an instant picture effect (polaroid) with tilt to images.</description>

<param name="image" type="uri">image uri</param>

<param name="shadowopacity" type="int" optional="true">shadow opacity in percent
(from 0 to 100; default: 33)</param>

<param name="framecolor" type="str" optional="true">frame color in hex
(from "000000" to "FFFFFF"; default: "F0F4FF")</param>

<param name="tilt" type="str" optional="true">tilt direction
(either "left", "none", or "right"; default: nil)</param>

<return>

<html xmlns:eval="http://mindtouch.com/2007/dekiscript">

<head><script src="http://server/instant.js" type="text/javascript" /></head>

<body>

<img

eval:src="args.image"

eval:class="'instant ishadow' .. (args.shadowopacity ?? 33) .. ' icolor' ..
(args.framecolor ?? 'F0F4FF') .. (args.tilt ? ' itilt' .. args.tilt : '')"

/>

</body>

<tail></tail>

</html>

</return>

</function>

</extension>

DekiScript allows you to evaluate attributes and elements.  When an attribute is evaluated, the attribute prefix is automatically stripped, and the attribute value becomes the result of the DekiScript expression.  For elements, it’s a little more varied.  There are three kinds of elements that can be evaluated: <eval:expr>, <eval:js>, and <eval:if>.  The first two are identical in execution, but the result is embedded in a different way.  The first uses the usual DekiScript embedding rules (just like for attributes), while the second converts the result to JavaScript notation (JSON), wich makes it really easy to embed DekiScript values such as lists or maps.  The third kind is a conditional element that prevents its inner elements from being embedded and evaluated unless the test condition succeeds.  All three forms replace the element with the outcome of the operation.  Let’s make this more concrete by looking at a couple of simple examples:

<eval:expr>"Hello"</eval:expr>
Hello
<eval:js>"Hello"</eval:js>
"Hello"
<eval:if test="true">Hello</eval:if><eval:if test="false">Bye</eval:if>
Hello

Last, but not least, we need to add our extension to Deki Wiki.  This is done in the usual manner.

  1. Go into the Control Panel
  2. Click on Service Management
  3. Click on “Local”
  4. Select “Extension”
  5. Enter a description for your service (like sample)
  6. Enter the DekiScript SID: http://services.mindtouch.com/deki/draft/2007/12/dekiscript
  7. Add the config the key manifest
  8. Set the value for the config key to the location of the XML extension file. The location can either be a disk path or a URI. (e.g. /root/sample.xml or c:filessample.xml or http://server/sample.xml)

That’s it!  You’re now ready to use the XML extension.

I’ve uploaded a couple of extensions already (AccuWeather and Scratch) to wet your appetite, but you can expect a lot more in the comming months.  The DekiScript service is included in Deki Wiki 1.8.3 RC2, which should go out tomorrow. Share your thoughts, suggestions, and questions on the forums.

8 Comments

  1. I realized after posting that the three examples I gave all have only one function defined. So, to dispel the false impression that only one function can be defined, I ported the existing Digg extension to XML as well. http://wiki.opengarden.org/Deki_Wiki/Extensions/D

  2. I realized after posting that the three examples I gave all have only one function defined. So, to dispel the false impression that only one function can be defined, I ported the existing Digg extension to XML as well. http://wiki.opengarden.org/Deki_Wiki/Extensions/D

  3. How is this available for your hosted Deki Wiki Pro customer?

  4. Currently we don't allow custom extensions for wik.is. If ti is an extension that is popular we can add it for everyone to use.

  5. Please do. Makes my Deki wiki site even more pretty. : )

Trackbacks for this post

  1. Writing My First Extension | MindTouch Blog
  2. Paypal Extension for Deki Wiki | MindTouch Blog
  3. New command line tool for testing DekiScript extensions | MindTouch, Inc Blog

Leave a Comment