Writing a DekiScript Extension

MindTouch Deki 1.8.3 includes the DekiScript service which provides an interface to run functions written in DekiScript. This makes it easier to write extensions for embedding widgets or using JavaScript APIs.  In addition to the information on this page, looking through the XML files in http://scripts.mindtouch.com/ can be a very useful resource for more advanced concepts and examples.

Getting started

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 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!

Defining a function with no parameters

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.developer.mindtouch.com/Deki/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 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.

Defining a function with parameters

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="num" 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>

Evaluating parameters for the script

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 four kinds of elements that can be evaluated: <eval:expr> , <eval:js>, <eval:if>, and <eval:for>.  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 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.  The fourth kind, added in 1.8.3b, iterates over lists and maps with an optional condition (by defaul all items are iterated over).  All four 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
<eval:for var="x" in="[1, 2, 3]" test="x % 2 == 1">odd </eval:for>
odd odd

Adding an XML extension to Deki

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

  1. Go into the Control Panel
  2. Click on System Settings
  3. Click Add Script
  4. Enter a description for your service (like sample)
  5. Set the value for the Manifest 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:\files\sample.xml or http://server/sample.xml)

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

Samples of XML extensions

The list of extensions written in DekiScript is growing quickly.  Check out the following XML extensions:

Tag page
You must login to post a comment.