# App/Xtn/Scripting

From XOWA: the free, open-source, offline wiki application

XOWA allows custom scripts to run on XOWA pages

| Please note that this feature is still a work in progress. For the latest updates / usage notes, please check https://github.com/gnosygnu/xowa/issues/88

## Options

The options page is at Options/Scripting

## Background

- MediaWiki supports custom functions through an extension system. These extensions are generally written in PHP.
- XOWA supports the most important extensions used on Wikimedia wikis. In addition it also supports some extensions used on Wikia wikis. These XOWA extensions convert the PHP counterparts to Java.
- However, there are many extensions which are unsupported by XOWA

If you would like to have an extension supported directly by XOWA, please contact the developer through Help/Feedback. You can also hack the XOWA source to add your own extension in Java.

However, if you want a simpler approach, XOWA does allow an extension system by adding javascript / lua files

## Overview

The following process is involved:

- Enable Scripting globally at home/wiki/Options/Scripting
- Place a main script file at `/xowa/wiki/simple.wikipedia.org/bin/any/script/xowa.script.main.js`. See below for the contents of a main script file
- Place an extension script file at `/xowa/wiki/simple.wikipedia.org/bin/any/script/example.js/example.main.js`. See below for the contents of an extension script file
- Launch a page in the wiki and observe the effects

## Javascript

### xowa.script.main.js

    /*
      "xoscript__main" loads extensions

      XOWA always looks for a file called "/xowa/wiki/wiki_name/bin/any/script/xowa.script.main.js"
      * If it finds a file, it runs "xoscript__main"
      * lua can also be used. For example, "/xowa/wiki/wiki_name/bin/any/script/xowa.script.main.lua"
      * If both a .js and a .lua file exists, the behavior is non-deterministic. Currently, it will run both files, but this may change in the future
    */
    function xoscript__main(xo) {
      /*
        "reg_xtn" registers an extension. It takes 2 arguments:
        * "key": a string key that is used internally for differentiating extensions. It may be exposed externally later
        * "file": a file path to the extension's "main" file. See the "example.main.js" for what should go in a "main" file"
      */
      xo.reg_xtn("example.js" , "./example.js/example.main.js");
      xo.reg_xtn("example.lua", "./example.lua/example.main.lua");
    }

### example.main.js

    /*
      "xoscript__init" can load utility functions for later use in *this* script

      "xoscript__init" should always be present; if not used, leave it empty. for example:

      function xoscript__init(env) {}
    */
    function xoscript__init(env) {
        // load a utility script called "example.util.js"
        // This will add a function called "xo_uppercase" which will be used below in "xoscript__page_write_end"
        env.load_script("./example.util.js");
    }

    /*
      "xoscript__page_write_end" can change the page html before it is rendered
    */
    function xoscript__page_write_end(page)
    {
      /*
        add a <script> tag to the "tail" of the html document
        * "tail" is defined as the area between "</body>" and "</html>"
        * Specifically: '</body><script src="file:///xowa/wiki/simple.wikipedia.org/wiki/bin/any/script/example.js/example.include.js" type="text/javascript"></script></html>'

        Note that a <script> tag can be added to the "head" of the html document at the "bot" position
        * EX: 'page.doc().head().add_js_file("./example.include.js")'

        In this case, there are a few more details
        * "head" is defined as the area between "<head>" and "</head>"
        * the following positions can be specified within "<head>":
        ** "top": defined as "before" all XOWA scripts
        *** EX: 'page.doc().head().add_js_file("top", "./example.include.js")'
        ** "bot": defined as "after" all XOWA scripts. note that "bot" is the default when position is omitted
        *** EX: 'page.doc().head().add_js_file("bot", "./example.include.js")'
        ** "": defined as "default" which is the same as "bot"
      */
      page.doc().tail().add_js_file("./example.include.js");

      /*
        adds a <meta> tag to the <head> area.
        * Specifically: '<meta name="some_name" content="some_content"></meta>'

        For parameters:
        * the 1nd argument is the position; EX: "top", "bot", ""
        * the 2nd argument is the tag_name; EX: "meta" -> "<meta></meta>"
        * the 3rd argument is the innerText; EX: "some_text" -> "<meta>some_text</meta>"
        * the rest of the arguments are key-value pairs for the opening tag; EX: "k1", "v1", "k2", "v2" -> '<meta k1="v1" k2="v2"></meta>'

        Note that like "add_js_file"...
        * positions can be specified with "head" / "tail"
        * "top" / "bot" are also supported
      */
      page.doc().head().add_tag("", "meta", "", "name", "some_name", "content", "some_content");

      /*
        adds arbitrary html to the tail document
        * Specifically: '<I>USING A FUNCTION FROM EXAMPLE.UTIL.JS</I>'

        Note that this line also demonstrates calling utility scripts:
        * in this case "xo_uppercase" exists in "./example.util.js"
        * "./example.util.js" was loaded by "xoscript_init" above
      */
      page.doc().tail().add_html(xo_uppercase("<i>using a function from example.util.js</i><br/>"));

      /*
        Some other functions;

        // log a message to the XOWA log. The XOWA log is visible at home/wiki/Special:XowaSystemData?type=log_session
        xolog.log('some log message');

        // get the current wiki_name
        var wiki_name = page.url().wiki_name();   // returns "simple.wikipedia.org"

        // get the current page_name
        var page_name = page.url().page_name();   // returns the name of the current page; EX: "Earth"

        // get the current html
        var html = page.doc().html();

        // set the current html
        page.doc().html("some_html");

        // add js script
        page.doc().head().add_js_code("alert('some_alert')");

        // add a css_file
        page.doc().head().add_css_file("./example.include.css");

        // add css code
        page.doc().head().add_js_code("my_style {display:none;}");
        */
    }

### example.util.js

    function xo_uppercase(s) {
      return s.toUpperCase();
    }

### example.include.js

    var content = document.getElementById("content");
    var h1Elements = content.getElementsByTagName("h1");
    if ( h1Elements.length != 0 ) {
      var current =  h1Elements[0].innerHTML;
      h1Elements[0].innerHTML = current[0] + ' from include.js';
    }

## Lua

### example.main.lua

    function xoscript__init(env)
      env:load_script("./example.util.lua");
    end

    function xoscript__page_write_end(page)
      page:doc():tail():add_html("top", xo_uppercase("from lua"));
    end

### example.util.lua

    function xo_uppercase(s)
      return s:upper()
    end

### XOWA

- Main page
- Screenshots
- Video
- Download XOWA
- Download wikis

### Getting started

- Requirements
- Installation
- Simple Wikipedia
- English Wikipedia
- Other Wikipedias

### Android

- Setup
- Video

### Help

- About
- Contents
- Media
- Feedback

### Blog

- Current

### Links

- Wikimedia dumps
- XOWA @ archive.org
- English Wikipedia

### Donate

- archive.org
- Wikipedia
- XOWA