GeneratedSectionEmitter.java
package docsite.emitters;
import docsite.util.*;
import j2html.tags.Tag;
import java.nio.file.*;
import java.util.regex.*;
import docsite.*;
import j2html.tags.specialized.*;
import static docsite.util.EmitterUtil.*;
import static j2html.TagCreator.*;
public abstract class GeneratedSectionEmitter extends SectionEmitter {
private final String translatedOrigin;
private final boolean translationIsMissing;
GeneratedSectionEmitter(EmitterBuildParams params) {
super(params);
if (siteLanguage.isPrimary()) {
logger.info("Generating from original path "+super.origin());
translatedOrigin = super.origin();
translationIsMissing = false;
} else {
String localizedOrigen = EmitterUtil.withLanguage(siteLanguage, super.origin());
if (!ResourceUtil.existsSource(params.baseDir(),localizedOrigen)) {
logger.info("Attempted to generate from localized path "+localizedOrigen+" but it doesnt exist");
translatedOrigin = super.origin();
translationIsMissing = true;
} else {
logger.info("Generating from translated path "+localizedOrigen);
translatedOrigin = localizedOrigen;
translationIsMissing = false;
}
}
}
protected abstract SectionTag generateSectionContent(Tag<?> before);
@Override
protected SectionTag createSectionContent() {
if (translationIsMissing) {
return generateSectionContent(blockquote("There is no localized version of this page"));
} else {
return generateSectionContent(div());
}
}
@Override
protected String url() {
return EmitterUtil.page(section.name());
}
@Override
protected String url(SiteLanguage language) {
return EmitterUtil.page(section.name(), language);
}
@Override
public ATag createLinkToSection(boolean withIcon) {
return withIcon ?
internalLinkWithIcon(baseDir, translate(section.name()), url(siteLanguage), section.icon(), globalImages) :
internalLink(translate(section.name()), url(siteLanguage));
}
@Override
protected AsideTag createTableOfContents(SectionTag section) {
return createTableOfContentsFromHtml(section.render());
}
@Override
protected String origin() {
return translatedOrigin;
}
protected String replaceLocalImages(String html) {
Matcher matcher = Pattern.compile("<img .*src=\"([^\"]+)\".*>").matcher(html);
while (matcher.find()) {
String src = matcher.group(1);
if (src.startsWith("http")) {
continue;
}
html = html.replace("src=\""+src+"\"", "src=\""+sectionImages.imageFile(src)+"\"");
}
return html;
}
protected String replaceMermaidDiagrams(String html) {
return html.replaceAll(
"<pre><code class=\"language-mermaid\">([^<]+)</code></pre>",
"<div class=\"mermaid\">$1</div>"
);
}
protected String hrefId(String name) {
return name.strip().toLowerCase().replace(" ", "-");
}
protected String normalizeLinks(String html) {
return html
.replaceAll(
"<a href([^>]*)>([^<]*)<([^<]*)</a>",
"<a target=\"_blank\" rel=\"external noreferrer noopener nofollow\" href$1>$2<$3</a>"
)
.replaceAll(
"<a href([^>]*)>([^<]*)</a>",
"<a class=\"external\" target=\"_blank\" rel=\"external noreferrer noopener nofollow\" href$1>$2</a>"
);
}
protected String removeH1(String html) {
return html.replaceAll("<h1>([^<]*)</h1>","");
}
protected String generateHeadersId(String html) {
String[] patterns = {"<(h\\d)>([^<]*)", "<(h\\d)><code>([^<]*)"};
for (String pattern : patterns) {
Matcher matcher = Pattern.compile(pattern).matcher(html);
while (matcher.find()) {
String tag = matcher.group(1);
String name = matcher.group(2);
String id = hrefId(name);
if (!id.isEmpty()) {
html = html.replace("<" + tag + ">" + name, "<" + tag + " id=\"" + id + "\">" + name);
}
}
}
return html;
}
protected AsideTag createTableOfContentsFromHtml(String html) {
Matcher matcher = Pattern.compile("<h(\\d)[^>]*>([^<]*)<").matcher(html);
StringBuilder string = new StringBuilder();
int previousLevel = TOC_MIN_LEVEL - 1;
boolean empty = true;
while (matcher.find()) {
int level = Integer.parseInt(matcher.group(1));
String name = matcher.group(2);
String id = hrefId(name);
if (level < TOC_MIN_LEVEL || level > TOC_MAX_LEVEL || id.isEmpty()) {
continue;
}
if (previousLevel > level) {
string.append("</ol>".repeat(Math.max(0, previousLevel - level)));
} else {
string.append("<ol>".repeat(Math.max(0, level - previousLevel)));
}
string
.append("<li><a class=\"internal\" href=\"#")
.append(id)
.append("\">")
.append(name)
.append("</a></li>");
previousLevel = level;
empty = false;
}
if (empty) {
return aside();
} else {
string.append("</ol>".repeat(previousLevel));
return aside().with(nav().with(rawHtml(string.toString())).withClass("toc"));
}
}
}