001/* 002 * Portions of this software was developed by employees of the National Institute 003 * of Standards and Technology (NIST), an agency of the Federal Government and is 004 * being made available as a public service. Pursuant to title 17 United States 005 * Code Section 105, works of NIST employees are not subject to copyright 006 * protection in the United States. This software may be subject to foreign 007 * copyright. Permission in the United States and in foreign countries, to the 008 * extent that NIST may hold copyright, to use, copy, modify, create derivative 009 * works, and distribute this software and its documentation without fee is hereby 010 * granted on a non-exclusive basis, provided that this notice and disclaimer 011 * of warranty appears in all copies. 012 * 013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER 014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY 015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF 016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM 017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE 018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT 019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, 020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, 021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, 022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR 023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT 024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. 025 */ 026 027package gov.nist.secauto.metaschema.core.datatype.markup.flexmark; 028 029import com.vladsch.flexmark.ext.escaped.character.EscapedCharacterExtension; 030import com.vladsch.flexmark.ext.gfm.strikethrough.SubscriptExtension; 031import com.vladsch.flexmark.ext.superscript.SuperscriptExtension; 032import com.vladsch.flexmark.ext.tables.TablesExtension; 033import com.vladsch.flexmark.ext.typographic.TypographicExtension; 034import com.vladsch.flexmark.formatter.Formatter; 035import com.vladsch.flexmark.html.HtmlRenderer; 036import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter; 037import com.vladsch.flexmark.parser.Parser; 038import com.vladsch.flexmark.parser.ParserEmulationProfile; 039import com.vladsch.flexmark.util.data.DataHolder; 040import com.vladsch.flexmark.util.data.DataSet; 041import com.vladsch.flexmark.util.data.MutableDataSet; 042import com.vladsch.flexmark.util.format.options.ListBulletMarker; 043import com.vladsch.flexmark.util.misc.Extension; 044 045import java.util.List; 046import java.util.Map; 047import java.util.concurrent.ConcurrentHashMap; 048 049import edu.umd.cs.findbugs.annotations.NonNull; 050import edu.umd.cs.findbugs.annotations.Nullable; 051 052public final class FlexmarkConfiguration { 053 054 @NonNull 055 private static final ParserEmulationProfile PARSER_PROFILE = ParserEmulationProfile.COMMONMARK_0_29; 056 057 @NonNull 058 public static final DataSet FLEXMARK_CONFIG = initFlexmarkConfig(); 059 060 @SuppressWarnings("null") 061 @NonNull 062 private static DataSet initFlexmarkConfig() { 063 MutableDataSet options = new MutableDataSet(); 064 options.setFrom(PARSER_PROFILE); 065 066 List<Extension> extensions = List.of( 067 // Metaschema insert 068 InsertAnchorExtension.create(), 069 // q tag handling 070 HtmlQuoteTagExtension.create(), 071 TypographicExtension.create(), 072 TablesExtension.create(), 073 // fix for code handling 074 HtmlCodeRenderExtension.create(), 075 // to ensure that escaped characters are not lost 076 EscapedCharacterExtension.create(), 077 SuperscriptExtension.create(), 078 SubscriptExtension.create() 079 // AutolinkExtension.create() 080 ); 081 Parser.EXTENSIONS.set(options, extensions); 082 083 // AST processing expects this 084 Parser.FENCED_CODE_CONTENT_BLOCK.set(options, true); 085 // Parser.CODE_SOFT_LINE_BREAKS.set(options, true); 086 // Parser.PARSE_INNER_HTML_COMMENTS.set(options, true); 087 // Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE.set(options, true); 088 // Parser.HTML_COMMENT_BLOCKS_INTERRUPT_PARAGRAPH.set(options, true); 089 090 // disable the built in processor, since we are configuring a patched one 091 Parser.ASTERISK_DELIMITER_PROCESSOR.set(options, false); 092 093 // configure GitHub-flavored tables 094 TablesExtension.COLUMN_SPANS.set(options, false); 095 TablesExtension.APPEND_MISSING_COLUMNS.set(options, true); 096 TablesExtension.DISCARD_EXTRA_COLUMNS.set(options, true); 097 TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH.set(options, true); 098 099 // 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("“", "“"); 109 typographicReplacementMap.put("”", "”"); 110 // typographicReplacementMap.put("‘", "'"); 111 // typographicReplacementMap.put("’", "'"); 112 typographicReplacementMap.put("‘", "‘"); 113 typographicReplacementMap.put("’", "’"); 114 typographicReplacementMap.put("'", "’"); 115 // typographicReplacementMap.put("«", "<<"); 116 typographicReplacementMap.put("«", "«"); 117 // typographicReplacementMap.put("»", ">>"); 118 typographicReplacementMap.put("»", "»"); 119 // typographicReplacementMap.put("…", "..."); 120 typographicReplacementMap.put("…", "…"); 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}