make/scripts/pandoc-troff-manpage-filter.js
branchihse-manpages-branch
changeset 57051 d8697832a650
parent 57049 d13c49f43710
equal deleted inserted replaced
57050:746a7ee75caa 57051:d8697832a650
       
     1 //
       
     2 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4 //
       
     5 // This code is free software; you can redistribute it and/or modify it
       
     6 // under the terms of the GNU General Public License version 2 only, as
       
     7 // published by the Free Software Foundation.
       
     8 //
       
     9 // This code is distributed in the hope that it will be useful, but WITHOUT
       
    10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12 // version 2 for more details (a copy is included in the LICENSE file that
       
    13 // accompanied this code).
       
    14 //
       
    15 // You should have received a copy of the GNU General Public License version
       
    16 // 2 along with this work; if not, write to the Free Software Foundation,
       
    17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18 //
       
    19 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20 // or visit www.oracle.com if you need additional information or have any
       
    21 // questions.
       
    22 //
       
    23 
       
    24 //
       
    25 // Traverse a tree of pandoc format objects, calling callback on each
       
    26 // element, and replacing it if callback returns a new object.
       
    27 //
       
    28 // Inspired by the walk method in
       
    29 // https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py
       
    30 //
       
    31 function traverse(obj, callback) {
       
    32     if (Array.isArray(obj)) {
       
    33         var processed_array = [];
       
    34         obj.forEach(function(elem) {
       
    35             if (elem === Object(elem) && elem.t) {
       
    36                 var replacement = callback(elem.t, elem.c || []);
       
    37                 if (!replacement) {
       
    38                     // no replacement object returned, use original
       
    39                     processed_array.push(traverse(elem, callback));
       
    40                 } else if (Array.isArray(replacement)) {
       
    41                     // array of objects returned, splice all elements into array
       
    42                     replacement.forEach(function(repl_elem) {
       
    43                         processed_array.push(traverse(repl_elem, callback));
       
    44                     })
       
    45                 } else {
       
    46                     // replacement object given, traverse it
       
    47                     processed_array.push(traverse(replacement, callback));
       
    48                 }
       
    49             } else {
       
    50                 processed_array.push(traverse(elem, callback));
       
    51             }
       
    52         })
       
    53         return processed_array;
       
    54     } else if (obj === Object(obj)) {
       
    55         var processed_obj = {};
       
    56         Object.keys(obj).forEach(function(key) {
       
    57             processed_obj[key] = traverse(obj[key], callback);
       
    58         })
       
    59         return processed_obj;
       
    60     } else {
       
    61         return obj;
       
    62     }
       
    63 }
       
    64 
       
    65 //
       
    66 // Helper constructors to create pandoc format objects
       
    67 //
       
    68 function Space() {
       
    69     return { 't': 'Space', 'c': [] };
       
    70 }
       
    71 
       
    72 function Str(value) {
       
    73     return { 't': 'Str', 'c': value };
       
    74 }
       
    75 
       
    76 function Strong(value) {
       
    77     return { 't': 'Strong', 'c': value };
       
    78 }
       
    79 
       
    80 function Header(value) {
       
    81     return { 't': 'Header', 'c': value };
       
    82 }
       
    83 
       
    84 //
       
    85 // Callback to change all Str texts to upper case
       
    86 //
       
    87 function uppercase(type, value) {
       
    88     if (type === 'Str') {
       
    89         return Str(value.toUpperCase());
       
    90     }
       
    91 }
       
    92 
       
    93 //
       
    94 // Main callback function that performs our man page AST rewrites
       
    95 //
       
    96 function manpage_filter(type, value) {
       
    97     // If it is a header, decrease the heading level by one, and
       
    98     // if it is a level 1 header, convert it to upper case.
       
    99     if (type === 'Header') {
       
   100         value[0] = Math.max(1, value[0] - 1);
       
   101         if (value[0] == 1) {
       
   102             return Header(traverse(value, uppercase));
       
   103         }
       
   104     }
       
   105 
       
   106     // Man pages does not have superscript. We use it for footnotes, so
       
   107     // enclose in [...] for best representation.
       
   108     if (type === 'Superscript') {
       
   109         return [ Str('['), value[0], Str(']') ];
       
   110     }
       
   111 
       
   112     // If it is a link, put the link name in bold. If it is an external
       
   113     // link, put it in brackets. Otherwise, it is either an internal link
       
   114     // (like "#next-heading"), or a relative link to another man page
       
   115     // (like "java.html"), so remove it for man pages.
       
   116     if (type === 'Link') {
       
   117         var target = value[2][0];
       
   118         if (target.match(/^http[s]?:/)) {
       
   119             return [ Strong(value[1]), Space(), Str('[' + target + ']') ];
       
   120         } else {
       
   121             return Strong(value[1]);
       
   122         }
       
   123     }
       
   124 }
       
   125 
       
   126 //
       
   127 // Main function
       
   128 //
       
   129 function main() {
       
   130     var input = "";
       
   131     while (line = readLine()) {
       
   132         input = input.concat(line);
       
   133     }
       
   134     var json = JSON.parse(input);
       
   135 
       
   136     var transformed_json = traverse(json, manpage_filter);
       
   137 
       
   138     print(JSON.stringify(transformed_json));
       
   139 }
       
   140 
       
   141 // ... and execute it
       
   142 main();