diff --git a/src/main/java/com/elovirta/dita/markdown/MarkdownParserImpl.java b/src/main/java/com/elovirta/dita/markdown/MarkdownParserImpl.java index e351d87..67ee7cf 100644 --- a/src/main/java/com/elovirta/dita/markdown/MarkdownParserImpl.java +++ b/src/main/java/com/elovirta/dita/markdown/MarkdownParserImpl.java @@ -1,5 +1,6 @@ package com.elovirta.dita.markdown; +import com.elovirta.dita.markdown.renderer.HeaderIdGenerator; import com.vladsch.flexmark.ast.Heading; import com.vladsch.flexmark.ast.Text; import com.vladsch.flexmark.ext.anchorlink.AnchorLink; @@ -11,6 +12,7 @@ import com.vladsch.flexmark.util.data.DataSet; import com.vladsch.flexmark.util.sequence.BasedSequence; import java.net.URI; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ResourceBundle; @@ -130,16 +132,17 @@ protected void validate(Document root) { * If document doesn't start with H1, generate H1 from YAML metadata or file name. */ protected Document preprocess(Document root, URI input) throws SAXException { - if (isWiki(root)) { + if (isWiki(root) && !DitaRenderer.MAP.get(options)) { + final Map header = parseYamlHeader(root); if (DitaRenderer.WIKI.get(options)) { - generateRootHeading(root, input); + generateRootHeading(root, header.get("id"), header.getOrDefault("title", getTextFromFile(input))); } else if (DitaRenderer.FIX_ROOT_HEADING.get(options)) { if (errorHandler != null) { errorHandler.warning( new SAXParseException(MESSAGES.getString("error.missing_title"), null, input.toString(), 1, 1) ); } - generateRootHeading(root, input); + generateRootHeading(root, header.get("id"), header.getOrDefault("title", getTextFromFile(input))); } else if (MarkdownReader.PROCESSING_MODE.get(options)) { if (errorHandler != null) { errorHandler.error( @@ -152,43 +155,51 @@ protected Document preprocess(Document root, URI input) throws SAXException { new SAXParseException(MESSAGES.getString("error.missing_title"), null, input.toString(), 1, 1) ); } - generateRootHeading(root, getTextFromFile(input).toLowerCase().trim().replaceAll("[\\s_]+", "-"), null); + String id = header.get("id"); + if (id == null) { + id = + HeaderIdGenerator.generateId( + getTextFromFile(input), + DitaRenderer.HEADER_ID_GENERATOR_TO_DASH_CHARS.get(root), + DitaRenderer.HEADER_ID_GENERATOR_NO_DUPED_DASHES.get(root) + ); + } + generateRootHeading(root, id, header.get("title")); } } return root; } - /** - * Generate root heading using YAML header or input file name. If neither YAML or file name is not available, create empty heading. - * - */ - private void generateRootHeading(Document root, URI input) { + private static String getId(final String contents) { + return contents.toLowerCase().replaceAll("[^\\w\\s]", "").trim().replaceAll("\\s+", "-"); + } + + private Map parseYamlHeader(Document root) { + Map res = new HashMap<>(); final YamlFrontMatterBlock yaml = root.getFirstChild() instanceof YamlFrontMatterBlock ? (YamlFrontMatterBlock) root.getFirstChild() : null; - String title = getTextFromFile(input); - String id = null; if (yaml != null) { final AbstractYamlFrontMatterVisitor v = new AbstractYamlFrontMatterVisitor(); v.visit(root); final Map> metadata = v.getData(); final List ids = metadata.get("id"); if (ids != null && !ids.isEmpty()) { - id = ids.get(0); + res.put("id", ids.get(0)); } final List titles = metadata.get("title"); if (titles != null && !titles.isEmpty()) { - title = titles.get(0); + String title = titles.get(0); if ( (title.charAt(0) == '\'' && title.charAt(title.length() - 1) == '\'') || (title.charAt(0) == '"' && title.charAt(title.length() - 1) == '"') ) { title = title.substring(1, title.length() - 1); } + res.put("title", title); } } - - generateRootHeading(root, id, title); + return res; } private void generateRootHeading(Document root, String id, String title) { @@ -197,10 +208,12 @@ private void generateRootHeading(Document root, String id, String title) { heading.setAnchorRefId(id); } heading.setLevel(1); - if (title != null) { + if (id == null) { final AnchorLink anchorLink = new AnchorLink(); - anchorLink.appendChild(new Text(title)); + anchorLink.appendChild(new Text(title != null ? title : "")); heading.appendChild(anchorLink); + } else { + heading.appendChild(new Text(title != null ? title : "")); } root.prependChild(heading); } diff --git a/src/main/java/com/elovirta/dita/markdown/MarkdownReader.java b/src/main/java/com/elovirta/dita/markdown/MarkdownReader.java index cabfc09..80e35ed 100644 --- a/src/main/java/com/elovirta/dita/markdown/MarkdownReader.java +++ b/src/main/java/com/elovirta/dita/markdown/MarkdownReader.java @@ -91,6 +91,7 @@ public class MarkdownReader implements XMLReader { features.put("http://lwdita.org/sax/features/specialization-concept", DitaRenderer.SPECIALIZATION_CONCEPT); features.put("http://lwdita.org/sax/features/specialization-task", DitaRenderer.SPECIALIZATION_TASK); features.put("http://lwdita.org/sax/features/specialization-reference", DitaRenderer.SPECIALIZATION_REFERENCE); + features.put("http://lwdita.org/sax/features/wiki", DitaRenderer.WIKI); features.put("http://lwdita.org/sax/features/fix-root-heading", DitaRenderer.FIX_ROOT_HEADING); features.put("http://lwdita.org/sax/features/map", DitaRenderer.MAP); FEATURES = Collections.unmodifiableMap(features); @@ -132,7 +133,7 @@ public MarkdownReader() { .set(TablesExtension.DISCARD_EXTRA_COLUMNS, true) .set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true) .set(DitaRenderer.SPECIALIZATION, true) - .set(DitaRenderer.WIKI, true) + .set(DitaRenderer.ID_FROM_YAML, true) ); } diff --git a/src/main/plugin.xml b/src/main/plugin.xml index 5288244..3896b76 100644 --- a/src/main/plugin.xml +++ b/src/main/plugin.xml @@ -48,6 +48,7 @@ + diff --git a/src/test/java/com/elovirta/dita/markdown/MarkdownReaderTest.java b/src/test/java/com/elovirta/dita/markdown/MarkdownReaderTest.java index ec1da2b..b4de991 100644 --- a/src/test/java/com/elovirta/dita/markdown/MarkdownReaderTest.java +++ b/src/test/java/com/elovirta/dita/markdown/MarkdownReaderTest.java @@ -136,26 +136,21 @@ public void test_missingHeader(String file) throws Exception { new MutableDataSet() .set(Parser.EXTENSIONS, singletonList(YamlFrontMatterExtension.create())) .set(DitaRenderer.FIX_ROOT_HEADING, true) + .set(DitaRenderer.ID_FROM_YAML, true) + .set(DitaRenderer.WIKI, true) ); final TestErrorHandler errorHandler = new TestErrorHandler(); reader.setErrorHandler(errorHandler); run(getSrc() + file, getExp() + "wiki/" + file.replaceAll("\\.md$", ".dita")); - assertEquals(1, errorHandler.warnings.size()); - final SAXParseException e = errorHandler.warnings.get(0); - assertEquals("Document content doesn't start with heading", e.getMessage()); - assertEquals("classpath:/markdown/" + file, e.getSystemId()); - assertNull(e.getPublicId()); - assertEquals(1, e.getLineNumber()); - assertEquals(1, e.getColumnNumber()); + assertEquals(0, errorHandler.warnings.size()); } @ParameterizedTest @ValueSource(strings = { "missing_root_header.md", "missing_root_header_with_yaml.md" }) public void test_emptyHeader(String file) throws Exception { - reader = - new MarkdownReader(new MutableDataSet().set(Parser.EXTENSIONS, singletonList(YamlFrontMatterExtension.create()))); + reader = new MarkdownReader(); final TestErrorHandler errorHandler = new TestErrorHandler(); reader.setErrorHandler(errorHandler); diff --git a/src/test/resources/dita/missing_root_header_with_yaml.dita b/src/test/resources/dita/missing_root_header_with_yaml.dita index fdf4b13..63d8edd 100644 --- a/src/test/resources/dita/missing_root_header_with_yaml.dita +++ b/src/test/resources/dita/missing_root_header_with_yaml.dita @@ -1,7 +1,7 @@ - + id="yaml-id" ditaarch:DITAArchVersion="2.0"> + YAML Title

Root topic content.

diff --git a/src/test/resources/dita/wiki/missing_root_header_with_yaml.dita b/src/test/resources/dita/wiki/missing_root_header_with_yaml.dita index cf4581e..63d8edd 100644 --- a/src/test/resources/dita/wiki/missing_root_header_with_yaml.dita +++ b/src/test/resources/dita/wiki/missing_root_header_with_yaml.dita @@ -1,6 +1,6 @@ + id="yaml-id" ditaarch:DITAArchVersion="2.0"> YAML Title

Root topic content.

diff --git a/src/test/resources/dita/yaml.dita b/src/test/resources/dita/yaml.dita index e5b8f16..324b2a3 100644 --- a/src/test/resources/dita/yaml.dita +++ b/src/test/resources/dita/yaml.dita @@ -1,6 +1,6 @@ + id="extended-profile" ditaarch:DITAArchVersion="2.0"> YAML Header Author One @@ -22,7 +22,6 @@ - diff --git a/src/test/resources/output/ast/missing_root_header.xml b/src/test/resources/output/ast/missing_root_header.xml index 015ecaa..1f99013 100644 --- a/src/test/resources/output/ast/missing_root_header.xml +++ b/src/test/resources/output/ast/missing_root_header.xml @@ -1 +1 @@ -
missing root header
Root topic content.
Nested Topic
Nested topic content.
\ No newline at end of file +
Root topic content.
Nested Topic
Nested topic content.
\ No newline at end of file diff --git a/src/test/resources/output/ast/missing_root_header_with_yaml.xml b/src/test/resources/output/ast/missing_root_header_with_yaml.xml index eb94329..21ea096 100644 --- a/src/test/resources/output/ast/missing_root_header_with_yaml.xml +++ b/src/test/resources/output/ast/missing_root_header_with_yaml.xml @@ -1 +1 @@ -
YAML Title
Root topic content.
\ No newline at end of file +
YAML Title
Root topic content.
\ No newline at end of file diff --git a/src/test/resources/output/ast/yaml.xml b/src/test/resources/output/ast/yaml.xml index 9ce28b1..972ecf6 100644 --- a/src/test/resources/output/ast/yaml.xml +++ b/src/test/resources/output/ast/yaml.xml @@ -1 +1 @@ -
YAML Header
\ No newline at end of file +
YAML Header
\ No newline at end of file diff --git a/src/test/resources/output/markdown/missing_root_header.md b/src/test/resources/output/markdown/missing_root_header.md index 6f9f5b2..58064ba 100644 --- a/src/test/resources/output/markdown/missing_root_header.md +++ b/src/test/resources/output/markdown/missing_root_header.md @@ -1,4 +1,4 @@ -# missing root header {#missing-root-header} +# {#missing-root-header} Root topic content. diff --git a/src/test/resources/output/markdown/missing_root_header_with_yaml.md b/src/test/resources/output/markdown/missing_root_header_with_yaml.md index a8e933c..f8a2f31 100644 --- a/src/test/resources/output/markdown/missing_root_header_with_yaml.md +++ b/src/test/resources/output/markdown/missing_root_header_with_yaml.md @@ -1,4 +1,4 @@ -# YAML Title {#yaml-title} +# YAML Title {#yaml-id} Root topic content. diff --git a/src/test/resources/output/markdown/yaml.md b/src/test/resources/output/markdown/yaml.md index 1e24ec2..45912a1 100644 --- a/src/test/resources/output/markdown/yaml.md +++ b/src/test/resources/output/markdown/yaml.md @@ -1,2 +1,2 @@ -# YAML Header {#yaml-header} +# YAML Header {#extended-profile}