diff --git a/znai-core/src/main/java/org/testingisdocumenting/znai/search/GlobalSearchEntry.java b/znai-core/src/main/java/org/testingisdocumenting/znai/search/GlobalSearchEntry.java
index 0bf97b21c..008a51940 100644
--- a/znai-core/src/main/java/org/testingisdocumenting/znai/search/GlobalSearchEntry.java
+++ b/znai-core/src/main/java/org/testingisdocumenting/znai/search/GlobalSearchEntry.java
@@ -1,4 +1,5 @@
/*
+ * Copyright 2025 znai maintainers
* Copyright 2019 TWO SIGMA OPEN SOURCE, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +17,10 @@
package org.testingisdocumenting.znai.search;
+import org.testingisdocumenting.znai.core.DocMeta;
+import org.testingisdocumenting.znai.markdown.PageMarkdownSection;
+import org.testingisdocumenting.znai.structure.TocItem;
+
import java.util.Objects;
/**
@@ -24,15 +29,37 @@
public class GlobalSearchEntry {
private String url;
private String fullTitle;
+ private String pageTitle;
+ private String chapterTitle;
+ private String pageSectionTitle;
private SearchText text;
public GlobalSearchEntry() {
}
- public GlobalSearchEntry(String url, String fullTitle, String text) {
+ public GlobalSearchEntry(DocMeta docMeta, TocItem tocItem, PageMarkdownSection section, String url) {
this.url = url;
- this.fullTitle = fullTitle;
- this.text = SearchScore.STANDARD.text(text);
+ this.fullTitle = buildFullTitle(tocItem, section, docMeta);
+ this.pageTitle = tocItem.getPageTitle();
+ this.chapterTitle = tocItem.getChapterTitle();
+ this.pageSectionTitle = section.title();
+ this.text = SearchScore.STANDARD.text(section.markdown());
+ }
+
+ private String buildFullTitle(TocItem tocItem, PageMarkdownSection section, DocMeta docMeta) {
+ if (tocItem.isIndex()) {
+ return docMeta.getTitle() + (section.title().isEmpty() ? "" : ": " + section.title());
+ }
+
+ String pageSectionPart = section.title().isEmpty() ?
+ "" :
+ ", " + section.title();
+
+ String chapterPart = tocItem.getChapterTitle().isEmpty() ?
+ "" :
+ " [" + tocItem.getChapterTitle() + "]";
+
+ return docMeta.getTitle() + ": " + tocItem.getPageTitle() + pageSectionPart + chapterPart;
}
public String getUrl() {
@@ -51,6 +78,30 @@ public void setFullTitle(String fullTitle) {
this.fullTitle = fullTitle;
}
+ public String getPageTitle() {
+ return pageTitle;
+ }
+
+ public void setPageTitle(String pageTitle) {
+ this.pageTitle = pageTitle;
+ }
+
+ public String getChapterTitle() {
+ return chapterTitle;
+ }
+
+ public void setChapterTitle(String chapterTitle) {
+ this.chapterTitle = chapterTitle;
+ }
+
+ public String getPageSectionTitle() {
+ return pageSectionTitle;
+ }
+
+ public void setPageSectionTitle(String pageSectionTitle) {
+ this.pageSectionTitle = pageSectionTitle;
+ }
+
public SearchText getText() {
return text;
}
@@ -71,11 +122,14 @@ public boolean equals(Object o) {
GlobalSearchEntry that = (GlobalSearchEntry) o;
return Objects.equals(url, that.url) &&
- Objects.equals(fullTitle, that.fullTitle);
+ Objects.equals(fullTitle, that.fullTitle) &&
+ Objects.equals(pageTitle, that.pageTitle) &&
+ Objects.equals(chapterTitle, that.chapterTitle) &&
+ Objects.equals(pageSectionTitle, that.pageSectionTitle);
}
@Override
public int hashCode() {
- return Objects.hash(url, fullTitle);
+ return Objects.hash(url, fullTitle, pageTitle, chapterTitle, pageSectionTitle);
}
}
diff --git a/znai-core/src/test/groovy/org/testingisdocumenting/znai/search/GlobalSearchEntriesTest.groovy b/znai-core/src/test/groovy/org/testingisdocumenting/znai/search/GlobalSearchEntriesTest.groovy
index ee57bef64..d27f71a7a 100644
--- a/znai-core/src/test/groovy/org/testingisdocumenting/znai/search/GlobalSearchEntriesTest.groovy
+++ b/znai-core/src/test/groovy/org/testingisdocumenting/znai/search/GlobalSearchEntriesTest.groovy
@@ -18,20 +18,41 @@
package org.testingisdocumenting.znai.search
import org.junit.Test
+import org.testingisdocumenting.znai.core.DocMeta
+import org.testingisdocumenting.znai.markdown.PageMarkdownSection
+import org.testingisdocumenting.znai.structure.TocItem
class GlobalSearchEntriesTest {
@Test
void "should generate XML document"() {
+ def docMeta = new DocMeta([title: 'Test Doc'])
+ def tocItem1 = new TocItem('chapter1', 'page1', 'md')
+ tocItem1.setPageTitleIfNoTocOverridePresent('page 1')
+ tocItem1.setChapterTitle('chapter 1')
+ def section1 = new PageMarkdownSection('section1', 'section 1', 'text 1')
+
+ def tocItem2 = new TocItem('chapter2', 'page2', 'md')
+ tocItem2.setPageTitleIfNoTocOverridePresent('page 2')
+ tocItem2.setChapterTitle('chapter 2')
+ def section2 = new PageMarkdownSection('section2', 'section 2', 'text 2')
+
+ def tocItemIndex = TocItem.createIndex()
+ def sectionIndex = new PageMarkdownSection('', '', 'index text')
+
def entries = new GlobalSearchEntries()
entries.addAll([
- new GlobalSearchEntry('/doc-id/title1', 'full title 1', 'text 1'),
- new GlobalSearchEntry('/doc-id/title2', 'full title 2', 'text 2')])
+ new GlobalSearchEntry(docMeta, tocItem1, section1, '/doc-id/title1'),
+ new GlobalSearchEntry(docMeta, tocItem2, section2, '/doc-id/title2'),
+ new GlobalSearchEntry(docMeta, tocItemIndex, sectionIndex, '/doc-id')])
println entries.toXml()
entries.toXml().should == '\n' +
' \n' +
' /doc-id/title1\n' +
- ' full title 1\n' +
+ ' Test Doc: page 1, section 1 [chapter 1]\n' +
+ ' page 1\n' +
+ ' chapter 1\n' +
+ ' section 1\n' +
' \n' +
' STANDARD\n' +
' text 1\n' +
@@ -39,28 +60,51 @@ class GlobalSearchEntriesTest {
' \n' +
' \n' +
' /doc-id/title2\n' +
- ' full title 2\n' +
+ ' Test Doc: page 2, section 2 [chapter 2]\n' +
+ ' page 2\n' +
+ ' chapter 2\n' +
+ ' section 2\n' +
' \n' +
' STANDARD\n' +
' text 2\n' +
' \n' +
' \n' +
+ ' \n' +
+ ' /doc-id\n' +
+ ' Test Doc\n' +
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ ' STANDARD\n' +
+ ' index text\n' +
+ ' \n' +
+ ' \n' +
'\n'
}
@Test
void "should handle ansi sequences"() {
+ def docMeta = new DocMeta([title: 'title', type: 'Guide'])
+ def tocItem = new TocItem('chapter', 'page', 'md')
+ tocItem.setPageTitleIfNoTocOverridePresent('page')
+ tocItem.setChapterTitle('chapter')
+ def section = new PageMarkdownSection('section', 'section',
+ "\u001B[1mwebtau:\u001B[m000\u001B" +
+ "[1m>\u001B[m http.get(\"https://jsonplaceholder.typicode.com/todos/1\")" +
+ " \u001B[33m> (\u001B[32m342ms\u001B[33m)\u001B[0m")
+
def entries = new GlobalSearchEntries()
entries.addAll([
- new GlobalSearchEntry('/doc-id/title', 'title',
- "\u001B[1mwebtau:\u001B[m000\u001B" +
- "[1m>\u001B[m http.get(\"https://jsonplaceholder.typicode.com/todos/1\")" +
- " \u001B[33m> (\u001B[32m342ms\u001B[33m)\u001B[0m")])
+ new GlobalSearchEntry(docMeta, tocItem, section, '/doc-id/title')])
entries.toXml().should == '\n' +
' \n' +
' /doc-id/title\n' +
- ' title\n' +
+ ' title: page, section [chapter]\n' +
+ ' page\n' +
+ ' chapter\n' +
+ ' section\n' +
' \n' +
' STANDARD\n' +
' webtau:000> http.get("https://jsonplaceholder.typicode.com/todos/1") > (342ms)\n' +
diff --git a/znai-docs/znai/release-notes/1.83/add-2025-11-09-search-entries-extra-fields.md b/znai-docs/znai/release-notes/1.83/add-2025-11-09-search-entries-extra-fields.md
new file mode 100644
index 000000000..500f35807
--- /dev/null
+++ b/znai-docs/znai/release-notes/1.83/add-2025-11-09-search-entries-extra-fields.md
@@ -0,0 +1 @@
+* Add: `search-entries.xml` add extra fields
\ No newline at end of file
diff --git a/znai-website-gen/src/main/java/org/testingisdocumenting/znai/website/WebSite.java b/znai-website-gen/src/main/java/org/testingisdocumenting/znai/website/WebSite.java
index 7f46ff5cd..ac17dbe59 100644
--- a/znai-website-gen/src/main/java/org/testingisdocumenting/znai/website/WebSite.java
+++ b/znai-website-gen/src/main/java/org/testingisdocumenting/znai/website/WebSite.java
@@ -590,11 +590,11 @@ private void updateTocItemWithPageMeta(TocItem tocItem, PageMeta pageMeta) {
private void updateSearchEntries(TocItem tocItem, MarkupParserResult parserResult) {
List siteSearchEntries = parserResult.markdown().sections().stream()
.filter(section -> !(section.title().isEmpty() && section.markdown().trim().isEmpty()))
- .map(section ->
- new GlobalSearchEntry(
- searchEntryUrl(tocItem, section),
- searchEntryTitle(tocItem, section),
- section.markdown()))
+ .map(section -> new GlobalSearchEntry(
+ docMeta,
+ tocItem,
+ section,
+ searchEntryUrl(tocItem, section)))
.collect(toList());
globalSearchEntries.addAll(siteSearchEntries);
@@ -609,23 +609,6 @@ private String searchEntryUrl(TocItem tocItem, PageMarkdownSection section) {
return docStructure.createUrl(null, docUrl);
}
- private String searchEntryTitle(TocItem tocItem, PageMarkdownSection section) {
- if (tocItem.isIndex()) {
- return docMeta.getTitle() + " " + (section.title().isEmpty() ?
- docMeta.getType() : section.title());
- }
-
- String pageSectionPart = section.title().isEmpty() ?
- "" :
- ", " + section.title();
-
- String chapterPart = tocItem.getChapterTitle().isEmpty() ?
- "" :
- " [" + tocItem.getChapterTitle() + "]";
-
- return docMeta.getTitle() + ": " + tocItem.getPageTitle() + pageSectionPart + chapterPart;
- }
-
// each markup file may refer other files like code snippets or diagrams
// we maintain dependency between them, so we know which one triggers what page refresh during preview mode
//