changeset 2245:87a0e2c73a25

Refactored njs documentation.
author Yaroslav Zhuravlev <yar@nginx.com>
date Mon, 24 Sep 2018 19:10:29 +0300
parents 467aef18bf12
children 32ba43abf9cd
files xml/en/GNUmakefile xml/en/docs/http/ngx_http_js_module.xml xml/en/docs/njs/cli.xml xml/en/docs/njs/compatibility.xml xml/en/docs/njs/examples.xml xml/en/docs/njs/index.xml xml/en/docs/njs/install.xml xml/en/docs/njs/njs_api.xml xml/en/docs/stream/ngx_stream_js_module.xml xml/index.xml xml/ru/GNUmakefile xml/ru/docs/http/ngx_http_js_module.xml xml/ru/docs/njs/cli.xml xml/ru/docs/njs/compatibility.xml xml/ru/docs/njs/examples.xml xml/ru/docs/njs/index.xml xml/ru/docs/stream/ngx_stream_js_module.xml
diffstat 17 files changed, 1727 insertions(+), 993 deletions(-) [+]
line wrap: on
line diff
--- a/xml/en/GNUmakefile
+++ b/xml/en/GNUmakefile
@@ -125,6 +125,10 @@ REFS =									\
 		njs/index						\
 		njs/njs_changes						\
 		njs/njs_api						\
+		njs/cli							\
+		njs/compatibility					\
+		njs/examples						\
+		njs/install						\
 
 TOP =									\
 		download						\
--- a/xml/en/docs/http/ngx_http_js_module.xml
+++ b/xml/en/docs/http/ngx_http_js_module.xml
@@ -9,21 +9,21 @@
 <module name="Module ngx_http_js_module"
         link="/en/docs/http/ngx_http_js_module.html"
         lang="en"
-        rev="16">
+        rev="17">
 
 <section id="summary">
 
 <para>
 The <literal>ngx_http_js_module</literal> module is used to implement
 location and variable handlers
-in <link doc="../njs/">njs</link> —
+in <link doc="../njs/index.xml">njs</link> —
 a subset of the JavaScript language.
 </para>
 
 <para>
 This module is not built by default.
 Download and install instructions are available
-<link doc="../njs/index.xml" id="install">here</link>.
+<link doc="../njs/install.xml">here</link>.
 </para>
 
 </section>
new file mode 100644
--- /dev/null
+++ b/xml/en/docs/njs/cli.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
+
+<article name="Command-line interface"
+        link="/en/docs/njs/cli.html"
+        lang="en"
+        rev="1">
+
+<section>
+<para>
+njs scripts development and debugging can be performed
+from the command-line.
+The command-line utility is available after the installation of
+the Linux <link doc="install.xml" id="install_package">package</link>
+or after building from the
+<link doc="install.xml" id="install_sources">sources</link>.
+Compared to njs running inside nginx,
+nginx objects
+(<link doc="njs_api.xml" id="http">HTTP</link> and
+<link doc="njs_api.xml" id="stream">Stream</link>)
+are not available in the utility.
+<example>
+$ echo "2**3" | njs -
+8
+
+$ njs
+>> var o = {a:[]}
+undefined
+
+>> JSON.stringify(o, undefined,1)
+{
+ "a": [
+
+ ]
+}
+>>
+</example>
+</para>
+
+</section>
+
+</article>
new file mode 100644
--- /dev/null
+++ b/xml/en/docs/njs/compatibility.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
+
+<article name="Compatibility"
+        link="/en/docs/njs/compatibility.html"
+        lang="en"
+        rev="1">
+
+<section>
+
+<para>
+njs is created in compliance with
+<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link>
+(strict mode) with some
+<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link>
+and later extensions.
+The compliance is still evolving.
+</para>
+
+</section>
+
+
+<section id="supported" name="What is currently supported">
+
+<para>
+<list type="bullet">
+
+<listitem>
+Boolean values, numbers, strings, objects, arrays,
+functions, and regular expressions
+</listitem>
+
+<listitem>
+ES5.1 operators, ES7 exponentiation operators
+</listitem>
+
+<listitem>
+ES5.1 statements: <literal>var</literal>, <literal>if</literal>,
+<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>,
+<literal>for in</literal>, <literal>while</literal>,
+<literal>do while</literal>, <literal>break</literal>,
+<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>,
+<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal>
+</listitem>
+
+<listitem>
+ES6 <literal>Number</literal> and
+<literal>Math</literal> properties and methods
+</listitem>
+
+<listitem>
+<literal>String</literal> methods:
+<list type="bullet">
+
+<listitem>
+ES5.1:
+<literal>fromCharCode</literal>, <literal>concat</literal>,
+<literal>slice</literal>, <literal>substring</literal>,
+<literal>substr</literal>, <literal>charAt</literal>,
+<literal>charCodeAt</literal>, <literal>indexOf</literal>,
+<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>,
+<literal>toUpperCase</literal>, <literal>trim</literal>,
+<literal>search</literal>, <literal>match</literal>, <literal>split</literal>,
+<literal>replace</literal>
+</listitem>
+
+<listitem>
+ES6:
+<literal>fromCodePoint</literal>, <literal>codePointAt</literal>,
+<literal>includes</literal>, <literal>startsWith</literal>,
+<literal>endsWith</literal>, <literal>repeat</literal>
+</listitem>
+
+<listitem>
+non-standard:
+<literal>bytesFrom</literal> (0.2.3)
+<literal>fromUTF8</literal>, <literal>toUTF8</literal>,
+<literal>fromBytes</literal>, <literal>toBytes</literal>
+</listitem>
+</list>
+
+</listitem>
+
+<listitem>
+<literal>Object</literal> methods:
+<list type="bullet">
+<listitem>
+ES5.1:
+<literal>create</literal> (support without properties list),
+<literal>keys</literal>,
+<literal>defineProperty</literal>,
+<literal>defineProperties</literal>,
+<literal>getOwnPropertyDescriptor</literal>,
+<literal>getPrototypeOf</literal>,
+<literal>hasOwnProperty</literal>,
+<literal>isPrototypeOf</literal>,
+<literal>preventExtensions</literal>,
+<literal>isExtensible</literal>,
+<literal>freeze</literal>,
+<literal>isFrozen</literal>,
+<literal>seal</literal>,
+<literal>isSealed</literal>
+</listitem>
+</list>
+
+</listitem>
+
+<listitem>
+<literal>Array</literal> methods:
+<list type="bullet">
+<listitem>
+ES5.1:
+<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>,
+<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>,
+<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>,
+<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>,
+<literal>lastIndexOf</literal>, <literal>forEach</literal>,
+<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>,
+<literal>map</literal>, <literal>reduce</literal>,
+<literal>reduceRight</literal>
+</listitem>
+
+<listitem>
+ES6:
+<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>,
+<literal>findIndex</literal>
+</listitem>
+
+<listitem>
+ES7: <literal>includes</literal>
+</listitem>
+</list>
+
+</listitem>
+
+<listitem>
+ES5.1 <literal>Function</literal> methods:
+<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal>
+</listitem>
+
+<listitem>
+ES5.1 <literal>RegExp</literal> methods:
+<literal>test</literal>, <literal>exec</literal>
+</listitem>
+
+<listitem>
+ES5.1 <literal>Date</literal> methods
+</listitem>
+
+<listitem>
+ES5.1 <literal>JSON</literal> object
+</listitem>
+
+<listitem>
+ES5.1 global functions:
+<literal>isFinite</literal>, <literal>isNaN</literal>,
+<literal>parseFloat</literal>, <literal>parseInt</literal>,
+<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>,
+<literal>encodeURI</literal>, <literal>encodeURIComponent</literal>
+</listitem>
+
+<listitem>
+<literal>Error</literal> objects:
+<literal>Error</literal>, <literal>EvalError</literal>,
+<literal>InternalError</literal>, <literal>RangeError</literal>,
+<literal>ReferenceError</literal>, <literal>SyntaxError</literal>,
+<literal>TypeError</literal>, <literal>URIError</literal>
+</listitem>
+
+<listitem>
+<literal>setTimeout()</literal> and <literal>clearTimeout()</literal> functions
+(0.2.0)
+</listitem>
+
+<listitem>
+<link url="https://nodejs.org/api/fs.html#fs_file_system">Node.js style</link>
+<literal>File system</literal> methods:
+<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>,
+<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>,
+<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal>
+</listitem>
+
+<listitem>
+<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">Node.js style</link>
+<literal>Crypto</literal> methods (0.2.0):
+<literal>crypto.createHash</literal>,
+<literal>crypto.createHmac</literal>
+
+</listitem>
+
+</list>
+</para>
+
+</section>
+
+
+<section id="not_supported" name="What is not supported yet">
+
+<para>
+<list type="bullet">
+
+<listitem>
+ES6 <literal>let</literal> and <literal>const</literal> declarations
+</listitem>
+
+<listitem>
+labels
+</listitem>
+
+<listitem>
+<literal>arguments</literal> array
+</listitem>
+
+<listitem>
+<literal>eval</literal> function
+</listitem>
+
+<listitem>
+<literal>new Function()</literal> constructor
+</listitem>
+
+<listitem>
+<literal>setInterval</literal>,
+<literal>setImmediate</literal> functions
+</listitem>
+
+<listitem>
+non-integer fractions (<literal>.235</literal>)
+</listitem>
+
+</list>
+</para>
+
+</section>
+
+</article>
+
new file mode 100644
--- /dev/null
+++ b/xml/en/docs/njs/examples.xml
@@ -0,0 +1,438 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
+
+<article name="Examples"
+        link="/en/docs/njs/examples.html"
+        lang="en"
+        rev="1">
+
+<section id="helloword" name="Hello World">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+load_module modules/ngx_http_js_module.so;
+
+events {}
+
+http {
+    js_include hello_world.js;
+
+    server {
+        listen 8000;
+
+        location / {
+            js_content hello;
+        }
+    }
+}
+
+</example>
+</para>
+
+<para>
+<literal>hello_world.js</literal>:
+<example>
+function hello(r) {
+    r.return(200, “Hello world!”);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="urldecode" name="URL Decoding">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include urldecode.js;
+
+js_set $decoded_foo decoded_foo;
+</example>
+</para>
+
+<para>
+<path>urldecode.js</path>:
+<example>
+function decoded_foo(r) {
+    return decodeURIComponent(r.args.foo);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="urlencode" name="URL Encoding">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include urlencode.js;
+
+js_set $encoded_foo encoded_foo;
+...
+
+location / {
+    proxy_pass http://example.com?foo=$encoded_foo;
+}
+</example>
+</para>
+
+<para>
+<path>urlencode.js</path>:
+<example>
+function encoded_foo(r) {
+    return encodeURIComponent('foo &amp; bar?');
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="redirect" name="Internal Redirect">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include redirect.js;
+
+location /redirect {
+    js_content redirect;
+}
+
+location @named {
+    return 200 named;
+}
+</example>
+</para>
+
+<para>
+<path>redirect.js</path>:
+<example>
+function redirect(r) {
+    r.internalRedirect('@named');
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="fast_response" name="Returning Fastest Response from Proxy">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include fastresponse.js;
+
+location /start {
+    js_content content;
+}
+
+location /foo {
+    proxy_pass http://backend1;
+}
+
+location /bar {
+    proxy_pass http://backend2;
+}
+</example>
+</para>
+
+<para>
+<path>fastresponse.js</path>:
+<example>
+function content(r) {
+    var n = 0;
+
+    function done(res) {
+        if (n++ == 0) {
+            r.return(res.status, res.responseBody);
+        }
+    }
+
+    r.subrequest('/foo', r.variables.args, done);
+    r.subrequest('/bar', r.variables.args, done);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="jwt" name="Creating HS JWT">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include hs_jwt.js;
+
+js_set $jwt jwt;
+</example>
+</para>
+
+<para>
+<path>hs_jwt.js</path>:
+<example>
+function create_hs256_jwt(claims, key, valid) {
+    var header = { "typ" : "JWT", "alg" : "HS256", "exp" : Date.now() + valid };
+
+    var s = JSON.stringify(header).toBytes().toString('base64url') + '.'
+            + JSON.stringify(claims).toBytes().toString('base64url');
+
+    var h = require('crypto').createHmac('sha256', key);
+
+    return s + '.' + h.update(s).digest().toString('base64url');
+}
+
+function jwt(r) {
+    var claims = {
+        "iss" : "nginx",
+        "sub" : "alice",
+        "foo" : 123,
+        "bar" : "qq",
+        "zyx" : false
+    };
+
+    return create_hs256_jwt(claims, 'foo', 600);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="subrequest" name="Accessing API from a Subrequest">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include subrequest.js;
+
+keyval_zone zone=foo:10m;
+...
+
+location /keyval {
+    js_content set_keyval;
+}
+
+location /version {
+    js_content version;
+}
+
+location /api {
+    api write=on;
+}
+</example>
+</para>
+
+<para>
+<path>subrequest.js</path>:
+<example>
+function set_keyval(r) {
+    r.subrequest('/api/3/http/keyvals/foo',
+        { method: 'POST',
+          body: JSON.stringify({ foo: 789, bar: "ss dd 00" })},
+
+        function(res) {
+            if (res.status >= 300) {
+                r.return(res.status, res.responseBody);
+                return;
+            }
+            r.return(500);
+        });
+}
+
+function version(r) {
+    r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) {
+        if (res.status != 200) {
+            r.return(res.status);
+            return;
+        }
+
+        var json = JSON.parse(res.responseBody);
+        r.return(200, json.version);
+    });
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="secure_link" name="Creating secure_link Hash">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include hash.js;
+
+js_set $new_foo create_secure_link;
+...
+
+location / {
+    secure_link $cookie_foo;
+    secure_link_md5 "$uri mykey";
+    ...
+}
+
+location @login {
+    add_header Set-Cookie "foo=$new_foo; Max-Age=60";
+    return 302 /;
+}
+</example>
+</para>
+
+<para>
+<path>hash.js</path>:
+<example>
+function create_secure_link(r) {
+    return require('crypto').createHash('md5')
+                            .update(r.uri).update(" mykey")
+                            .digest('base64url');
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="legacy" name="Legacy Examples">
+
+<section id="legacy_stream" name="Injecting HTTP header using stream proxy">
+
+<para>
+Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+stream configuration
+<link doc="../stream/ngx_stream_js_module.xml" id="example">example</link>
+has been changed.
+For njs <link doc="../njs/njs_changes.xml" id="njs0.2.3">0.2.3</link>
+and earlier, use this configuration example:
+<example>
+load_module modules/ngx_stream_js_module.so;
+...
+
+stream {
+    js_include stream.js;
+
+    js_set $foo foo;
+    js_set $bar bar;
+
+    server {
+        listen 12345;
+
+        js_preread qux;
+        return     $foo;
+    }
+
+    server {
+        listen 12346;
+
+        js_access  xyz;
+        proxy_pass 127.0.0.1:8000;
+        js_filter  baz;
+    }
+}
+
+http {
+    server {
+        listen 8000;
+        location / {
+            return 200 $http_foo\n;
+        }
+    }
+}
+</example>
+</para>
+
+<para>
+The <path>stream.js</path> file:
+<example>
+var req = '';
+var matched = 0;
+var line = '';
+
+function qux(s) {
+    var n = s.buffer.indexOf('\n');
+    if (n == -1) {
+        return s.AGAIN;
+    }
+
+    line = s.buffer.substr(0, n);
+}
+
+function foo(s) {
+    return line;
+}
+
+function bar(s) {
+    var v = s.variables;
+    s.log("hello from bar() handler!");
+    return "foo-var" + v.remote_port + "; pid=" + v.pid;
+}
+
+// The filter processes one buffer per call.
+// The buffer is available in s.buffer both for
+// reading and writing.  Called for both directions.
+
+function baz(s) {
+    if (s.fromUpstream || matched) {
+        return;
+    }
+
+    // Disable certain addresses.
+
+    if (s.remoteAddress.match('^192.*')) {
+        return s.ERROR;
+    }
+
+    // Read HTTP request line.
+    // Collect bytes in 'req' until request
+    // line is read.  Clear current buffer to
+    // disable output.
+
+    req = req + s.buffer;
+    s.buffer = '';
+
+    var n = req.search('\n');
+
+    if (n != -1) {
+        // Inject a new HTTP header.
+        var rest = req.substr(n + 1);
+        req = req.substr(0, n + 1);
+
+        var addr = s.remoteAddress;
+
+        s.log('req:' + req);
+        s.log('rest:' + rest);
+
+        // Output the result and skip further
+        // processing.
+
+        s.buffer = req + 'Foo: addr_' + addr + '\r\n' + rest;
+        matched = 1;
+    }
+}
+
+function xyz(s) {
+    if (s.remoteAddress.match('^192.*')) {
+        return s.ABORT;
+    }
+}
+</example>
+</para>
+
+</section>
+
+</section>
+
+</article>
--- a/xml/en/docs/njs/index.xml
+++ b/xml/en/docs/njs/index.xml
@@ -9,192 +9,52 @@
 <article name="njs scripting language"
         link="/en/docs/njs/index.html"
         lang="en"
-        rev="23">
-
-<section id="summary">
+        rev="24"
+        toc="no">
 
-<para>
-njs is a subset of the JavaScript language that allows
-implementing location and variable handlers in
-<link doc="../http/ngx_http_js_module.xml">http</link> and
-<link doc="../stream/ngx_stream_js_module.xml">stream</link>.
-njs is created in compliance with
-<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link>
-(strict mode) with some
-<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link>
-extensions.
-The compliance is still evolving.
-</para>
-
-</section>
-
-
-<section id="supported" name="What is currently supported">
+<section id="links">
 
 <para>
 <list type="bullet">
 
 <listitem>
-Boolean values, numbers, strings, objects, arrays,
-functions, and regular expressions
-</listitem>
-
-<listitem>
-ES5.1 operators, ES7 exponentiation operators
-</listitem>
-
-<listitem>
-ES5.1 statements: <literal>var</literal>, <literal>if</literal>,
-<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>,
-<literal>for in</literal>, <literal>while</literal>,
-<literal>do while</literal>, <literal>break</literal>,
-<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>,
-<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal>
-</listitem>
-
-<listitem>
-ES6 <literal>Number</literal> and
-<literal>Math</literal> properties and methods
-</listitem>
-
-<listitem>
-<literal>String</literal> methods:
-<list type="bullet">
-
-<listitem>
-ES5.1:
-<literal>fromCharCode</literal>, <literal>concat</literal>,
-<literal>slice</literal>, <literal>substring</literal>,
-<literal>substr</literal>, <literal>charAt</literal>,
-<literal>charCodeAt</literal>, <literal>indexOf</literal>,
-<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>,
-<literal>toUpperCase</literal>, <literal>trim</literal>,
-<literal>search</literal>, <literal>match</literal>, <literal>split</literal>,
-<literal>replace</literal>
+<link doc="install.xml"/>
 </listitem>
 
 <listitem>
-ES6:
-<literal>fromCodePoint</literal>, <literal>codePointAt</literal>,
-<literal>includes</literal>, <literal>startsWith</literal>,
-<literal>endsWith</literal>, <literal>repeat</literal>
-</listitem>
-
-<listitem>
-non-standard:
-<literal>bytesFrom</literal> (0.2.3)
-<literal>fromUTF8</literal>, <literal>toUTF8</literal>,
-<literal>fromBytes</literal>, <literal>toBytes</literal>
-</listitem>
-</list>
-
+<link doc="njs_changes.xml"/>
 </listitem>
 
 <listitem>
-<literal>Object</literal> methods:
-<list type="bullet">
+<link doc="njs_api.xml"/>
+</listitem>
+
 <listitem>
-ES5.1:
-<literal>create</literal> (support without properties list),
-<literal>keys</literal>,
-<literal>defineProperty</literal>,
-<literal>defineProperties</literal>,
-<literal>getOwnPropertyDescriptor</literal>,
-<literal>getPrototypeOf</literal>,
-<literal>hasOwnProperty</literal>,
-<literal>isPrototypeOf</literal>,
-<literal>preventExtensions</literal>,
-<literal>isExtensible</literal>,
-<literal>freeze</literal>,
-<literal>isFrozen</literal>,
-<literal>seal</literal>,
-<literal>isSealed</literal>
-</listitem>
-</list>
-
+<link doc="examples.xml"/>
 </listitem>
 
 <listitem>
-<literal>Array</literal> methods:
-<list type="bullet">
-<listitem>
-ES5.1:
-<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>,
-<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>,
-<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>,
-<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>,
-<literal>lastIndexOf</literal>, <literal>forEach</literal>,
-<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>,
-<literal>map</literal>, <literal>reduce</literal>,
-<literal>reduceRight</literal>
-</listitem>
-
-<listitem>
-ES6:
-<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>,
-<literal>findIndex</literal>
-</listitem>
-
-<listitem>
-ES7: <literal>includes</literal>
-</listitem>
-</list>
-
-</listitem>
-
-<listitem>
-ES5.1 <literal>Function</literal> methods:
-<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal>
-</listitem>
-
-<listitem>
-ES5.1 <literal>RegExp</literal> methods:
-<literal>test</literal>, <literal>exec</literal>
+<link doc="compatibility.xml"/>
 </listitem>
 
 <listitem>
-ES5.1 <literal>Date</literal> methods
-</listitem>
-
-<listitem>
-ES5.1 <literal>JSON</literal> object
+<link doc="cli.xml"/>
 </listitem>
 
+</list>
+</para>
+
+<para>
+<list type="bullet">
+
 <listitem>
-ES5.1 global functions:
-<literal>isFinite</literal>, <literal>isNaN</literal>,
-<literal>parseFloat</literal>, <literal>parseInt</literal>,
-<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>,
-<literal>encodeURI</literal>, <literal>encodeURIComponent</literal>
+<link doc="../http/ngx_http_js_module.xml">
+ngx_http_js_module</link>
 </listitem>
 
 <listitem>
-<literal>Error</literal> objects:
-<literal>Error</literal>, <literal>EvalError</literal>,
-<literal>InternalError</literal>, <literal>RangeError</literal>,
-<literal>ReferenceError</literal>, <literal>SyntaxError</literal>,
-<literal>TypeError</literal>, <literal>URIError</literal>
-</listitem>
-
-<listitem>
-<literal>setTimeout()</literal> and <literal>clearTimeout()</literal> functions
-(0.2.0)
-</listitem>
-
-<listitem>
-<link url="https://nodejs.org/api/fs.html#fs_file_system">Node.js style</link>
-<literal>File system</literal> methods:
-<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>,
-<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>,
-<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal>
-</listitem>
-
-<listitem>
-<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">Node.js style</link>
-<literal>Crypto</literal> methods (0.2.0):
-<literal>crypto.createHash</literal>,
-<literal>crypto.createHmac</literal>
-
+<link doc="../stream/ngx_stream_js_module.xml">
+ngx_stream_js_module</link>
 </listitem>
 
 </list>
@@ -203,171 +63,107 @@ ES5.1 global functions:
 </section>
 
 
-<section id="not_supported" name="What is not supported yet">
+<section id="summary">
+
+<para>
+njs is a subset of the JavaScript language that allows
+extending nginx functionality.
+njs is created in compliance with
+<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link>
+(strict mode) with some
+<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link>
+and later extensions.
+The compliance is still <link doc="compatibility.xml">evolving</link>.
+</para>
+
+</section>
+
+
+<section id="usecases" name="Use cases">
 
 <para>
 <list type="bullet">
 
 <listitem>
-ES6 <literal>let</literal> and <literal>const</literal> declarations
-</listitem>
-
-<listitem>
-labels
-</listitem>
-
-<listitem>
-<literal>arguments</literal> array
+Complex access control and security checks in njs
+before a request reaches an upstream server
 </listitem>
 
 <listitem>
-<literal>eval</literal> function
-</listitem>
-
-<listitem>
-<literal>new Function()</literal> constructor
+Manipulating response headers
 </listitem>
 
 <listitem>
-<literal>setInterval</literal>,
-<literal>setImmediate</literal> functions
-</listitem>
-
-<listitem>
-non-integer fractions (<literal>.235</literal>)
+Writing flexible asynchronous content handlers and filters
 </listitem>
 
 </list>
+See <link doc="examples.xml">examples</link> and
+<link url="https://www.nginx.com/blog/tag/nginscript/">blog posts</link>
+for more njs use cases.
 </para>
 
 </section>
 
 
-<section id="changelog" name="Change Log">
+<section id="example" name="Basic HTTP Example">
 
 <para>
-The complete list of njs changes is available
-<link doc="njs_changes.xml">here</link>.
-</para>
-</section>
-
-
-<section id="njs_api" name="njs API Reference">
-
-<para>
-njs API reference is available
-<link doc="njs_api.xml">here</link>.
-</para>
-</section>
-
-
-<section id="install" name="Download and install">
-
-<para>
-njs is available in two modules:
+To use njs in nginx:
 <list type="bullet">
 
 <listitem>
-<link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link>
+<para>
+<link doc="install.xml">install</link> njs scripting language
+</para>
+</listitem>
+
+<listitem id="hello_world">
+<para>
+create an njs script file, for example, <path>hello_world.js</path>.
+See <link doc="njs_api.xml">Reference</link>
+for the list of njs properties and methods.
+<example>
+function hello(r) {
+    r.return(200, “Hello world!”);
+}
+</example>
+</para>
 </listitem>
 
 <listitem>
-<link doc="../stream/ngx_stream_js_module.xml">ngx_stream_js_module</link>
-</listitem>
 
-</list>
-Both modules are not built by default,
-they should be either compiled from the sources
-or installed as a Linux package.
-In addition, the Linux package provides
-njs command-line <link id="cli">utility</link>.
-</para>
+<para>
+in the <path>nginx.conf</path> file, enable
+<link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link> module
+and specify the
+<link doc="../http/ngx_http_js_module.xml" id="js_include">js_include</link>
+directive
+with the <path>hello_world.js</path> script file:
+<example>
+load_module modules/ngx_http_js_module.so;
 
+events {}
 
-<section id="install_package" name="Installing as a Linux package">
-<para>
-For Linux, njs modules
-<link doc="../../linux_packages.xml" id="dynmodules">packages</link> can be used:
-<list type="bullet">
+http {
+    js_include hello_world.js;
+
+    server {
+        listen 8000;
 
-<listitem>
-<literal>nginx-module-njs</literal> — njs
-<link doc="../ngx_core_module.xml" id="load_module">dynamic</link> modules
-</listitem>
+        location / {
+            js_content hello;
+        }
+    }
+}
 
-<listitem>
-<literal>nginx-module-njs-dbg</literal> — debug symbols for the
-<literal>nginx-module-njs</literal> package
+</example>
+</para>
 </listitem>
 
 </list>
-</para>
-
-</section>
-
-
-<section id="install_sources" name="Building from the sources">
-
-<para>
-The <link url="http://hg.nginx.org/njs">repository</link>
-with njs sources can be cloned with the following command:
-(requires <link url="https://www.mercurial-scm.org">Mercurial</link> client):
-<example>
-hg clone http://hg.nginx.org/njs
-</example>
-Then the modules should be compiled using the
-<literal>--add-module</literal> configuration parameter:
-<example>
-./configure --add-module=<value>path-to-njs</value>/nginx
-</example>
-The modules can also be built as
-<link doc="../ngx_core_module.xml" id="load_module">dynamic</link>:
-<example>
-./configure --add-dynamic-module=<value>path-to-njs</value>/nginx
-</example>
-</para>
-
-<para>
-To build only njs command-line <link id="cli">utility</link>, run
-<literal>./configure</literal> and <literal>make njs</literal> commands
-from njs root directory.
-The utility is available as <literal>./build/njs</literal>.
-</para>
-
-</section>
-
-</section>
-
-
-<section id="cli" name="Command-line interface">
-
-<para>
-njs scripts development and debugging can be performed
-from the command-line.
-The command-line utility is available after the installation of
-the Linux <link id="install_package">package</link>
-or after building from the <link id="install_sources">sources</link>.
-Compared to njs running inside nginx,
-nginx objects
-(<link doc="njs_api.xml" id="http">HTTP</link> and
-<link doc="njs_api.xml" id="stream">Stream</link>)
-are not available in the utility.
-<example>
-$ echo "2**3" | njs -
-8
-
-$ njs
->> var o = {a:[]}
-undefined
-
->> JSON.stringify(o, undefined,1)
-{
- "a": [
-
- ]
-}
->>
-</example>
+There is also a standalone <link doc="cli.xml">command line</link> utility
+that can be used independently of nginx for njs development and debugging.
 </para>
 
 </section>
new file mode 100644
--- /dev/null
+++ b/xml/en/docs/njs/install.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
+
+<article name="Download and install"
+        link="/en/docs/njs/install.html"
+        lang="en"
+        rev="1">
+
+<section id="install_package" name="Installing as a Linux package">
+
+<para>
+For Linux, njs modules
+<link doc="../../linux_packages.xml" id="dynmodules">packages</link> can be used:
+<list type="bullet">
+
+<listitem>
+<literal>nginx-module-njs</literal> — njs
+<link doc="../ngx_core_module.xml" id="load_module">dynamic</link> modules
+</listitem>
+
+<listitem>
+<literal>nginx-module-njs-dbg</literal> — debug symbols for the
+<literal>nginx-module-njs</literal> package
+</listitem>
+
+</list>
+</para>
+
+</section>
+
+
+<section id="install_sources" name="Building from the sources">
+
+<para>
+The <link url="http://hg.nginx.org/njs">repository</link>
+with njs sources can be cloned with the following command:
+(requires <link url="https://www.mercurial-scm.org">Mercurial</link> client):
+<example>
+hg clone http://hg.nginx.org/njs
+</example>
+Then the modules should be compiled using the
+<literal>--add-module</literal> configuration parameter:
+<example>
+./configure --add-module=<value>path-to-njs</value>/nginx
+</example>
+The modules can also be built as
+<link doc="../ngx_core_module.xml" id="load_module">dynamic</link>:
+<example>
+./configure --add-dynamic-module=<value>path-to-njs</value>/nginx
+</example>
+</para>
+
+<para>
+To build only njs command-line <link doc="cli.xml">utility</link>, run
+<literal>./configure</literal> and <literal>make njs</literal> commands
+from njs root directory.
+The utility is available as <literal>./build/njs</literal>.
+</para>
+
+</section>
+
+</article>
--- a/xml/en/docs/njs/njs_api.xml
+++ b/xml/en/docs/njs/njs_api.xml
@@ -9,7 +9,7 @@
 <article name="njs API"
         link="/en/docs/njs/njs_api.html"
         lang="en"
-        rev="7">
+        rev="8">
 
 <section id="summary">
 
@@ -1278,391 +1278,4 @@ the <link id="s_allow">s.allow()</link> 
 </section>
 
 
-<section id="example" name="Examples">
-
-
-<section id="example_urldecode" name="URL Decoding">
-
-<para>
-<example>
-js_include urldecode.js;
-
-js_set $decoded_foo decoded_foo;
-</example>
-</para>
-
-<para>
-The <path>urldecode.js</path> file:
-<example>
-function decoded_foo(r) {
-    return decodeURIComponent(r.args.foo);
-}
-</example>
-</para>
-
-</section>
-
-
-<section id="example_urlencode" name="URL Encoding">
-
-<para>
-<example>
-js_include urlencode.js;
-
-js_set $encoded_foo encoded_foo;
-...
-
-location / {
-    proxy_pass http://example.com?foo=$encoded_foo;
-}
-</example>
-</para>
-
-<para>
-The <path>urlencode.js</path> file:
-<example>
-function encoded_foo(r) {
-    return encodeURIComponent('foo &amp; bar?');
-}
-</example>
-</para>
-
-</section>
-
-
-<section id="example_internal_redirect" name="Internal Redirect">
-
-<para>
-<example>
-js_include redirect.js;
-
-location /redirect {
-    js_content redirect;
-}
-
-location @named {
-    return 200 named;
-}
-</example>
-</para>
-
-<para>
-The <path>redirect.js</path> file:
-<example>
-function redirect(r) {
-    r.internalRedirect('@named');
-}
-</example>
-</para>
-
-</section>
-
-
-<section id="example_fast_response" name="Returning Fastest Response from Proxy">
-
-<para>
-<example>
-js_include fastresponse.js;
-
-location /start {
-    js_content content;
-}
-
-location /foo {
-    proxy_pass http://backend1;
-}
-
-location /bar {
-    proxy_pass http://backend2;
-}
-</example>
-</para>
-
-<para>
-The <path>fastresponse.js</path> file:
-<example>
-function content(r) {
-    var n = 0;
-
-    function done(res) {
-        if (n++ == 0) {
-            r.return(res.status, res.responseBody);
-        }
-    }
-
-    r.subrequest('/foo', r.variables.args, done);
-    r.subrequest('/bar', r.variables.args, done);
-}
-</example>
-</para>
-
-</section>
-
-
-<section id="example_jwt" name="Creating HS JWT">
-
-<para>
-<example>
-js_include hs_jwt.js;
-
-js_set $jwt jwt;
-</example>
-</para>
-
-<para>
-The <path>hs_jwt.js</path> file:
-<example>
-function create_hs256_jwt(claims, key, valid) {
-    var header = { "typ" : "JWT", "alg" : "HS256", "exp" : Date.now() + valid };
-
-    var s = JSON.stringify(header).toBytes().toString('base64url') + '.'
-            + JSON.stringify(claims).toBytes().toString('base64url');
-
-    var h = require('crypto').createHmac('sha256', key);
-
-    return s + '.' + h.update(s).digest().toString('base64url');
-}
-
-function jwt(r) {
-    var claims = {
-        "iss" : "nginx",
-        "sub" : "alice",
-        "foo" : 123,
-        "bar" : "qq",
-        "zyx" : false
-    };
-
-    return create_hs256_jwt(claims, 'foo', 600);
-}
-</example>
-</para>
-
-</section>
-
-
-<section id="example_subrequest" name="Accessing API from a Subrequest">
-
-<para>
-<example>
-js_include subrequest.js;
-
-keyval_zone zone=foo:10m;
-...
-
-location /keyval {
-    js_content set_keyval;
-}
-
-location /version {
-    js_content version;
-}
-
-location /api {
-    api write=on;
-}
-</example>
-</para>
-
-<para>
-The <path>subrequest.js</path> file:
-<example>
-function set_keyval(r) {
-    r.subrequest('/api/3/http/keyvals/foo',
-        { method: 'POST',
-          body: JSON.stringify({ foo: 789, bar: "ss dd 00" })},
-
-        function(res) {
-            if (res.status >= 300) {
-                r.return(res.status, res.responseBody);
-                return;
-            }
-            r.return(500);
-        });
-}
-
-function version(r) {
-    r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) {
-        if (res.status != 200) {
-            r.return(res.status);
-            return;
-        }
-
-        var json = JSON.parse(res.responseBody);
-        r.return(200, json.version);
-    });
-}
-</example>
-</para>
-
-</section>
-
-
-<section id="example_secure_link" name="Creating secure_link Hash">
-
-<para>
-<example>
-js_include hash.js;
-
-js_set $new_foo create_secure_link;
-...
-
-location / {
-    secure_link $cookie_foo;
-    secure_link_md5 "$uri mykey";
-    ...
-}
-
-location @login {
-    add_header Set-Cookie "foo=$new_foo; Max-Age=60";
-    return 302 /;
-}
-</example>
-</para>
-
-<para>
-The <path>hash.js</path> file:
-<example>
-function create_secure_link(r) {
-    return require('crypto').createHash('md5')
-                            .update(r.uri).update(" mykey")
-                            .digest('base64url');
-}
-</example>
-</para>
-
-</section>
-
-
-<section id="example_legacy" name="Legacy Examples">
-
-
-<section id="example_legacy_stream" name="Stream Example">
-
-<para>
-Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
-stream configuration
-<link doc="../stream/ngx_stream_js_module.xml" id="example">example</link>
-has been changed.
-For njs <link doc="../njs/njs_changes.xml" id="njs-0.2.3">0.2.3</link>
-and earlier, use this configuration example:
-<example>
-load_module modules/ngx_stream_js_module.so;
-...
-
-stream {
-    js_include stream.js;
-
-    js_set $foo foo;
-    js_set $bar bar;
-
-    server {
-        listen 12345;
-
-        js_preread qux;
-        return     $foo;
-    }
-
-    server {
-        listen 12346;
-
-        js_access  xyz;
-        proxy_pass 127.0.0.1:8000;
-        js_filter  baz;
-    }
-}
-
-http {
-    server {
-        listen 8000;
-        location / {
-            return 200 $http_foo\n;
-        }
-    }
-}
-</example>
-</para>
-
-<para>
-The <path>stream.js</path> file:
-<example>
-var req = '';
-var matched = 0;
-var line = '';
-
-function qux(s) {
-    var n = s.buffer.indexOf('\n');
-    if (n == -1) {
-        return s.AGAIN;
-    }
-
-    line = s.buffer.substr(0, n);
-}
-
-function foo(s) {
-    return line;
-}
-
-function bar(s) {
-    var v = s.variables;
-    s.log("hello from bar() handler!");
-    return "foo-var" + v.remote_port + "; pid=" + v.pid;
-}
-
-// The filter processes one buffer per call.
-// The buffer is available in s.buffer both for
-// reading and writing.  Called for both directions.
-
-function baz(s) {
-    if (s.fromUpstream || matched) {
-        return;
-    }
-
-    // Disable certain addresses.
-
-    if (s.remoteAddress.match('^192.*')) {
-        return s.ERROR;
-    }
-
-    // Read HTTP request line.
-    // Collect bytes in 'req' until request
-    // line is read.  Clear current buffer to
-    // disable output.
-
-    req = req + s.buffer;
-    s.buffer = '';
-
-    var n = req.search('\n');
-
-    if (n != -1) {
-        // Inject a new HTTP header.
-        var rest = req.substr(n + 1);
-        req = req.substr(0, n + 1);
-
-        var addr = s.remoteAddress;
-
-        s.log('req:' + req);
-        s.log('rest:' + rest);
-
-        // Output the result and skip further
-        // processing.
-
-        s.buffer = req + 'Foo: addr_' + addr + '\r\n' + rest;
-        matched = 1;
-    }
-}
-
-function xyz(s) {
-    if (s.remoteAddress.match('^192.*')) {
-        return s.ABORT;
-    }
-}
-</example>
-</para>
-
-</section>
-
-</section>
-
-</section>
-
 </article>
--- a/xml/en/docs/stream/ngx_stream_js_module.xml
+++ b/xml/en/docs/stream/ngx_stream_js_module.xml
@@ -9,20 +9,20 @@
 <module name="Module ngx_stream_js_module"
         link="/en/docs/stream/ngx_stream_js_module.html"
         lang="en"
-        rev="14">
+        rev="15">
 
 <section id="summary">
 
 <para>
 The <literal>ngx_stream_js_module</literal> module is used to implement
-handlers in <link doc="../njs/">njs</link> —
+handlers in <link doc="../njs/index.xml">njs</link> —
 a subset of the JavaScript language.
 </para>
 
 <para>
 This module is not built by default.
 Download and install instructions are available
-<link doc="../njs/index.xml" id="install">here</link>.
+<link doc="../njs/install.xml">here</link>.
 </para>
 
 </section>
@@ -36,7 +36,7 @@ This example is valid for
 njs <link doc="../njs/njs_changes.xml" id="njs-0.2.4">0.2.4</link>.
 For njs <link doc="../njs/njs_changes.xml" id="njs-0.2.3">0.2.3</link>
 and earlier, use
-<link doc="../njs/njs_api.xml" id="example_legacy">this</link> example.
+<link doc="../njs/examples.xml" id="legacy">this</link> example.
 </note>
 <example>
 load_module modules/ngx_stream_js_module.so;
--- a/xml/index.xml
+++ b/xml/index.xml
@@ -34,7 +34,7 @@ support and control API</link> for TLS c
 
 <event date="2018-09-18">
 <para>
-<link doc="en/docs/njs/">njs-0.2.4</link>
+<link doc="en/docs/njs/index.xml">njs-0.2.4</link>
 version has been released, featuring
 <link doc="en/docs/njs/njs_api.xml" id="s_on">s.on()</link>,
 <link doc="en/docs/njs/njs_api.xml" id="s_off">s.off()</link>,
@@ -56,7 +56,7 @@ mainline version has been released.
 
 <event date="2018-07-31">
 <para>
-<link doc="en/docs/njs/">njs-0.2.3</link>
+<link doc="en/docs/njs/index.xml">njs-0.2.3</link>
 version has been released, featuring
 <link doc="en/docs/njs/njs_api.xml" id="string_bytesfrom">String.bytesFrom()</link>,
 <link doc="en/docs/njs/njs_api.xml" id="string_padstart">String.padStart()</link>,
@@ -93,7 +93,7 @@ balancing method</link>.
 
 <event date="2018-06-19">
 <para>
-<link doc="en/docs/njs/">njs-0.2.2</link>
+<link doc="en/docs/njs/index.xml">njs-0.2.2</link>
 version has been released, featuring HTTP
 <link doc="en/docs/njs/njs_api.xml" id="r_internal_redirect">internalRedirect()</link>
 method support
@@ -119,7 +119,7 @@ mainline version has been released.
 
 <event date="2018-05-31">
 <para>
-<link doc="en/docs/njs/">njs-0.2.1</link>
+<link doc="en/docs/njs/index.xml">njs-0.2.1</link>
 version has been
 <link doc="en/docs/njs/njs_changes.xml" id="njs0.2.1">released</link>.
 </para>
@@ -178,7 +178,7 @@ mainline version has been released.
 
 <event date="2018-04-03">
 <para>
-<link doc="en/docs/njs/">njs-0.2.0</link>
+<link doc="en/docs/njs/index.xml">njs-0.2.0</link>
 version has been released, featuring HTTP
 <link doc="en/docs/njs/njs_api.xml" id="subrequest">subrequest()</link>
 method support
--- a/xml/ru/GNUmakefile
+++ b/xml/ru/GNUmakefile
@@ -108,6 +108,10 @@ REFS =									\
 		ngx_google_perftools_module				\
 		njs/index						\
 		njs/njs_api						\
+		njs/cli							\
+		njs/compatibility					\
+		njs/examples						\
+		njs/install						\
 
 TOP =									\
 		download						\
--- a/xml/ru/docs/http/ngx_http_js_module.xml
+++ b/xml/ru/docs/http/ngx_http_js_module.xml
@@ -9,21 +9,21 @@
 <module name="Модуль ngx_http_js_module"
         link="/ru/docs/http/ngx_http_js_module.html"
         lang="ru"
-        rev="16">
+        rev="17">
 
 <section id="summary">
 
 <para>
 Модуль <literal>ngx_http_js_module</literal> позволяет задавать
 обработчики location и переменных
-на <link doc="../njs/">njs</link> —
+на <link doc="../njs/index.xml">njs</link> —
 подмножестве языка JavaScript.
 </para>
 
 <para>
 По умолчанию этот модуль не собирается.
 Инструкция по сборке и установке доступны
-<link doc="../njs/index.xml" id="install">здесь</link>.
+<link doc="../njs/install.xml">здесь</link>.
 </para>
 
 </section>
new file mode 100644
--- /dev/null
+++ b/xml/ru/docs/njs/cli.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
+
+<article name="Интерфейс командной строки"
+        link="/ru/docs/njs/cli.html"
+        lang="ru"
+        rev="1">
+
+<section>
+<para>
+Создание и отладка njs-скриптов может осуществляться
+в командной строке.
+Утилита командной строки доступна после установки
+<link doc="install.xml" id="install_package">пакета</link> Linux
+или после сборки из
+<link doc="install.xml" id="install_sources">исходных файлов</link>.
+В отличие от njs, запущенном внутри nginx,
+в утилите недоступны объекты nginx
+(<link doc="njs_api.xml" id="http">HTTP</link> и
+<link doc="njs_api.xml" id="stream">Stream</link>).
+<example>
+$ echo "2**3" | njs -
+8
+
+$ njs
+>> var o = {a:[]}
+undefined
+
+>> JSON.stringify(o, undefined,1)
+{
+ "a": [
+
+ ]
+}
+>>
+</example>
+</para>
+
+</section>
+
+</article>
new file mode 100644
--- /dev/null
+++ b/xml/ru/docs/njs/compatibility.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
+
+<article name="Совместимость"
+        link="/ru/docs/njs/compatibility.html"
+        lang="ru"
+        rev="1">
+
+<section>
+
+<para>
+njs совместим с
+<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link>
+(строгий режим) c некоторыми расширениями
+<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link>
+и позже.
+Совместимость находится в стадии развития.
+</para>
+
+</section>
+
+
+<section id="supported" name="Готовая функциональность">
+
+<para>
+<list type="bullet">
+
+<listitem>
+Логические значения, числа, строки, объекты, массивы,
+функции и регулярные выражения
+</listitem>
+
+<listitem>
+ES5.1 операторы, ES7 операторы возведения в степень
+</listitem>
+
+<listitem>
+ES5.1 инструкции: <literal>var</literal>, <literal>if</literal>,
+<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>,
+<literal>for in</literal>, <literal>while</literal>,
+<literal>do while</literal>, <literal>break</literal>,
+<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>,
+<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal>
+</listitem>
+
+<listitem>
+ES6 методы и свойства <literal>Number</literal> и
+<literal>Math</literal>
+</listitem>
+
+<listitem>
+Методы <literal>String</literal>:
+<list type="bullet">
+
+<listitem>
+ES5.1:
+<literal>fromCharCode</literal>, <literal>concat</literal>,
+<literal>slice</literal>, <literal>substring</literal>,
+<literal>substr</literal>, <literal>charAt</literal>,
+<literal>charCodeAt</literal>, <literal>indexOf</literal>,
+<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>,
+<literal>toUpperCase</literal>, <literal>trim</literal>,
+<literal>search</literal>, <literal>match</literal>, <literal>split</literal>,
+<literal>replace</literal>
+</listitem>
+
+<listitem>
+ES6:
+<literal>fromCodePoint</literal>, <literal>codePointAt</literal>,
+<literal>includes</literal>, <literal>startsWith</literal>,
+<literal>endsWith</literal>, <literal>repeat</literal>
+</listitem>
+
+<listitem>
+нестандартные:
+<literal>bytesFrom</literal> (0.2.3),
+<literal>fromUTF8</literal>, <literal>toUTF8</literal>,
+<literal>fromBytes</literal>, <literal>toBytes</literal>
+</listitem>
+</list>
+
+</listitem>
+
+<listitem>
+Методы <literal>Object</literal>:
+<list type="bullet">
+<listitem>
+ES5.1:
+<literal>create</literal> (поддержка без списка свойств),
+<literal>keys</literal>,
+<literal>defineProperty</literal>,
+<literal>defineProperties</literal>,
+<literal>getOwnPropertyDescriptor</literal>,
+<literal>getPrototypeOf</literal>,
+<literal>hasOwnProperty</literal>,
+<literal>isPrototypeOf</literal>,
+<literal>preventExtensions</literal>,
+<literal>isExtensible</literal>,
+<literal>freeze</literal>,
+<literal>isFrozen</literal>,
+<literal>seal</literal>,
+<literal>isSealed</literal>
+</listitem>
+</list>
+
+</listitem>
+
+<listitem>
+Методы <literal>Array</literal>:
+<list type="bullet">
+<listitem>
+ES5.1:
+<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>,
+<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>,
+<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>,
+<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>,
+<literal>lastIndexOf</literal>, <literal>forEach</literal>,
+<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>,
+<literal>map</literal>, <literal>reduce</literal>,
+<literal>reduceRight</literal>
+</listitem>
+
+<listitem>
+ES6:
+<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>,
+<literal>findIndex</literal>
+</listitem>
+
+<listitem>
+ES7: <literal>includes</literal>
+</listitem>
+</list>
+
+</listitem>
+
+<listitem>
+ES5.1 методы <literal>Function</literal>:
+<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal>
+</listitem>
+
+<listitem>
+ES5.1 методы <literal>RegExp</literal>:
+<literal>test</literal>, <literal>exec</literal>
+</listitem>
+
+<listitem>
+ES5.1 методы <literal>Date</literal>
+</listitem>
+
+<listitem>
+ES5.1 объект <literal>JSON</literal>
+</listitem>
+
+<listitem>
+ES5.1 глобальные функции:
+<literal>isFinite</literal>, <literal>isNaN</literal>,
+<literal>parseFloat</literal>, <literal>parseInt</literal>,
+<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>,
+<literal>encodeURI</literal>, <literal>encodeURIComponent</literal>
+</listitem>
+
+<listitem>
+Объекты <literal>Error</literal>:
+<literal>Error</literal>, <literal>EvalError</literal>,
+<literal>InternalError</literal>, <literal>RangeError</literal>,
+<literal>ReferenceError</literal>, <literal>SyntaxError</literal>,
+<literal>TypeError</literal>, <literal>URIError</literal>
+</listitem>
+
+<listitem>
+Функции <literal>setTimeout()</literal> и <literal>clearTimeout()</literal>
+(0.2.0)
+</listitem>
+
+<listitem>
+Методы <literal>File system</literal>
+<link url="https://nodejs.org/api/fs.html#fs_file_system">стиль Node.js</link>:
+<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>,
+<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>,
+<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal>
+</listitem>
+
+<listitem>
+Методы <literal>Crypto</literal>
+<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">стиль Node.js</link>
+(0.2.0):
+<literal>crypto.createHash</literal>,
+<literal>crypto.createHmac</literal>
+</listitem>
+
+</list>
+</para>
+
+</section>
+
+
+<section id="not_supported" name="Функциональность в разработке">
+
+<para>
+<list type="bullet">
+
+<listitem>
+ES6 объявления <literal>let</literal> и <literal>const</literal>
+</listitem>
+
+<listitem>
+labels
+</listitem>
+
+<listitem>
+массив <literal>arguments</literal>
+</listitem>
+
+<listitem>
+функция <literal>eval</literal>
+</listitem>
+
+<listitem>
+конструктор <literal>new Function()</literal>
+</listitem>
+
+<listitem>
+функции <literal>setInterval</literal>,
+<literal>setImmediate</literal>
+</listitem>
+
+<listitem>
+дроби без целой части (<literal>.235</literal>)
+</listitem>
+
+</list>
+</para>
+
+</section>
+
+</article>
+
new file mode 100644
--- /dev/null
+++ b/xml/ru/docs/njs/examples.xml
@@ -0,0 +1,438 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
+
+<article name="Примеры использования"
+        link="/ru/docs/njs/examples.html"
+        lang="ru"
+        rev="1">
+
+<section id="helloword" name="Hello World">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+load_module modules/ngx_http_js_module.so;
+
+events {}
+
+http {
+    js_include hello_world.js;
+
+    server {
+        listen 8000;
+
+        location / {
+            js_content hello;
+        }
+    }
+}
+
+</example>
+</para>
+
+<para>
+<literal>hello_world.js</literal>:
+<example>
+function hello(r) {
+    r.return(200, “Hello world!”);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="urldecode" name="Декодирование URL">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include urldecode.js;
+
+js_set $decoded_foo decoded_foo;
+</example>
+</para>
+
+<para>
+<path>urldecode.js</path>:
+<example>
+function decoded_foo(r) {
+    return decodeURIComponent(r.args.foo);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="urlencode" name="Кодирование URL">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include urlencode.js;
+
+js_set $encoded_foo encoded_foo;
+...
+
+location / {
+    proxy_pass http://example.com?foo=$encoded_foo;
+}
+</example>
+</para>
+
+<para>
+<path>urlencode.js</path>:
+<example>
+function encoded_foo(r) {
+    return encodeURIComponent('foo &amp; bar?');
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="redirect" name="Внутренняя переадресация">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include redirect.js;
+
+location /redirect {
+    js_content redirect;
+}
+
+location @named {
+    return 200 named;
+}
+</example>
+</para>
+
+<para>
+<path>redirect.js</path>:
+<example>
+function redirect(r) {
+    r.internalRedirect('@named');
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="fast_response" name="Возвращение самого быстрого ответа от прокси">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include fastresponse.js;
+
+location /start {
+    js_content content;
+}
+
+location /foo {
+    proxy_pass http://backend1;
+}
+
+location /bar {
+    proxy_pass http://backend2;
+}
+</example>
+</para>
+
+<para>
+<path>fastresponse.js</path>:
+<example>
+function content(r) {
+    var n = 0;
+
+    function done(res) {
+        if (n++ == 0) {
+            r.return(res.status, res.responseBody);
+        }
+    }
+
+    r.subrequest('/foo', r.variables.args, done);
+    r.subrequest('/bar', r.variables.args, done);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="jwt" name="Создание HS JWT">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include hs_jwt.js;
+
+js_set $jwt jwt;
+</example>
+</para>
+
+<para>
+<path>hs_jwt.js</path>:
+<example>
+function create_hs256_jwt(claims, key, valid) {
+    var header = { "typ" : "JWT", "alg" : "HS256", "exp" : Date.now() + valid };
+
+    var s = JSON.stringify(header).toBytes().toString('base64url') + '.'
+            + JSON.stringify(claims).toBytes().toString('base64url');
+
+    var h = require('crypto').createHmac('sha256', key);
+
+    return s + '.' + h.update(s).digest().toString('base64url');
+}
+
+function jwt(r) {
+    var claims = {
+        "iss" : "nginx",
+        "sub" : "alice",
+        "foo" : 123,
+        "bar" : "qq",
+        "zyx" : false
+    };
+
+    return create_hs256_jwt(claims, 'foo', 600);
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="subrequest" name="Доступ к API из подзапроса">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include subrequest.js;
+
+keyval_zone zone=foo:10m;
+...
+
+location /keyval {
+    js_content set_keyval;
+}
+
+location /version {
+    js_content version;
+}
+
+location /api {
+    api write=on;
+}
+</example>
+</para>
+
+<para>
+<path>subrequest.js</path>:
+<example>
+function set_keyval(r) {
+    r.subrequest('/api/3/http/keyvals/foo',
+        { method: 'POST',
+          body: JSON.stringify({ foo: 789, bar: "ss dd 00" })},
+
+        function(res) {
+            if (res.status >= 300) {
+                r.return(res.status, res.responseBody);
+                return;
+            }
+            r.return(500);
+        });
+}
+
+function version(r) {
+    r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) {
+        if (res.status != 200) {
+            r.return(res.status);
+            return;
+        }
+
+        var json = JSON.parse(res.responseBody);
+        r.return(200, json.version);
+    });
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="secure_link" name="Создание secure_link хэша">
+
+<para>
+<path>nginx.conf</path>:
+<example>
+js_include hash.js;
+
+js_set $new_foo create_secure_link;
+...
+
+location / {
+    secure_link $cookie_foo;
+    secure_link_md5 "$uri mykey";
+    ...
+}
+
+location @login {
+    add_header Set-Cookie "foo=$new_foo; Max-Age=60";
+    return 302 /;
+}
+</example>
+</para>
+
+<para>
+<path>hash.js</path>:
+<example>
+function create_secure_link(r) {
+    return require('crypto').createHash('md5')
+                            .update(r.uri).update(" mykey")
+                            .digest('base64url');
+}
+</example>
+</para>
+
+</section>
+
+
+<section id="legacy" name="Устаревшие примеры">
+
+<section id="legacy_stream" name="Внедрение HTTP-заголовка при помощи stream proxy">
+
+<para>
+Начиная с версии njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>
+<link doc="../stream/ngx_stream_js_module.xml" id="example">пример</link>
+конфигурации в stream
+был изменён.
+Для njs <link doc="../njs/njs_changes.xml" id="njs0.2.3">0.2.3</link>
+и более ранних версий необходимо использовать следующий пример конфигурации:
+<example>
+load_module modules/ngx_stream_js_module.so;
+...
+
+stream {
+    js_include stream.js;
+
+    js_set $foo foo;
+    js_set $bar bar;
+
+    server {
+        listen 12345;
+
+        js_preread qux;
+        return     $foo;
+    }
+
+    server {
+        listen 12346;
+
+        js_access  xyz;
+        proxy_pass 127.0.0.1:8000;
+        js_filter  baz;
+    }
+}
+
+http {
+    server {
+        listen 8000;
+        location / {
+            return 200 $http_foo\n;
+        }
+    }
+}
+</example>
+</para>
+
+<para>
+Файл <path>stream.js</path>:
+<example>
+var req = '';
+var matched = 0;
+var line = '';
+
+function qux(s) {
+    var n = s.buffer.indexOf('\n');
+    if (n == -1) {
+        return s.AGAIN;
+    }
+
+    line = s.buffer.substr(0, n);
+}
+
+function foo(s) {
+    return line;
+}
+
+function bar(s) {
+    var v = s.variables;
+    s.log("hello from bar() handler!");
+    return "foo-var" + v.remote_port + "; pid=" + v.pid;
+}
+
+// Фильтр обрабатывает один буфер за вызов.
+// Буфер недоступен в s.buffer для
+// чтения и записи.  Вызывается в обоих направлениях.
+
+function baz(s) {
+    if (s.fromUpstream || matched) {
+        return;
+    }
+
+    // Отключение определённых адресов.
+
+    if (s.remoteAddress.match('^192.*')) {
+        return s.ERROR;
+    }
+
+    // Чтение строки HTTP-запроса.
+    // Получение байт в 'req' до того как
+    // будет прочитана строка запроса.  Очистка текущего буфера
+    // для отключения вывода.
+
+    req = req + s.buffer;
+    s.buffer = '';
+
+    var n = req.search('\n');
+
+    if (n != -1) {
+        // Inject a new HTTP header.
+        var rest = req.substr(n + 1);
+        req = req.substr(0, n + 1);
+
+        var addr = s.remoteAddress;
+
+        s.log('req:' + req);
+        s.log('rest:' + rest);
+
+        // Вывод результата и пропуск дальнейшей
+        // обработки.
+
+        s.buffer = req + 'Foo: addr_' + addr + '\r\n' + rest;
+        matched = 1;
+    }
+}
+
+function xyz(s) {
+    if (s.remoteAddress.match('^192.*')) {
+        return s.ABORT;
+    }
+}
+</example>
+</para>
+
+</section>
+
+</section>
+
+</article>
--- a/xml/ru/docs/njs/index.xml
+++ b/xml/ru/docs/njs/index.xml
@@ -9,191 +9,52 @@
 <article name="Сценарный язык njs"
         link="/ru/docs/njs/index.html"
         lang="ru"
-        rev="23">
-
-<section id="summary">
+        rev="24"
+        toc="no">
 
-<para>
-njs - это подмножество языка JavaScript, который позволяет
-задавать обработчики location и переменных в
-<link doc="../http/ngx_http_js_module.xml">http</link> и
-<link doc="../stream/ngx_stream_js_module.xml">stream</link>.
-njs совместим с
-<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link>
-(строгий режим) c некоторыми расширениями
-<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link>.
-Совместимость находится в стадии развития.
-</para>
-
-</section>
-
-
-<section id="supported" name="Готовая функциональность">
+<section id="links">
 
 <para>
 <list type="bullet">
 
 <listitem>
-Логические значения, числа, строки, объекты, массивы,
-функции и регулярные выражения
-</listitem>
-
-<listitem>
-ES5.1 операторы, ES7 операторы возведения в степень
-</listitem>
-
-<listitem>
-ES5.1 инструкции: <literal>var</literal>, <literal>if</literal>,
-<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>,
-<literal>for in</literal>, <literal>while</literal>,
-<literal>do while</literal>, <literal>break</literal>,
-<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>,
-<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal>
-</listitem>
-
-<listitem>
-ES6 методы и свойства <literal>Number</literal> и
-<literal>Math</literal>
-</listitem>
-
-<listitem>
-Методы <literal>String</literal>:
-<list type="bullet">
-
-<listitem>
-ES5.1:
-<literal>fromCharCode</literal>, <literal>concat</literal>,
-<literal>slice</literal>, <literal>substring</literal>,
-<literal>substr</literal>, <literal>charAt</literal>,
-<literal>charCodeAt</literal>, <literal>indexOf</literal>,
-<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>,
-<literal>toUpperCase</literal>, <literal>trim</literal>,
-<literal>search</literal>, <literal>match</literal>, <literal>split</literal>,
-<literal>replace</literal>
+<link doc="install.xml"/>
 </listitem>
 
 <listitem>
-ES6:
-<literal>fromCodePoint</literal>, <literal>codePointAt</literal>,
-<literal>includes</literal>, <literal>startsWith</literal>,
-<literal>endsWith</literal>, <literal>repeat</literal>
-</listitem>
-
-<listitem>
-нестандартные:
-<literal>bytesFrom</literal> (0.2.3),
-<literal>fromUTF8</literal>, <literal>toUTF8</literal>,
-<literal>fromBytes</literal>, <literal>toBytes</literal>
-</listitem>
-</list>
-
+<link doc="njs_changes.xml">Изменения в njs</link>
 </listitem>
 
 <listitem>
-Методы <literal>Object</literal>:
-<list type="bullet">
+<link doc="njs_api.xml"/>
+</listitem>
+
 <listitem>
-ES5.1:
-<literal>create</literal> (поддержка без списка свойств),
-<literal>keys</literal>,
-<literal>defineProperty</literal>,
-<literal>defineProperties</literal>,
-<literal>getOwnPropertyDescriptor</literal>,
-<literal>getPrototypeOf</literal>,
-<literal>hasOwnProperty</literal>,
-<literal>isPrototypeOf</literal>,
-<literal>preventExtensions</literal>,
-<literal>isExtensible</literal>,
-<literal>freeze</literal>,
-<literal>isFrozen</literal>,
-<literal>seal</literal>,
-<literal>isSealed</literal>
-</listitem>
-</list>
-
+<link doc="examples.xml"/>
 </listitem>
 
 <listitem>
-Методы <literal>Array</literal>:
-<list type="bullet">
-<listitem>
-ES5.1:
-<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>,
-<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>,
-<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>,
-<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>,
-<literal>lastIndexOf</literal>, <literal>forEach</literal>,
-<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>,
-<literal>map</literal>, <literal>reduce</literal>,
-<literal>reduceRight</literal>
-</listitem>
-
-<listitem>
-ES6:
-<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>,
-<literal>findIndex</literal>
-</listitem>
-
-<listitem>
-ES7: <literal>includes</literal>
-</listitem>
-</list>
-
-</listitem>
-
-<listitem>
-ES5.1 методы <literal>Function</literal>:
-<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal>
-</listitem>
-
-<listitem>
-ES5.1 методы <literal>RegExp</literal>:
-<literal>test</literal>, <literal>exec</literal>
+<link doc="compatibility.xml"/>
 </listitem>
 
 <listitem>
-ES5.1 методы <literal>Date</literal>
-</listitem>
-
-<listitem>
-ES5.1 объект <literal>JSON</literal>
+<link doc="cli.xml"/>
 </listitem>
 
+</list>
+</para>
+
+<para>
+<list type="bullet">
+
 <listitem>
-ES5.1 глобальные функции:
-<literal>isFinite</literal>, <literal>isNaN</literal>,
-<literal>parseFloat</literal>, <literal>parseInt</literal>,
-<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>,
-<literal>encodeURI</literal>, <literal>encodeURIComponent</literal>
+<link doc="../http/ngx_http_js_module.xml">
+ngx_http_js_module</link>
 </listitem>
 
 <listitem>
-Объекты <literal>Error</literal>:
-<literal>Error</literal>, <literal>EvalError</literal>,
-<literal>InternalError</literal>, <literal>RangeError</literal>,
-<literal>ReferenceError</literal>, <literal>SyntaxError</literal>,
-<literal>TypeError</literal>, <literal>URIError</literal>
-</listitem>
-
-<listitem>
-Функции <literal>setTimeout()</literal> и <literal>clearTimeout()</literal>
-(0.2.0)
-</listitem>
-
-<listitem>
-Методы <literal>File system</literal>
-<link url="https://nodejs.org/api/fs.html#fs_file_system">стиль Node.js</link>:
-<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>,
-<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>,
-<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal>
-</listitem>
-
-<listitem>
-Методы <literal>Crypto</literal>
-<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">стиль Node.js</link>
-(0.2.0):
-<literal>crypto.createHash</literal>,
-<literal>crypto.createHmac</literal>
+<link doc="../stream/ngx_stream_js_module.xml">
+ngx_stream_js_module</link>
 </listitem>
 
 </list>
@@ -202,173 +63,109 @@ ES5.1 глобальные функции:
 </section>
 
 
-<section id="not_supported" name="Функциональность в разработке">
+<section id="summary">
+
+<para>
+njs - это подмножество языка JavaScript, позволяющее
+расширить функциональность nginx.
+njs совместим с
+<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link>
+(строгий режим) c некоторыми расширениями
+<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link>
+и позже.
+Совместимость находится в стадии
+<link doc="compatibility.xml">развития</link>.
+</para>
+
+</section>
+
+
+<section id="usecases" name="Сценарии использования">
 
 <para>
 <list type="bullet">
 
 <listitem>
-ES6 объявления <literal>let</literal> и <literal>const</literal>
-</listitem>
-
-<listitem>
-labels
-</listitem>
-
-<listitem>
-массив <literal>arguments</literal>
+Комплексное управление доступом и проверка защиты при помощи njs
+до получения запроса сервером группы
 </listitem>
 
 <listitem>
-функция <literal>eval</literal>
-</listitem>
-
-<listitem>
-конструктор <literal>new Function()</literal>
+Управление заголовками ответа
 </listitem>
 
 <listitem>
-функции <literal>setInterval</literal>,
-<literal>setImmediate</literal>
-</listitem>
-
-<listitem>
-дроби без целой части (<literal>.235</literal>)
+Создание гибких асинхронных обработчиков содержимого и фильтров
 </listitem>
 
 </list>
+Подробнее о сценариях использования
+см. в <link doc="examples.xml">примерах</link>
+и <link url="https://www.nginx.com/blog/tag/nginscript/">блогпостах</link>.
 </para>
 
 </section>
 
 
-<section id="changelog" name="История изменений">
-
-<para>
-Полная история изменений njs доступна
-<link doc="njs_changes.xml">здесь</link>.
-</para>
-</section>
-
-<section id="njs_api" name="Справочник njs API">
+<section id="example" name="Базовый пример HTTP">
 
 <para>
-Справочник njs API доступен
-<link doc="njs_api.xml">здесь</link>.
-</para>
-</section>
-
-
-<section id="install" name="Загрузка и установка">
-
-<para>
-njs доступен в двух модулях:
+Чтобы использовать njs в nginx, необходимо:
 <list type="bullet">
 
 <listitem>
-<link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link>
+<para>
+<link doc="install.xml">установить</link> njs
+</para>
+</listitem>
+
+<listitem id="hello_world">
+<para>
+создать файл сценария njs, например <path>hello_world.js</path>.
+Описание свойств и методов языка njs
+см. в <link doc="njs_api.xml">справочнике</link>.
+<example>
+function hello(r) {
+    r.return(200, “Hello world!”);
+}
+</example>
+</para>
 </listitem>
 
 <listitem>
-<link doc="../stream/ngx_stream_js_module.xml">ngx_stream_js_module</link>
+
+<para>
+в файле <path>nginx.conf</path> включить
+модуль <link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link>
+и указать директиву
+<link doc="../http/ngx_http_js_module.xml" id="js_include">js_include</link>
+с файлом сценария <path>hello_world.js</path>:
+<example>
+load_module modules/ngx_http_js_module.so;
+
+events {}
+
+http {
+    js_include hello_world.js;
+
+    server {
+        listen 8000;
+
+        location / {
+            js_content hello;
+        }
+    }
+}
+
+</example>
+</para>
 </listitem>
 
 </list>
-По умолчанию модули не собираются
-их необходимо собрать из исходного кода
-или установить из отдельного пакета Linux.
-Кроме того, в пакете Linux предоставляется
-<link id="cli">утилита</link> командной строки njs.
-</para>
-
-
-<section id="install_package" name="Установка пакета Linux">
-<para>
-Для установки модулей njs на Linux могут быть использованы
-<link doc="../../linux_packages.xml" id="dynmodules">пакеты</link>:
-<list type="bullet">
-
-<listitem>
-<literal>nginx-module-njs</literal> —
-<link doc="../ngx_core_module.xml" id="load_module">динамические</link> модули
-njs
-</listitem>
-
-<listitem>
-<literal>nginx-module-njs-dbg</literal> — debug-символы для
-пакета <literal>nginx-module-njs</literal>
-</listitem>
-
-</list>
+ Также доступна отдельная утилита <link doc="cli.xml">командной строки</link>,
+которая может использоваться независимо от nginx для разработки и отладки njs.
 </para>
 
 </section>
 
-
-<section id="install_sources" name="Установка из исходных файлов">
-
-<para>
-<link url="http://hg.nginx.org/njs">Репозиторий</link>
-с исходным кодом njs можно клонировать следующей командой:
-(необходим клиент <link url="https://www.mercurial-scm.org">Mercurial</link>):
-<example>
-hg clone http://hg.nginx.org/njs
-</example>
-Затем модули необходимо собрать с помощью
-конфигурационного параметра <literal>--add-module</literal>:
-<example>
-./configure --add-module=<value>path-to-njs</value>/nginx
-</example>
-Модули также можно собрать как
-<link doc="../ngx_core_module.xml" id="load_module">динамические</link>:
-<example>
-./configure --add-dynamic-module=<value>path-to-njs</value>/nginx
-</example>
-</para>
-
-<para>
-Чтобы собрать только <link id="cli">утилиту</link> командной строки njs
-необходимо запустить
-команды <literal>./configure</literal> и <literal>make njs</literal>
-из корневого каталога.
-Утилита доступна как <literal>./build/njs</literal>.
-</para>
-
-</section>
-
-
-<section id="cli" name="Интерфейс командной строки">
-
-<para>
-Создание и отладка njs-скриптов может осуществляться
-в командной строке.
-Утилита командной строки доступна после установки
-<link id="install_package">пакета</link> Linux
-или после сборки из <link id="install_sources">исходных файлов</link>.
-В отличие от njs, запущенном внутри nginx,
-в утилите недоступны объекты nginx
-(<link doc="njs_api.xml" id="http">HTTP</link> и
-<link doc="njs_api.xml" id="stream">Stream</link>).
-<example>
-$ echo "2**3" | njs -
-8
-
-$ njs
->> var o = {a:[]}
-undefined
-
->> JSON.stringify(o, undefined,1)
-{
- "a": [
-
- ]
-}
->>
-</example>
-</para>
-
-</section>
-
-</section>
-
 </article>
--- a/xml/ru/docs/stream/ngx_stream_js_module.xml
+++ b/xml/ru/docs/stream/ngx_stream_js_module.xml
@@ -9,20 +9,20 @@
 <module name="Модуль ngx_stream_js_module"
         link="/ru/docs/stream/ngx_stream_js_module.html"
         lang="ru"
-        rev="14">
+        rev="15">
 
 <section id="summary">
 
 <para>
 Модуль <literal>ngx_stream_js_module</literal> позволяет задавать
-обработчики на <link doc="../njs/">njs</link> —
+обработчики на <link doc="../njs/index.xml">njs</link> —
 подмножестве языка JavaScript.
 </para>
 
 <para>
 По умолчанию этот модуль не собирается.
 Инструкция по сборке и установке доступны
-<link doc="../njs/index.xml" id="install">здесь</link>.
+<link doc="../njs/install.xml">здесь</link>.
 </para>
 
 </section>
@@ -36,7 +36,7 @@
 версией njs <link doc="../njs_changes.xml" id="njs-0.2.4">0.2.4</link>.
 Для версий njs <link doc="../njs_changes.xml" id="njs-0.2.3">0.2.3</link>
 и ранее необходимо использовать
-<link doc="../njs_api.xml" id="example_legacy">этот</link> пример.
+<link doc="../examples.xml" id="legacy">этот</link> пример.
 </note>
 <example>
 load_module modules/ngx_stream_js_module.so;