8246435: Replace Javascript implementation of pandoc filters with Java

Reviewed-by: erikj
This commit is contained in:
Magnus Ihse Bursie 2020-06-06 02:04:21 +02:00
parent 71c926c4f6
commit cd651b9aad
23 changed files with 1510 additions and 308 deletions

View File

@ -103,8 +103,8 @@ ifeq ($(ENABLE_PANDOC), true)
SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.sh.template, \ SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.sh.template, \
OUTPUT_FILE := $(PANDOC_TROFF_MANPAGE_FILTER), \ OUTPUT_FILE := $(PANDOC_TROFF_MANPAGE_FILTER), \
REPLACEMENTS := \ REPLACEMENTS := \
@@JJS@@ => $(JJS) ; \ @@JAVA_SMALL@@ => $(JAVA_SMALL) ; \
@@TOPDIR@@ => $(TOPDIR) ; \ @@BUILDTOOLS_OUTPUTDIR@@ => $(BUILDTOOLS_OUTPUTDIR) ; \
)) ))
# Created script must be made executable # Created script must be made executable
@ -126,8 +126,8 @@ ifeq ($(ENABLE_PANDOC), true)
SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-html-manpage-filter.sh.template, \ SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-html-manpage-filter.sh.template, \
OUTPUT_FILE := $(PANDOC_HTML_MANPAGE_FILTER), \ OUTPUT_FILE := $(PANDOC_HTML_MANPAGE_FILTER), \
REPLACEMENTS := \ REPLACEMENTS := \
@@JJS@@ => $(JJS) ; \ @@JAVA_SMALL@@ => $(JAVA_SMALL) ; \
@@TOPDIR@@ => $(TOPDIR) ; \ @@BUILDTOOLS_OUTPUTDIR@@ => $(BUILDTOOLS_OUTPUTDIR) ; \
)) ))
# Created script must be made executable # Created script must be made executable

View File

@ -610,9 +610,9 @@ ifeq ($(ENABLE_PANDOC), true)
# PANDOC_HTML_MANPAGE_FILTER, a wrapper around # PANDOC_HTML_MANPAGE_FILTER, a wrapper around
# PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk. # PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk.
# We should also depend on the source javascript filter # We should also depend on the source code for the filter
PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT := \ PANDOC_HTML_MANPAGE_FILTER_SOURCE := $(call FindFiles, \
$(TOPDIR)/make/scripts/pandoc-html-manpage-filter.js $(TOPDIR)/make/jdk/src/classes/build/tools/pandocfilter)
$(foreach m, $(ALL_MODULES), \ $(foreach m, $(ALL_MODULES), \
$(eval MAN_$m := $(call FindModuleManDirs, $m)) \ $(eval MAN_$m := $(call FindModuleManDirs, $m)) \
@ -632,7 +632,7 @@ ifeq ($(ENABLE_PANDOC), true)
OPTIONS := --toc -V include-before='$(SPECS_TOP)' -V include-after='$(SPECS_BOTTOM_1)', \ OPTIONS := --toc -V include-before='$(SPECS_TOP)' -V include-after='$(SPECS_BOTTOM_1)', \
POST_PROCESS := $(TOOL_FIXUPPANDOC), \ POST_PROCESS := $(TOOL_FIXUPPANDOC), \
EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \
$(PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT), \ $(PANDOC_HTML_MANPAGE_FILTER_SOURCE), \
)) \ )) \
$(eval JDK_SPECS_TARGETS += $($($m_$f_NAME))) \ $(eval JDK_SPECS_TARGETS += $($($m_$f_NAME))) \
) \ ) \

View File

@ -381,22 +381,6 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
BOOTJDK_USE_LOCAL_CDS=false BOOTJDK_USE_LOCAL_CDS=false
AC_MSG_RESULT([no, -XX:SharedArchiveFile not supported]) AC_MSG_RESULT([no, -XX:SharedArchiveFile not supported])
fi fi
# Check for jjs in bootjdk
UTIL_SETUP_TOOL(JJS,
[
AC_MSG_CHECKING([for jjs in Boot JDK])
JJS=$BOOT_JDK/bin/jjs
if test ! -x $JJS; then
AC_MSG_RESULT(not found)
JJS=""
AC_MSG_NOTICE([Cannot use pandoc without jjs])
ENABLE_PANDOC=false
else
AC_MSG_RESULT(ok)
fi
AC_SUBST(JJS)
])
]) ])
AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],

View File

@ -625,7 +625,6 @@ JAR_CMD:=@JAR@
JLINK_CMD := @JLINK@ JLINK_CMD := @JLINK@
JMOD_CMD := @JMOD@ JMOD_CMD := @JMOD@
JARSIGNER_CMD:=@JARSIGNER@ JARSIGNER_CMD:=@JARSIGNER@
JJS_CMD:=@JJS@
# These variables are meant to be used. They are defined with = instead of := to make # These variables are meant to be used. They are defined with = instead of := to make
# it possible to override only the *_CMD variables. # it possible to override only the *_CMD variables.
JAVA=@FIXPATH@ $(JAVA_CMD) $(JAVA_FLAGS_BIG) $(JAVA_FLAGS) JAVA=@FIXPATH@ $(JAVA_CMD) $(JAVA_FLAGS_BIG) $(JAVA_FLAGS)
@ -637,7 +636,6 @@ JAR=@FIXPATH@ $(JAR_CMD)
JLINK = @FIXPATH@ $(JLINK_CMD) JLINK = @FIXPATH@ $(JLINK_CMD)
JMOD = @FIXPATH@ $(JMOD_CMD) $(JAVA_TOOL_FLAGS_SMALL) JMOD = @FIXPATH@ $(JMOD_CMD) $(JAVA_TOOL_FLAGS_SMALL)
JARSIGNER=@FIXPATH@ $(JARSIGNER_CMD) JARSIGNER=@FIXPATH@ $(JARSIGNER_CMD)
JJS=@FIXPATH@ $(JJS_CMD) $(JAVA_TOOL_FLAGS_SMALL)
BUILD_JAVA_FLAGS := @BOOTCYCLE_JVM_ARGS_BIG@ BUILD_JAVA_FLAGS := @BOOTCYCLE_JVM_ARGS_BIG@
BUILD_JAVA=@FIXPATH@ $(BUILD_JDK)/bin/java $(BUILD_JAVA_FLAGS) BUILD_JAVA=@FIXPATH@ $(BUILD_JDK)/bin/java $(BUILD_JAVA_FLAGS)

View File

@ -199,9 +199,9 @@ ifeq ($(call isTargetOsType, unix), true)
# PANDOC_TROFF_MANPAGE_FILTER, a wrapper around # PANDOC_TROFF_MANPAGE_FILTER, a wrapper around
# PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk. # PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk.
# We should also depend on the source javascript filter # We should also depend on the source code for the filter
PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT := \ PANDOC_TROFF_MANPAGE_FILTER_SOURCE := $(call FindFiles, \
$(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.js $(TOPDIR)/make/jdk/src/classes/build/tools/pandocfilter)
# The norm in man pages is to display code literals as bold, but pandoc # The norm in man pages is to display code literals as bold, but pandoc
# "correctly" converts these constructs (encoded in markdown using `...` # "correctly" converts these constructs (encoded in markdown using `...`
@ -231,7 +231,7 @@ ifeq ($(call isTargetOsType, unix), true)
@@VERSION_SHORT@@ => $(VERSION_SHORT) ; \ @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \
@@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \ @@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \
EXTRA_DEPS := $(PANDOC_TROFF_MANPAGE_FILTER) \ EXTRA_DEPS := $(PANDOC_TROFF_MANPAGE_FILTER) \
$(PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT), \ $(PANDOC_TROFF_MANPAGE_FILTER_SOURCE), \
)) ))
TARGETS += $(BUILD_MAN_PAGES) TARGETS += $(BUILD_MAN_PAGES)

View File

@ -604,10 +604,6 @@ var getJibProfilesProfiles = function (input, common, data) {
dependencies: [ name + ".jdk" ], dependencies: [ name + ".jdk" ],
configure_args: [ configure_args: [
"--with-boot-jdk=" + input.get(name + ".jdk", "home_path"), "--with-boot-jdk=" + input.get(name + ".jdk", "home_path"),
// Full docs do not currently work with bootcycle build
// since Nashorn was removed. This negates the
// --enable-full-docs from the main profile.
"--enable-full-docs=auto",
] ]
} }
profiles[bootcyclePrebuiltName] = concatObjects(profiles[name], profiles[bootcyclePrebuiltName] = concatObjects(profiles[name],

View File

@ -0,0 +1,108 @@
package build.tools.pandocfilter;
import build.tools.pandocfilter.json.JSON;
import build.tools.pandocfilter.json.JSONArray;
import build.tools.pandocfilter.json.JSONObject;
import build.tools.pandocfilter.json.JSONString;
import build.tools.pandocfilter.json.JSONValue;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.Map;
public class PandocFilter {
/**
* Traverse a tree of pandoc format objects, calling callback on each
* element, and replacing it if callback returns a new object.
* <p>
* Inspired by the walk method in
* https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py
*/
public JSONValue traverse(JSONValue obj, Callback callback, boolean deep) {
if (obj instanceof JSONArray) {
JSONArray array = (JSONArray) obj;
JSONArray processed_array = new JSONArray();
for (JSONValue elem : array) {
if (elem instanceof JSONObject && elem.contains("t")) {
JSONValue replacement = callback.invoke(elem.get("t").asString(), elem.contains("c") ? elem.get("c") : new JSONArray());
if (replacement == null) {
// no replacement object returned, use original
processed_array.add(traverse(elem, callback, deep));
} else if (replacement instanceof JSONArray) {
// array of objects returned, splice all elements into array
JSONArray replacement_array = (JSONArray) replacement;
for (JSONValue repl_elem : replacement_array) {
processed_array.add(traverse(repl_elem, callback, deep));
}
} else {
// replacement object given, traverse it
processed_array.add(traverse(replacement, callback, deep));
}
} else {
processed_array.add(traverse(elem, callback, deep));
}
}
return processed_array;
} else if (obj instanceof JSONObject) {
if (deep && obj.contains("t")) {
JSONValue replacement = callback.invoke(obj.get("t").asString(), obj.contains("c") ? obj.get("c") : new JSONArray());
if (replacement != null) {
return replacement;
}
} JSONObject obj_obj = (JSONObject) obj;
var processed_obj = new JSONObject();
for (String key : obj_obj.keys()) {
processed_obj.put(key, traverse(obj_obj.get(key), callback, deep));
}
return processed_obj;
} else {
return obj;
}
}
public JSONValue createPandocNode(String type, JSONValue content) {
if (content == null) {
return new JSONObject(Map.of(
"t", new JSONString(type)));
} else {
return new JSONObject(Map.of(
"t", new JSONString(type),
"c", content));
}
}
public JSONValue createPandocNode(String type) {
return createPandocNode(type, null);
}
/*
* Helper constructors to create pandoc format objects
*/
public JSONValue createSpace() {
return createPandocNode("Space");
}
public JSONValue createStr(String string) {
return createPandocNode("Str", new JSONString(string));
}
public static JSONValue loadJson(String[] args) throws FileNotFoundException {
StringBuffer input = new StringBuffer();
InputStreamReader reader;
if (args.length > 0)
reader = new FileReader(args[0]);
else {
reader = new InputStreamReader(System.in);
}
new BufferedReader(reader).lines().forEach(line -> input.append(line));
return JSON.parse(input.toString());
}
public interface Callback {
JSONValue invoke(String type, JSONValue value);
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter;
import build.tools.pandocfilter.json.JSONArray;
import build.tools.pandocfilter.json.JSONObject;
import build.tools.pandocfilter.json.JSONValue;
import java.io.FileNotFoundException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PandocManPageHtmlFilter extends PandocFilter {
private JSONValue MetaInlines(JSONValue value) {
return createPandocNode("MetaInlines", value);
}
private JSONValue changeTitle(String type, JSONValue value) {
if (type.equals("MetaInlines")) {
String subType = value.get(0).get("t").asString();
String subContent = value.get(0).get("c").asString();
if (subType.equals("Str")) {
Pattern pattern = Pattern.compile("^([A-Z0-9]+)\\([0-9]+\\)$");
Matcher matcher = pattern.matcher(subContent);
if (matcher.find()) {
String commandName = matcher.group(1).toLowerCase();
return MetaInlines(new JSONArray(
createStr("The"), createSpace(),
createStr(commandName),
createSpace(), createStr("Command")));
}
}
}
return null;
}
/**
* Main function
*/
public static void main(String[] args) throws FileNotFoundException {
JSONValue json = loadJson(args);
PandocManPageHtmlFilter filter = new PandocManPageHtmlFilter();
JSONValue meta = json.get("meta");
if (meta != null && meta instanceof JSONObject) {
JSONObject metaobj = (JSONObject) meta;
metaobj.remove("date");
JSONValue title = meta.get("title");
if (title != null) {
metaobj.put("title", filter.traverse(title, filter::changeTitle, true));
}
}
System.out.println(json);
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter;
import build.tools.pandocfilter.json.JSONArray;
import build.tools.pandocfilter.json.JSONValue;
import java.io.FileNotFoundException;
public class PandocManPageTroffFilter extends PandocFilter {
private JSONValue createStrong(JSONValue value) {
return createPandocNode("Strong", value);
}
private JSONValue createHeader(JSONValue value) {
return createPandocNode("Header", value);
}
/**
* Callback to change all Str texts to upper case
*/
private JSONValue uppercase(String type, JSONValue value) {
if (type.equals("Str")) {
return createStr(value.asString().toUpperCase());
}
return null;
}
/**
* Main callback function that performs our man page AST rewrites
*/
private JSONValue manpageFilter(String type, JSONValue value) {
// If it is a header, decrease the heading level by one, and
// if it is a level 1 header, convert it to upper case.
if (type.equals("Header")) {
JSONArray array = value.asArray();
int level = array.get(0).asInt();
array.set(0, JSONValue.from(level - 1));
if (value.asArray().get(0).asInt() == 1) {
return createHeader(traverse(value, this::uppercase, false));
}
}
// Man pages does not have superscript. We use it for footnotes, so
// enclose in [...] for best representation.
if (type.equals("Superscript")) {
return new JSONArray(createStr("["), value, createStr("]"));
}
// If it is a link, put the link name in bold. If it is an external
// link, put it in brackets. Otherwise, it is either an internal link
// (like "#next-heading"), or a relative link to another man page
// (like "java.html"), so remove it for man pages.
if (type.equals("Link")) {
JSONValue target = value.asArray().get(2).asArray().get(0);
String targetStr = target.asString();
if (targetStr.startsWith("https:") || targetStr.startsWith("http:")) {
return new JSONArray(createStrong(value.asArray().get(1)), createSpace(), createStr("[" + targetStr + "]"));
} else {
return createStrong(value.asArray().get(1));
}
}
return null;
}
/**
* Main function
*/
public static void main(String[] args) throws FileNotFoundException {
JSONValue json = loadJson(args);
build.tools.pandocfilter.PandocManPageTroffFilter filter = new build.tools.pandocfilter.PandocManPageTroffFilter();
JSONValue transformed_json = filter.traverse(json, filter::manpageFilter, false);
System.out.println(transformed_json);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
public class JSON {
public static JSONValue parse(String s) {
return new JSONParser().parse(s);
}
public static JSONValue of(int i) {
return JSONValue.from(i);
}
public static JSONValue of(long l) {
return JSONValue.from(l);
}
public static JSONValue of(double d) {
return JSONValue.from(d);
}
public static JSONValue of(boolean b) {
return JSONValue.from(b);
}
public static JSONValue of(String s) {
return JSONValue.from(s);
}
public static JSONValue of() {
return JSONValue.fromNull();
}
public static JSONArray array() {
return new JSONArray();
}
public static JSONObject object() {
return new JSONObject();
}
}

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
import java.util.*;
import java.util.stream.Stream;
public class JSONArray implements JSONValue, Iterable<JSONValue> {
private final List<JSONValue> values;
public JSONArray() {
this.values = new ArrayList<JSONValue>();
}
public JSONArray(JSONValue[] array) {
this.values = new ArrayList<JSONValue>(array.length);
for (var v : array) {
values.add(v);
}
}
private void append(JSONValue value) {
if (value instanceof JSONArray) {
for (var v : value.asArray()) {
append(v);
}
} else {
this.values.add(value);
}
}
public JSONArray(JSONValue value, JSONValue... values) {
this.values = new ArrayList<JSONValue>(values.length + 1);
append(value);
for (var v : values) {
append(v);
}
}
public JSONArray(List<JSONValue> values) {
this.values = new ArrayList<JSONValue>(values);
}
@Override
public boolean isArray() {
return true;
}
@Override
public JSONArray asArray() {
return this;
}
public JSONArray set(int i, boolean value) {
values.set(i, JSON.of(value));
return this;
}
public JSONArray set(int i, int value) {
values.set(i, JSON.of(value));
return this;
}
public JSONArray set(int i, long value) {
values.set(i, JSON.of(value));
return this;
}
public JSONArray set(int i, String value) {
values.set(i, JSON.of(value));
return this;
}
public JSONArray set(int i, double value) {
values.set(i, JSON.of(value));
return this;
}
public JSONArray set(int i, JSONValue value) {
values.set(i, value);
return this;
}
public JSONArray setNull(int i) {
values.set(i, JSON.of());
return this;
}
public JSONArray add(boolean value) {
values.add(JSON.of(value));
return this;
}
public JSONArray add(int value) {
values.add(JSON.of(value));
return this;
}
public JSONArray add(long value) {
values.add(JSON.of(value));
return this;
}
public JSONArray add(String value) {
values.add(JSON.of(value));
return this;
}
public JSONArray add(double value) {
values.add(JSON.of(value));
return this;
}
public JSONArray add(JSONValue value) {
values.add(value);
return this;
}
public JSONArray addNull() {
values.add(JSON.of());
return this;
}
public JSONValue get(int i) {
return values.get(i);
}
public int size() {
return values.size();
}
@Override
public String toString() {
var builder = new StringBuilder();
builder.append("[");
for (var i = 0; i < size(); i++) {
builder.append(get(i).toString());
if (i != (size() - 1)) {
builder.append(",");
}
}
builder.append("]");
return builder.toString();
}
@Override
public Stream<JSONValue> stream() {
return values.stream();
}
@Override
public Iterator<JSONValue> iterator() {
return values.iterator();
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
public class JSONBoolean implements JSONValue {
private boolean value;
public JSONBoolean(boolean value) {
this.value = value;
}
@Override
public boolean isBoolean() {
return true;
}
@Override
public boolean asBoolean() {
return value;
}
@Override
public String toString() {
return value ? "true" : "false";
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
public class JSONDecimal implements JSONValue {
private double value;
public JSONDecimal(double value) {
this.value = value;
}
@Override
public boolean isDouble() {
return true;
}
@Override
public double asDouble() {
return value;
}
@Override
public String toString() {
return Double.toString(value);
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
public class JSONNull implements JSONValue {
public JSONNull() {
}
@Override
public boolean isNull() {
return true;
}
@Override
public String asString() {
return null;
}
@Override
public JSONArray asArray() {
return null;
}
@Override
public JSONObject asObject() {
return null;
}
@Override
public String toString() {
return "null";
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
public class JSONNumber implements JSONValue {
private long value;
public JSONNumber(int value) {
this.value = value;
}
public JSONNumber(long value) {
this.value = value;
}
@Override
public boolean isInt() {
return true;
}
@Override
public boolean isLong() {
return true;
}
@Override
public int asInt() {
return Math.toIntExact(value);
}
@Override
public long asLong() {
return value;
}
@Override
public String toString() {
return Long.toString(value);
}
}

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
import java.util.*;
import java.util.stream.Collectors;
public class JSONObject implements JSONValue {
public static class Field {
private final String name;
private final JSONValue value;
private Field(String name, JSONValue value) {
this.name = name;
this.value = value;
}
public String name() {
return name;
}
public JSONValue value() {
return value;
}
}
private final Map<String, JSONValue> value;
public JSONObject() {
this.value = new HashMap<String, JSONValue>();
}
public JSONObject(Map<String, JSONValue> map) {
this.value = new HashMap<String, JSONValue>(map);
}
@Override
public boolean isObject() {
return true;
}
@Override
public JSONObject asObject() {
return this;
}
public JSONObject put(String k, boolean v) {
value.put(k, JSON.of(v));
return this;
}
public JSONObject put(String k, int v) {
value.put(k, JSON.of(v));
return this;
}
public JSONObject put(String k, long v) {
value.put(k, JSON.of(v));
return this;
}
public JSONObject put(String k, String v) {
value.put(k, JSON.of(v));
return this;
}
public JSONObject put(String k, double v) {
value.put(k, JSON.of(v));
return this;
}
public JSONObject put(String k, JSONArray v) {
value.put(k, v);
return this;
}
public JSONObject put(String k, JSONObject v) {
value.put(k, v);
return this;
}
public JSONObject put(String k, JSONValue v) {
value.put(k, v);
return this;
}
public JSONObject putNull(String k) {
value.put(k, JSON.of());
return this;
}
public JSONValue remove(String k) {
return value.remove(k);
}
public JSONValue get(String k) {
return value.get(k);
}
public List<Field> fields() {
return value.entrySet()
.stream()
.map(e -> new Field(e.getKey(), e.getValue()))
.collect(Collectors.toList());
}
public boolean contains(String field) {
return value.containsKey(field);
}
public Set<String> keys() {
return value.keySet();
}
@Override
public String toString() {
var builder = new StringBuilder();
builder.append("{");
for (var key : value.keySet()) {
builder.append("\"");
builder.append(key);
builder.append("\":");
builder.append(value.get(key).toString());
builder.append(",");
}
var end = builder.length() - 1;
if (builder.charAt(end) == ',') {
builder.deleteCharAt(end);
}
builder.append("}");
return builder.toString();
}
}

View File

@ -0,0 +1,391 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
import java.util.*;
class JSONParser {
private int pos = 0;
private String input;
JSONParser() {
}
private IllegalStateException failure(String message) {
return new IllegalStateException(String.format("[%d]: %s : %s", pos, message, input));
}
private char current() {
return input.charAt(pos);
}
private void advance() {
pos++;
}
private boolean hasInput() {
return pos < input.length();
}
private void expectMoreInput(String message) {
if (!hasInput()) {
throw failure(message);
}
}
private char next(String message) {
advance();
if (!hasInput()) {
throw failure(message);
}
return current();
}
private void expect(char c) {
var msg = String.format("Expected character %c", c);
var n = next(msg);
if (n != c) {
throw failure(msg);
}
}
private void assume(char c, String message) {
expectMoreInput(message);
if (current() != c) {
throw failure(message);
}
}
private JSONBoolean parseBoolean() {
if (current() == 't') {
expect('r');
expect('u');
expect('e');
advance();
return new JSONBoolean(true);
}
if (current() == 'f') {
expect('a');
expect('l');
expect('s');
expect('e');
advance();
return new JSONBoolean(false);
}
throw failure("a boolean can only be 'true' or 'false'");
}
private JSONValue parseNumber() {
var isInteger = true;
var builder = new StringBuilder();
if (current() == '-') {
builder.append(current());
advance();
expectMoreInput("a number cannot consist of only '-'");
}
if (current() == '0') {
builder.append(current());
advance();
if (hasInput() && current() == '.') {
isInteger = false;
builder.append(current());
advance();
expectMoreInput("a number cannot end with '.'");
if (!isDigit(current())) {
throw failure("must be at least one digit after '.'");
}
while (hasInput() && isDigit(current())) {
builder.append(current());
advance();
}
}
} else {
while (hasInput() && isDigit(current())) {
builder.append(current());
advance();
}
if (hasInput() && current() == '.') {
isInteger = false;
builder.append(current());
advance();
expectMoreInput("a number cannot end with '.'");
if (!isDigit(current())) {
throw failure("must be at least one digit after '.'");
}
while (hasInput() && isDigit(current())) {
builder.append(current());
advance();
}
}
}
if (hasInput() && (current() == 'e' || current() == 'E')) {
isInteger = false;
builder.append(current());
advance();
expectMoreInput("a number cannot end with 'e' or 'E'");
if (current() == '+' || current() == '-') {
builder.append(current());
advance();
}
if (!isDigit(current())) {
throw failure("a digit must follow {'e','E'}{'+','-'}");
}
while (hasInput() && isDigit(current())) {
builder.append(current());
advance();
}
}
var value = builder.toString();
return isInteger ? new JSONNumber(Long.parseLong(value)) :
new JSONDecimal(Double.parseDouble(value));
}
private JSONString parseString() {
var missingEndChar = "string is not terminated with '\"'";
var builder = new StringBuilder();
for (var c = next(missingEndChar); c != '"'; c = next(missingEndChar)) {
if (c == '\\') {
var n = next(missingEndChar);
switch (n) {
case '"':
builder.append("\"");
break;
case '\\':
builder.append("\\");
break;
case '/':
builder.append("/");
break;
case 'b':
builder.append("\b");
break;
case 'f':
builder.append("\f");
break;
case 'n':
builder.append("\n");
break;
case 'r':
builder.append("\r");
break;
case 't':
builder.append("\t");
break;
case 'u':
var u1 = next(missingEndChar);
var u2 = next(missingEndChar);
var u3 = next(missingEndChar);
var u4 = next(missingEndChar);
var cp = Integer.parseInt(String.format("%c%c%c%c", u1, u2, u3, u4), 16);
builder.append(new String(new int[]{cp}, 0, 1));
break;
default:
throw failure(String.format("Unexpected escaped character '%c'", n));
}
} else {
builder.append(c);
}
}
advance(); // step beyond closing "
return new JSONString(builder.toString());
}
private JSONArray parseArray() {
var error = "array is not terminated with ']'";
var list = new ArrayList<JSONValue>();
advance(); // step beyond opening '['
consumeWhitespace();
expectMoreInput(error);
while (current() != ']') {
var val = parseValue();
list.add(val);
expectMoreInput(error);
if (current() == ',') {
advance();
}
expectMoreInput(error);
}
advance(); // step beyond closing ']'
return new JSONArray(list.toArray(new JSONValue[0]));
}
public JSONNull parseNull() {
expect('u');
expect('l');
expect('l');
advance();
return new JSONNull();
}
public JSONObject parseObject() {
var error = "object is not terminated with '}'";
var map = new HashMap<String, JSONValue>();
advance(); // step beyond opening '{'
consumeWhitespace();
expectMoreInput(error);
while (current() != '}') {
var key = parseValue();
if (!(key instanceof JSONString)) {
throw failure("a field must of type string");
}
if (!hasInput() || current() != ':') {
throw failure("a field must be followed by ':'");
}
advance(); // skip ':'
var val = parseValue();
map.put(key.asString(), val);
expectMoreInput(error);
if (current() == ',') {
advance();
}
expectMoreInput(error);
}
advance(); // step beyond '}'
return new JSONObject(map);
}
private boolean isDigit(char c) {
return c == '0' ||
c == '1' ||
c == '2' ||
c == '3' ||
c == '4' ||
c == '5' ||
c == '6' ||
c == '7' ||
c == '8' ||
c == '9';
}
private boolean isStartOfNumber(char c) {
return isDigit(c) || c == '-';
}
private boolean isStartOfString(char c) {
return c == '"';
}
private boolean isStartOfBoolean(char c) {
return c == 't' || c == 'f';
}
private boolean isStartOfArray(char c) {
return c == '[';
}
private boolean isStartOfNull(char c) {
return c == 'n';
}
private boolean isWhitespace(char c) {
return c == '\r' ||
c == '\n' ||
c == '\t' ||
c == ' ';
}
private boolean isStartOfObject(char c) {
return c == '{';
}
private void consumeWhitespace() {
while (hasInput() && isWhitespace(current())) {
advance();
}
}
public JSONValue parseValue() {
JSONValue ret = null;
consumeWhitespace();
if (hasInput()) {
var c = current();
if (isStartOfNumber(c)) {
ret = parseNumber();
} else if (isStartOfString(c)) {
ret = parseString();
} else if (isStartOfBoolean(c)) {
ret = parseBoolean();
} else if (isStartOfArray(c)) {
ret = parseArray();
} else if (isStartOfNull(c)) {
ret = parseNull();
} else if (isStartOfObject(c)) {
ret = parseObject();
} else {
throw failure("not a valid start of a JSON value");
}
}
consumeWhitespace();
return ret;
}
public JSONValue parse(String s) {
if (s == null || s.equals("")) {
return null;
}
pos = 0;
input = s;
var result = parseValue();
if (hasInput()) {
throw failure("can only have one top-level JSON value");
}
return result;
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
public class JSONString implements JSONValue {
private String value;
public JSONString(String value) {
this.value = value;
}
@Override
public boolean isString() {
return true;
}
@Override
public String asString() {
return value;
}
@Override
public String toString() {
var builder = new StringBuilder();
builder.append("\"");
for (var i = 0; i < value.length(); i++) {
var c = value.charAt(i);
switch (c) {
case '"':
builder.append("\\\"");
break;
case '\\':
builder.append("\\\\");
break;
case '/':
builder.append("\\/");
break;
case '\b':
builder.append("\\b");
break;
case '\f':
builder.append("\\f");
break;
case '\n':
builder.append("\\n");
break;
case '\r':
builder.append("\\r");
break;
case '\t':
builder.append("\\t");
break;
default:
builder.append(c);
break;
}
}
builder.append("\"");
return builder.toString();
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.pandocfilter.json;
import java.util.stream.Stream;
import java.util.List;
public interface JSONValue {
default int asInt() {
throw new IllegalStateException("Unsupported conversion to int");
}
default long asLong() {
throw new IllegalStateException("Unsupported conversion to long");
}
default double asDouble() {
throw new IllegalStateException("Unsupported conversion to double");
}
default String asString() {
throw new IllegalStateException("Unsupported conversion to String");
}
default boolean asBoolean() {
throw new IllegalStateException("Unsupported conversion to boolean");
}
default JSONArray asArray() {
throw new IllegalStateException("Unsupported conversion to array");
}
default JSONObject asObject() {
throw new IllegalStateException("Unsupported conversion to object");
}
default boolean isInt() {
return false;
}
default boolean isLong() {
return false;
}
default boolean isDouble() {
return false;
}
default boolean isString() {
return false;
}
default boolean isBoolean() {
return false;
}
default boolean isArray() {
return false;
}
default boolean isObject() {
return false;
}
default boolean isNull() {
return false;
}
default List<JSONObject.Field> fields() {
return asObject().fields();
}
default boolean contains(String key) {
return asObject().contains(key);
}
default JSONValue get(String key) {
return asObject().get(key);
}
default JSONValue get(int i) {
return asArray().get(i);
}
default Stream<JSONValue> stream() {
return Stream.of(this);
}
static JSONValue from(int i) {
return new JSONNumber(i);
}
static JSONValue from(long l) {
return new JSONNumber(l);
}
static JSONValue from(double d) {
return new JSONDecimal(d);
}
static JSONValue from(boolean b) {
return new JSONBoolean(b);
}
static JSONValue from(String s) {
return new JSONString(s);
}
static JSONValue fromNull() {
return new JSONNull();
}
}

View File

@ -1,125 +0,0 @@
//
// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 2 only, as
// published by the Free Software Foundation.
//
// This code is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// version 2 for more details (a copy is included in the LICENSE file that
// accompanied this code).
//
// You should have received a copy of the GNU General Public License version
// 2 along with this work; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
// or visit www.oracle.com if you need additional information or have any
// questions.
//
//
// Traverse a tree of pandoc format objects, calling callback on each
// element, and replacing it if callback returns a new object.
//
// Inspired by the walk method in
// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py
//
function traverse(obj, callback) {
if (Array.isArray(obj)) {
var processed_array = [];
obj.forEach(function(elem) {
if (elem === Object(elem) && elem.t) {
var replacement = callback(elem.t, elem.c || []);
if (!replacement) {
// no replacement object returned, use original
processed_array.push(traverse(elem, callback));
} else if (Array.isArray(replacement)) {
// array of objects returned, splice all elements into array
replacement.forEach(function(repl_elem) {
processed_array.push(traverse(repl_elem, callback));
})
} else {
// replacement object given, traverse it
processed_array.push(traverse(replacement, callback));
}
} else {
processed_array.push(traverse(elem, callback));
}
})
return processed_array;
} else if (obj === Object(obj)) {
if (obj.t) {
var replacement = callback(obj.t, obj.c || []);
if (replacement) {
return replacement;
}
}
var processed_obj = {};
Object.keys(obj).forEach(function(key) {
processed_obj[key] = traverse(obj[key], callback);
})
return processed_obj;
} else {
return obj;
}
}
//
// Helper constructors to create pandoc format objects
//
function Space() {
return { 't': 'Space' };
}
function Str(value) {
return { 't': 'Str', 'c': value };
}
function MetaInlines(value) {
return { 't': 'MetaInlines', 'c': value };
}
function change_title(type, value) {
if (type === 'MetaInlines') {
if (value[0].t === 'Str') {
var match = value[0].c.match(/^([A-Z0-9]+)\([0-9]+\)$/);
if (match) {
return MetaInlines([
Str("The"), Space(),
Str(match[1].toLowerCase()),
Space(), Str("Command")
]);
}
}
}
}
//
// Main function
//
function main() {
var input = "";
while (line = readLine()) {
input = input.concat(line);
}
var json = JSON.parse(input);
var meta = json.meta;
if (meta) {
meta.date = undefined;
var title = meta.title;
if (meta.title) {
meta.title = traverse(meta.title, change_title);
}
}
print(JSON.stringify(json));
}
// ... and execute it
main();

View File

@ -22,7 +22,7 @@
# questions. # questions.
# #
# Simple wrapper script to call Nashorn with the javascript pandoc filter # Simple wrapper script to call Java with the pandoc filter
@@JJS@@ -scripting \ @@JAVA_SMALL@@ -cp @@BUILDTOOLS_OUTPUTDIR@@/jdk_tools_classes \
"@@TOPDIR@@/make/scripts/pandoc-html-manpage-filter.js" 2> /dev/null build.tools.pandocfilter.PandocManPageHtmlFilter

View File

@ -1,142 +0,0 @@
//
// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 2 only, as
// published by the Free Software Foundation.
//
// This code is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// version 2 for more details (a copy is included in the LICENSE file that
// accompanied this code).
//
// You should have received a copy of the GNU General Public License version
// 2 along with this work; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
// or visit www.oracle.com if you need additional information or have any
// questions.
//
//
// Traverse a tree of pandoc format objects, calling callback on each
// element, and replacing it if callback returns a new object.
//
// Inspired by the walk method in
// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py
//
function traverse(obj, callback) {
if (Array.isArray(obj)) {
var processed_array = [];
obj.forEach(function(elem) {
if (elem === Object(elem) && elem.t) {
var replacement = callback(elem.t, elem.c || []);
if (!replacement) {
// no replacement object returned, use original
processed_array.push(traverse(elem, callback));
} else if (Array.isArray(replacement)) {
// array of objects returned, splice all elements into array
replacement.forEach(function(repl_elem) {
processed_array.push(traverse(repl_elem, callback));
})
} else {
// replacement object given, traverse it
processed_array.push(traverse(replacement, callback));
}
} else {
processed_array.push(traverse(elem, callback));
}
})
return processed_array;
} else if (obj === Object(obj)) {
var processed_obj = {};
Object.keys(obj).forEach(function(key) {
processed_obj[key] = traverse(obj[key], callback);
})
return processed_obj;
} else {
return obj;
}
}
//
// Helper constructors to create pandoc format objects
//
function Space() {
return { 't': 'Space', 'c': [] };
}
function Str(value) {
return { 't': 'Str', 'c': value };
}
function Strong(value) {
return { 't': 'Strong', 'c': value };
}
function Header(value) {
return { 't': 'Header', 'c': value };
}
//
// Callback to change all Str texts to upper case
//
function uppercase(type, value) {
if (type === 'Str') {
return Str(value.toUpperCase());
}
}
//
// Main callback function that performs our man page AST rewrites
//
function manpage_filter(type, value) {
// If it is a header, decrease the heading level by one, and
// if it is a level 1 header, convert it to upper case.
if (type === 'Header') {
value[0] = Math.max(1, value[0] - 1);
if (value[0] == 1) {
return Header(traverse(value, uppercase));
}
}
// Man pages does not have superscript. We use it for footnotes, so
// enclose in [...] for best representation.
if (type === 'Superscript') {
return [ Str('['), value[0], Str(']') ];
}
// If it is a link, put the link name in bold. If it is an external
// link, put it in brackets. Otherwise, it is either an internal link
// (like "#next-heading"), or a relative link to another man page
// (like "java.html"), so remove it for man pages.
if (type === 'Link') {
var target = value[2][0];
if (target.match(/^http[s]?:/)) {
return [ Strong(value[1]), Space(), Str('[' + target + ']') ];
} else {
return Strong(value[1]);
}
}
}
//
// Main function
//
function main() {
var input = "";
while (line = readLine()) {
input = input.concat(line);
}
var json = JSON.parse(input);
var transformed_json = traverse(json, manpage_filter);
print(JSON.stringify(transformed_json));
}
// ... and execute it
main();

View File

@ -22,7 +22,7 @@
# questions. # questions.
# #
# Simple wrapper script to call Nashorn with the javascript pandoc filter # Simple wrapper script to call Java with the pandoc filter
@@JJS@@ -scripting \ @@JAVA_SMALL@@ -cp @@BUILDTOOLS_OUTPUTDIR@@/jdk_tools_classes \
"@@TOPDIR@@/make/scripts/pandoc-troff-manpage-filter.js" 2> /dev/null build.tools.pandocfilter.PandocManPageTroffFilter