GeneratedSectionEmitter.java

  1. package docsite.emitters;


  2. import docsite.util.*;
  3. import j2html.tags.Tag;
  4. import java.nio.file.*;
  5. import java.util.regex.*;

  6. import docsite.*;
  7. import j2html.tags.specialized.*;
  8. import static docsite.util.EmitterUtil.*;
  9. import static j2html.TagCreator.*;

  10. public abstract class GeneratedSectionEmitter extends SectionEmitter {

  11.     private final String translatedOrigin;
  12.     private final boolean translationIsMissing;


  13.     GeneratedSectionEmitter(EmitterBuildParams params) {
  14.         super(params);
  15.         if (siteLanguage.isPrimary()) {
  16.             logger.info("Generating from original path "+super.origin());
  17.             translatedOrigin = super.origin();
  18.             translationIsMissing = false;
  19.         } else {
  20.             String localizedOrigen = EmitterUtil.withLanguage(siteLanguage, super.origin());
  21.             if (!ResourceUtil.existsSource(params.baseDir(),localizedOrigen)) {
  22.                 logger.info("Attempted to generate from localized path "+localizedOrigen+" but it doesnt exist");
  23.                 translatedOrigin = super.origin();
  24.                 translationIsMissing = true;
  25.             } else {
  26.                 logger.info("Generating from translated path "+localizedOrigen);
  27.                 translatedOrigin = localizedOrigen;
  28.                 translationIsMissing = false;
  29.             }
  30.         }
  31.     }


  32.     protected abstract SectionTag generateSectionContent(Tag<?> before);


  33.     @Override
  34.     protected SectionTag createSectionContent() {
  35.         if (translationIsMissing) {
  36.             return generateSectionContent(blockquote("There is no localized version of this page"));
  37.         } else {
  38.             return generateSectionContent(div());
  39.         }
  40.     }


  41.     @Override
  42.     protected String url() {
  43.         return EmitterUtil.page(section.name());
  44.     }


  45.     @Override
  46.     protected String url(SiteLanguage language) {
  47.         return EmitterUtil.page(section.name(), language);
  48.     }


  49.     @Override
  50.     public ATag createLinkToSection(boolean withIcon) {
  51.         return withIcon ?
  52.             internalLinkWithIcon(baseDir, translate(section.name()), url(siteLanguage), section.icon(), globalImages) :
  53.             internalLink(translate(section.name()), url(siteLanguage));
  54.     }


  55.     @Override
  56.     protected AsideTag createTableOfContents(SectionTag section) {
  57.         return createTableOfContentsFromHtml(section.render());
  58.     }


  59.     @Override
  60.     protected String origin() {
  61.         return translatedOrigin;
  62.     }


  63.     protected String replaceLocalImages(String html) {
  64.         Matcher matcher = Pattern.compile("<img .*src=\"([^\"]+)\".*>").matcher(html);
  65.         while (matcher.find()) {
  66.             String src = matcher.group(1);
  67.             if (src.startsWith("http")) {
  68.                 continue;
  69.             }
  70.             html = html.replace("src=\""+src+"\"", "src=\""+sectionImages.imageFile(src)+"\"");
  71.         }
  72.         return html;
  73.     }


  74.     protected String replaceMermaidDiagrams(String html) {
  75.         return html.replaceAll(
  76.             "<pre><code class=\"language-mermaid\">([^<]+)</code></pre>",
  77.             "<div class=\"mermaid\">$1</div>"
  78.         );
  79.     }


  80.     protected String hrefId(String name) {
  81.         return name.strip().toLowerCase().replace(" ", "-");
  82.     }


  83.     protected String normalizeLinks(String html) {
  84.         return html
  85.             .replaceAll(
  86.                 "<a href([^>]*)>([^<]*)<([^<]*)</a>",
  87.                 "<a target=\"_blank\" rel=\"external noreferrer noopener nofollow\" href$1>$2<$3</a>"
  88.             )
  89.             .replaceAll(
  90.                 "<a href([^>]*)>([^<]*)</a>",
  91.                 "<a class=\"external\" target=\"_blank\" rel=\"external noreferrer noopener nofollow\" href$1>$2</a>"
  92.             );
  93.     }


  94.     protected String removeH1(String html) {
  95.         return html.replaceAll("<h1>([^<]*)</h1>","");
  96.     }


  97.     protected String generateHeadersId(String html) {
  98.         String[] patterns = {"<(h\\d)>([^<]*)", "<(h\\d)><code>([^<]*)"};
  99.         for (String pattern : patterns) {
  100.             Matcher matcher = Pattern.compile(pattern).matcher(html);
  101.             while (matcher.find()) {
  102.                 String tag = matcher.group(1);
  103.                 String name = matcher.group(2);
  104.                 String id = hrefId(name);
  105.                 if (!id.isEmpty()) {
  106.                     html = html.replace("<" + tag + ">" + name, "<" + tag + " id=\"" + id + "\">" + name);
  107.                 }
  108.             }
  109.         }
  110.         return html;
  111.     }





  112.     protected AsideTag createTableOfContentsFromHtml(String html) {

  113.         Matcher matcher = Pattern.compile("<h(\\d)[^>]*>([^<]*)<").matcher(html);

  114.         StringBuilder string = new StringBuilder();
  115.         int previousLevel = TOC_MIN_LEVEL - 1;

  116.         boolean empty = true;

  117.         while (matcher.find()) {

  118.             int level = Integer.parseInt(matcher.group(1));
  119.             String name = matcher.group(2);
  120.             String id = hrefId(name);

  121.             if (level < TOC_MIN_LEVEL || level > TOC_MAX_LEVEL || id.isEmpty()) {
  122.                 continue;
  123.             }

  124.             if (previousLevel > level) {
  125.                 string.append("</ol>".repeat(Math.max(0, previousLevel - level)));
  126.             } else {
  127.                 string.append("<ol>".repeat(Math.max(0, level - previousLevel)));
  128.             }
  129.             string
  130.                 .append("<li><a class=\"internal\" href=\"#")
  131.                 .append(id)
  132.                 .append("\">")
  133.                 .append(name)
  134.                 .append("</a></li>");

  135.             previousLevel = level;
  136.             empty = false;
  137.         }

  138.         if (empty) {
  139.             return aside();
  140.         } else {
  141.             string.append("</ol>".repeat(previousLevel));
  142.             return aside().with(nav().with(rawHtml(string.toString())).withClass("toc"));
  143.         }

  144.     }

  145. }