Parsoid/JS

From mediawiki.org

This page documents Parsoid/JS, which was replaced by Parsoid/PHP in 2020.

See also:

Setting up VisualEditor[edit]

To set up your own Parsoid service follow the Parsoid installation instructions before setting up VisualEditor. Note that it can be particularly complicated to set up Parsoid and Node.js in non-standard systems, like those running Windows or Debian.

Below is the non-official compatibility matrix between the VisualEditor on some MediaWiki version and the Parsoid service. In general, if you're running into problems with installation, getting exactly matching versions (VisualEditor, Parsoid, and MediaWiki) should be one of the first things you try, even if this table says that a mismatched set will probably work.

Parsoid →
MediaWiki ↓
0.4.1 0.6.0 0.6.1 0.7.0 0.7.1 0.8.0 0.9.0
compat
0.9.0 0.9.0+ 0.10.0 0.11.0
1.34 X X
1.33 X X
1.32
1.31 - (d) - (d) X X X X X X
1.30 - (d) - (d) X X X X - (b) - (b)
1.29 X X X X X X - (b) - (b)
1.28 X X X X X X - (b) - (b)
1.27 X X X X X - - (b) - (b)
1.26 X X X X X - (c) - (c) -
1.25 - (a) -
1.24 -
1.23 -

Caption :

X = tested, working
- = tested, non-working

Notes :

(a) = non-compatible with 0.6.1 (phabricator:T100681)
(b) = non-compatible with 0.9.0 (mailarchive:wikitech-l/2018-March/089690.html); from the version after 0.9.0 (currently unreleased) there is no more compatibility mode
(c) = very partially, it is possible to add text but not to modify existing text
(d) = issues on images for Parsoid 0.6 + MW 1.30 and probably 1.31 also (Topic:Ufpghq2hidcj3d3w)
0.9 compat = either modified Parsoid code (see this blog) either a specific Parsoid configuration (see this topic)

Node.js and Parsoid compatibility Matrix[edit]

Parsoid →
Node.js↓
0.4.1 0.6.0 0.6.1 0.7.0 0.7.1 0.8.0 0.8.1 0.9.0 0.10.0 0.11.0
12
10 X X
8
6+ X

Linking with Parsoid[edit]

To get VisualEditor to talk to Parsoid, add the following code to your LocalSettings.php to specify your Parsoid instance:

$wgVirtualRestConfig['modules']['parsoid'] = array(
    // URL to the Parsoid instance
    // Use port 8142 if you use the Debian package
    'url' => 'http://localhost:8000',
    // Parsoid "domain", see below (optional)
    'domain' => 'localhost',
    // Parsoid "prefix", see below (optional)
    'prefix' => 'localhost'
);

A single Parsoid server can handle multiple wikis. The Parsoid domain setting identifies your wiki configuration to Parsoid. Whether you set domain explicitly or optionally accept the default value, the value from $wgVirtualRestConfig must match the value from Parsoid's config.yaml. By default it is set to the hostname named by $wgCanonicalServer, but you can pick an arbitrary string. Older versions of Parsoid also used a unique "prefix" to identify the server; you may need to list that here as well.

Parsoid must have been configured to match, for example with the following in Parsoid's config.yaml:

    mwApis:
        - # This is the only required parameter,
          # the URL of you MediaWiki API endpoint.
          uri: 'http://path/to/my/wiki/api.php'
          domain: 'localhost'
        - # and another MediaWiki
          uri: 'http://path/to/my/otherwiki/api.php'
          domain: 'uniqueidentifier'

If you are using Parsoid older than 0.6.0, you would use a line in Parsoid's localsettings.js like:

parsoidConfig.setMwApi({ uri: 'http://path/to/my/wiki/api.php', domain: 'localhost', prefix: 'localhost' });

Again, the "domain" property is optional in the Parsoid configuration; it defaults to the hostname used in the uri property if not specified. The "prefix" property can also be omitted unless you are running a very old version of Parsoid.

See Parsoid/Setup#Configuration for more details.

Servers with multiple virtual sites[edit]

If Apache2 is configured with multiple virtual sites, Parsoid is (in standard configuration) only able to access the default site. To check for this problem, run curl '[http://your-wiki-base-url]/api.php/' on the server.

If the response starts with:

<!DOCTYPE html><html lang="en-GB" dir="ltr" class="client-nojs"><head><meta charset="UTF-8" /><title>MediaWiki API help - ['''''Name of your wiki''''']</title>

then you don't have the problem, but if it doesn't, you may need to configure a host alias that Parsoid can use:

Look at the apache2 configuration file for the virtual server hosting the wiki, near the top of the file there should be a line like:

<VirtualHost *:80>

If the '*' is present, then the alias can be to localhost, if there is an IP address replacing the '*' then the alias must be to that IP address.

In the same file add a line:

ServerAlias my_wiki_alias

In the hosts file of the server (/etc/hosts on Ubuntu), add a route for my_wiki_alias, either for 127.0.0.1 (if the apache2 virtual server configuration had the '*' above, else to the IP address from the apache2 virtual server configuration.

Finally, in the Parsoid localsettings.js file, find the parsoidConfig.setMwApi setting, and set it to:

parsoidConfig.setMwApi({
  uri: 'http://my_wiki_alias:80/path-to-my-wiki/api.php',
  domain: '/* my Parsoid "domain" matching the value in LocalSettings.php */',
  prefix: '/* my Parsoid "prefix" matching the value in LocalSettings.php */'
});

Reload the network config, apache config, and Parsoid config, and retest the curl command above.

The same method works for multiple wikis hosted on multiple virtual servers on a host (use a different alias and add a parsoidConfig.setMwApi setting for each wiki).

Linking with Parsoid in private wikis[edit]
Warning Warning: All current options have significant, serious security implications. Think carefully before applying any of these hacks. The best option right now is to provide Parsoid over HTTPS. In the future this will be properly integrated with MediaWiki and special measures will not be needed.

Try one of these three options:

Forwarding cookies to Parsoid[edit]
Warning Warning: ONLY enable this on private wikis and ONLY IF you understand the SECURITY IMPLICATIONS of sending Cookie headers to Parsoid over HTTP! (but see the HTTPS section below)
// This feature requires a non-locking session store. The default session store will not work and
// will cause deadlocks (connection timeouts from Parsoid) when trying to use this feature. Only required for MediaWiki 1.26.x and earlier!
$wgSessionsInObjectCache = true;

// Forward users' Cookie: headers to Parsoid. Required for private wikis (login required to read).
// If the wiki is not private (i.e. $wgGroupPermissions['*']['read'] is true) this configuration
// variable will be ignored.
//
// WARNING: ONLY enable this on private wikis and ONLY IF you understand the SECURITY IMPLICATIONS
// of sending Cookie headers to Parsoid over HTTP. For security reasons, it is strongly recommended
// that $wgVirtualRestConfig['modules']['parsoid']['url'] be pointed to localhost if this setting is enabled.
$wgVirtualRestConfig['modules']['parsoid']['forwardCookies'] = true;
Authentication Bypass for Parsoid, without forwarding cookies[edit]

An alternative to the approach above is explicitly giving read permissions to requests from the parsoid server. There are two suggested solutions:

Note Note: Replace 127.0.0.1 in both example solutions with the IP address of the server that is running Parsoid. This should of course only be done if the Parsoid server is on a 'trusted' network.

1) Using the NetworkAuth extension

The forwarding of cookies (and the enabling of $wgSessionsInObjectCache and the forwardCookies property) can be avoided by adding a user (which may be called parsoid) to the wiki and then add the NetworkAuth extension to the wiki with the configuration in "LocalSettings.php" file:

require_once "$IP/extensions/NetworkAuth/NetworkAuth.php";
$wgNetworkAuthUsers[] = [
	'iprange' => [ '127.0.0.1' ],
	'user'    => 'parsoid'
];

Where the IP address matches that of the Parsoid server and the user matches the one you added to the wiki.

2) Bypass how permissions are set
Warning Warning: This will allow your private wiki to be readable over the Parsoid port. You should ensure that the Parsoid port is closed to outside traffic.

After your settings for $wgGroupPermissions add the following to your "LocalSettings.php":

if ( !isset( $_SERVER['REMOTE_ADDR'] ) OR $_SERVER['REMOTE_ADDR'] == '127.0.0.1'	) {
	$wgGroupPermissions['*']['read'] = true;
	$wgGroupPermissions['*']['edit'] = true;
}

Where the IP address matches that of the Parsoid server. Solution as mentioned in: explicitly remove restrictions for Parsoid by IP address.

Parsoid over HTTPS[edit]

By default, Parsoid only supports HTTP connections. However, it's easy to provide HTTPS Parsoid by using Stunnel, a utility which offers SSL wrapping for arbitrary sockets. Most Unix distributions have 'stunnel' or 'stunnel4' package available from the repository. First install stunnel:

sudo apt install stunnel

Then you need a config file for stunnel. It resides under /etc/stunnel/*.conf, so create it here with the editor you like, e.g. nano:

sudo nano /etc/stunnel/parsoid.conf

Give the file similar content like this:

cert = /etc/ssl/my_certs/parsoid.crt
key = /etc/ssl/my_keys/mykey.key
CAfile = /etc/ssl/my_ca/ca.crt

[parsoid]
accept  = 8143
connect = 8142

First you define the path to the ssl-keys used for your server. Then you give the service a name you like in brackets. It is only to know what this config shall do and to separate different configs in the same file. After the key accept you write the port number for the public incoming connection, which is ssl-ciphered. After the connect key write the intern port number, to which stunnel should route the traffic from the accept-port, but without ssl. At this port your parsoid-server is listen. If you use the Parsoid/Developer Setup use port number 8000, otherwise 8142 is standard port.

If you are using Let's Encrypt, you can use the following (replacing `<domain>` with the primary URL you have the certificate for):

cert = /etc/letsencrypt/live/<domain>/fullchain.pem
key = /etc/letsencrypt/live/<domain>/privkey.pem

[parsoid]
accept  = 8143
connect = 8142

This example use its own subdomain for parsoid and secured it with letsencrypt.

The stunnel config-file is ready now, but you need two more things to activate the configuration:

First enable stunnel to work after reboot. Therefore change 'ENABLED' to 1 in the file /etc/default/stunnel4

sudo nano /etc/default/stunnel4
ENABLED=1

Second, if you dont want to reboot now, you have to start the service. For Ubuntu 14.x use

sudo /etc/init.d/stunnel4 restart

For Ubuntu 16.x the command changed to

sudo systemctl restart stunnel4.service

To test configuration you can check in your browser, if the parsoid-server is answering over the ssl-connection. (e.g. write in the adress-line of your browser: 'https://parsoid.mydomain.com:8143'). If the answer is „Welcome to the Parsoid web service.“ then congratulation - you have successfull secured your parsoid installation. One step remaining: Once this is working, you have to use the appropriate URL (e.g. 'https://parsoid.mydomain.com:8143') in your MediaWiki configuration for VisualEditor. Note the change from http to https and the port-number you set under accept in stunnel-configuration-file.

If you do not like to create an extra subdomain for parsoid like here, you can also use an existing subdomain (e.g. [wiki] if it's listed in your .crt file and then the appropriate URL will become: https://wiki.mydomain.com:8143).

  • You cannot use this type of configuration with Parsoid accessible via 'localhost', because the certificate chain for localhost, which will almost certainly be self-signed, will fail validation. You must use a proper hostname for Parsoid server, with appropriately issued and signed SSL certificate.
  • You might enable SSL tunnels for stunnel. See e.g. for Debian /etc/default/stunnel4

Setting up such a configuration allows you to avoid the security implications of transmitting parsoid cookies in cleartext.

Producing and installing SSL certificates is beyond the scope of this document. Read more about stunnel:

Parsoid on Windows and other systems[edit]

It is particularly complicated and time consuming to set up VisualEditor with Parsoid in non-standard systems, like those running Windows or non-standard Linux - those difficulties might even prevent the successful installation of VisualEditor for some people on some platforms:

Setting VisualEditor up on shared hosting[edit]

See VisualEditor/Installation on a shared host

Running Parsoid tests[edit]

To run all parser tests and mocha tests:

$ npm test

The parser tests have quite a few options now which can be listed using node bin/parserTests.js --help. To run tests on the PHP port:

$ composer test

Converting simple wikitext[edit]

You can convert simple wikitext snippets from the command line using the parse.js script in the bin/ directory:

echo 'Foo' | node bin/parse.js

The parse script has a lot of options. node bin/parse.js --help gives you information about this.

(In Ubuntu 13 and 14, node has been renamed to nodejs. There, either type nodejs or create a symbolic link or equivalent.)