View Javadoc
1   /*
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.metaschema.core.datatype.markup.flexmark;
28  
29  import com.vladsch.flexmark.ext.escaped.character.EscapedCharacterExtension;
30  import com.vladsch.flexmark.ext.gfm.strikethrough.SubscriptExtension;
31  import com.vladsch.flexmark.ext.superscript.SuperscriptExtension;
32  import com.vladsch.flexmark.ext.tables.TablesExtension;
33  import com.vladsch.flexmark.ext.typographic.TypographicExtension;
34  import com.vladsch.flexmark.formatter.Formatter;
35  import com.vladsch.flexmark.html.HtmlRenderer;
36  import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter;
37  import com.vladsch.flexmark.parser.Parser;
38  import com.vladsch.flexmark.parser.ParserEmulationProfile;
39  import com.vladsch.flexmark.util.data.DataHolder;
40  import com.vladsch.flexmark.util.data.DataSet;
41  import com.vladsch.flexmark.util.data.MutableDataSet;
42  import com.vladsch.flexmark.util.format.options.ListBulletMarker;
43  import com.vladsch.flexmark.util.misc.Extension;
44  
45  import java.util.List;
46  import java.util.Map;
47  import java.util.concurrent.ConcurrentHashMap;
48  
49  import edu.umd.cs.findbugs.annotations.NonNull;
50  import edu.umd.cs.findbugs.annotations.Nullable;
51  
52  public final class FlexmarkConfiguration {
53  
54    @NonNull
55    private static final ParserEmulationProfile PARSER_PROFILE = ParserEmulationProfile.COMMONMARK_0_29;
56  
57    @NonNull
58    public static final DataSet FLEXMARK_CONFIG = initFlexmarkConfig();
59  
60    @SuppressWarnings("null")
61    @NonNull
62    private static DataSet initFlexmarkConfig() {
63      MutableDataSet options = new MutableDataSet();
64      options.setFrom(PARSER_PROFILE);
65  
66      List<Extension> extensions = List.of(
67          // Metaschema insert
68          InsertAnchorExtension.create(),
69          // q tag handling
70          HtmlQuoteTagExtension.create(),
71          TypographicExtension.create(),
72          TablesExtension.create(),
73          // fix for code handling
74          HtmlCodeRenderExtension.create(),
75          // to ensure that escaped characters are not lost
76          EscapedCharacterExtension.create(),
77          SuperscriptExtension.create(),
78          SubscriptExtension.create()
79      // AutolinkExtension.create()
80      );
81      Parser.EXTENSIONS.set(options, extensions);
82  
83      // AST processing expects this
84      Parser.FENCED_CODE_CONTENT_BLOCK.set(options, true);
85      // Parser.CODE_SOFT_LINE_BREAKS.set(options, true);
86      // Parser.PARSE_INNER_HTML_COMMENTS.set(options, true);
87      // Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE.set(options, true);
88      // Parser.HTML_COMMENT_BLOCKS_INTERRUPT_PARAGRAPH.set(options, true);
89  
90      // disable the built in processor, since we are configuring a patched one
91      Parser.ASTERISK_DELIMITER_PROCESSOR.set(options, false);
92  
93      // configure GitHub-flavored tables
94      TablesExtension.COLUMN_SPANS.set(options, false);
95      TablesExtension.APPEND_MISSING_COLUMNS.set(options, true);
96      TablesExtension.DISCARD_EXTRA_COLUMNS.set(options, true);
97      TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH.set(options, true);
98  
99      // TypographicExtension.ENABLE_QUOTES.set(options, true); // default
100     TypographicExtension.ENABLE_SMARTS.set(options, false);
101     TypographicExtension.SINGLE_QUOTE_UNMATCHED.set(options, "'");
102     TypographicExtension.DOUBLE_QUOTE_OPEN.set(options, "\"");
103     TypographicExtension.DOUBLE_QUOTE_CLOSE.set(options, "\"");
104 
105     Map<String, String> typographicReplacementMap = new ConcurrentHashMap<>();
106     typographicReplacementMap.put("“", "\"");
107     typographicReplacementMap.put("”", "\"");
108     typographicReplacementMap.put("&ldquo;", "“");
109     typographicReplacementMap.put("&rdquo;", "”");
110     // typographicReplacementMap.put("‘", "'");
111     // typographicReplacementMap.put("’", "'");
112     typographicReplacementMap.put("&lsquo;", "‘");
113     typographicReplacementMap.put("&rsquo;", "’");
114     typographicReplacementMap.put("&apos;", "’");
115     // typographicReplacementMap.put("«", "<<");
116     typographicReplacementMap.put("&laquo;", "«");
117     // typographicReplacementMap.put("»", ">>");
118     typographicReplacementMap.put("&raquo;", "»");
119     // typographicReplacementMap.put("…", "...");
120     typographicReplacementMap.put("&hellip;", "…");
121     // typographicReplacementMap.put("–", "--");
122     typographicReplacementMap.put("&endash;", "–");
123     // typographicReplacementMap.put("—", "---");
124     typographicReplacementMap.put("&emdash;", "—");
125 
126     FlexmarkHtmlConverter.TYPOGRAPHIC_REPLACEMENT_MAP.set(options, typographicReplacementMap);
127     FlexmarkHtmlConverter.OUTPUT_UNKNOWN_TAGS.set(options, true);
128     FlexmarkHtmlConverter.SETEXT_HEADINGS.set(options, false); // disable
129     // needed to ensure extra empty paragraphs are ignored
130     FlexmarkHtmlConverter.BR_AS_EXTRA_BLANK_LINES.set(options, false);
131 
132     // FlexmarkHtmlConverter.RENDER_COMMENTS.set(options, true);
133     // FlexmarkHtmlConverter.ADD_TRAILING_EOL.set(options, false); // default
134 
135     Formatter.MAX_TRAILING_BLANK_LINES.set(options, -1);
136     Formatter.LIST_BULLET_MARKER.set(options, ListBulletMarker.DASH);
137 
138     HtmlRenderer.MAX_TRAILING_BLANK_LINES.set(options, -1);
139     HtmlRenderer.UNESCAPE_HTML_ENTITIES.set(options, true);
140     HtmlRenderer.PERCENT_ENCODE_URLS.set(options, true);
141     // HtmlRenderer.ESCAPE_HTML_COMMENT_BLOCKS.set(options, false); // default
142     // HtmlRenderer.SUPPRESS_HTML_COMMENT_BLOCKS.set(options, false); // default
143     // HtmlRenderer.SUPPRESS_INLINE_HTML_COMMENTS.set(options, false); // default
144     // HtmlRenderer.HARD_BREAK.set(options,"<br/>");
145 
146     return options.toImmutable();
147   }
148 
149   public static DataSet newFlexmarkConfig(@Nullable DataHolder options) {
150     return options == null ? FLEXMARK_CONFIG : DataSet.merge(FLEXMARK_CONFIG, options);
151   }
152 
153   private FlexmarkConfiguration() {
154     // disable construction
155   }
156 
157 }