From d83dbee0a54ed9a7313fae03addff7488b562837 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Mon, 28 Sep 2026 17:45:52 +0200 Subject: [PATCH 1/8] Fix Unicode white space text being uploaded to Algolia --- layouts/_default/list.mxdocsalgolia.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index 5b0e0d6284d..e2cc3416e85 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -121,7 +121,8 @@ Define Global variables {{- $scratch.SetInMap $uniqueHit "h6" $h6 -}} {{- $uniqueHierarchy = printf "%s > %s" $uniqueHierarchy $h6 -}} {{- end -}} - {{- $text = trim (htmlUnescape ($processSlice | plainify)) " " -}} + {{- /* strings.TrimSpace strips all Unicode whitespace including \r, \n, \t, and non-breaking spaces ( ) that trim " " misses */ -}} + {{- $text = strings.TrimSpace (htmlUnescape ($processSlice | plainify)) -}} {{- $scratch.SetInMap $uniqueHit "text" $text -}} {{- $scratch.SetInMap $uniqueHit "mendix_version" $pageDot.Params.mendix_version -}} {{- $scratch.SetInMap $uniqueHit "time_stamp" $pageDot.Lastmod.UTC.Unix -}} From bd1a2f94fa14b6f9608bfef033dc5a49307289c6 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Mon, 28 Sep 2026 17:47:18 +0200 Subject: [PATCH 2/8] Fix whitespace in heading fields uploaded to Algolia After plainify strips HTML tags from heading elements, trailing \r, \n, and other whitespace remained in the h2-h6 fields because htmlUnescape alone does not trim. This caused dirty values in those fields and in the unique_hierarchy breadcrumb string. Replaced htmlUnescape with strings.TrimSpace (htmlUnescape ...) for all five heading levels. Co-Authored-By: Claude Sonnet 4.6 --- layouts/_default/list.mxdocsalgolia.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index e2cc3416e85..5637f341c96 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -70,25 +70,25 @@ Define Global variables {{- $startSlice = slicestr $processSlice 0 3 -}} {{- /* Set up the heading level we are in */ -}} {{- if eq $startSlice " Date: Tue, 29 Sep 2026 10:27:33 +0200 Subject: [PATCH 3/8] Add heading anchors to Algolia record URLs Each content record's url field now includes a fragment pointing to the deepest heading in scope (e.g. /refguide/entities/#entity-types). Hugo's rendered HTML already carries id attributes on all headings, so the id is extracted with findRE as each heading chunk is processed and tracked per level alongside the existing heading text variables. The deepest non-empty anchor is appended when writing the url field, so search results in Algolia link directly to the relevant section rather than the top of the page. Co-Authored-By: Claude Sonnet 4.6 --- layouts/_default/list.mxdocsalgolia.json | 46 +++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index 5637f341c96..79859202cb7 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -59,6 +59,11 @@ Define Global variables {{- $h4 := "" }} {{- $h5 := "" }} {{- $h6 := "" }} + {{- $h2anchor := "" }} + {{- $h3anchor := "" }} + {{- $h4anchor := "" }} + {{- $h5anchor := "" }} + {{- $h6anchor := "" }} {{- $text := "" }} {{- range $processSlice := $contentSlices -}} {{- /* sliceNumber tells us where we are in the file and gives us a way of making each hit unique */ -}} @@ -71,24 +76,50 @@ Define Global variables {{- /* Set up the heading level we are in */ -}} {{- if eq $startSlice " Date: Tue, 29 Sep 2026 11:32:07 +0200 Subject: [PATCH 4/8] Add explanatory comment block to Algolia index template Replaces the brief original comment with a full description of the template's purpose, page selection criteria, content splitting approach, heading context tracking, record fields, and empty-text exclusion. Co-Authored-By: Claude Sonnet 4.6 --- layouts/_default/list.mxdocsalgolia.json | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index 79859202cb7..9ff0a7eac44 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -1,6 +1,26 @@ {{- /* -Algolia generation based on this blog: https://web.archive.org/web/20201109041339/https://forestry.io/blog/search-with-algolia-in-hugo/ -Define Global variables +Algolia search index generator — based on https://web.archive.org/web/20201109041339/https://forestry.io/blog/search-with-algolia-in-hugo/ + +Outputs a JSON array of Algolia records, one per content chunk per page. + +Pages included: all non-draft, non-private pages of type "docs" or "swagger" +that are descendants of the current section. + +How records are created: +1. Each page's rendered HTML is split on heading tags (h2–h6), paragraph, + list item, table cell, alert div, and code block tags. This produces one + chunk per distinct piece of content. +2. As chunks are processed, heading context (h2–h6 text and id anchors) is + tracked and updated. When a higher-level heading is encountered, all + deeper heading levels are reset. +3. Heading chunks themselves are never written as records. Only non-heading + chunks produce a record, carrying the current heading context as fields. +4. Each record includes: objectID (unique per chunk), title, h2–h6 heading + text, text (plain content), url (page URL with #anchor of deepest heading + in scope), unique_hierarchy (breadcrumb string), slug, description, + content_type, type, mendix_version, menu_order, time_stamp, weight.position, + and weight.tag_name (p / li / th / td / code / alert). +5. Records with empty text are excluded. */ -}} {{- $firstloop := true -}} {{- /* Use a local scratchpad - Page scratchpad already contains other stuff */ -}} From fe12aa349bcded659df3aad24a550164e8647b1c Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Mon, 28 Sep 2026 17:45:52 +0200 Subject: [PATCH 5/8] Fix Unicode white space text being uploaded to Algolia --- layouts/_default/list.mxdocsalgolia.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index 5b0e0d6284d..e2cc3416e85 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -121,7 +121,8 @@ Define Global variables {{- $scratch.SetInMap $uniqueHit "h6" $h6 -}} {{- $uniqueHierarchy = printf "%s > %s" $uniqueHierarchy $h6 -}} {{- end -}} - {{- $text = trim (htmlUnescape ($processSlice | plainify)) " " -}} + {{- /* strings.TrimSpace strips all Unicode whitespace including \r, \n, \t, and non-breaking spaces ( ) that trim " " misses */ -}} + {{- $text = strings.TrimSpace (htmlUnescape ($processSlice | plainify)) -}} {{- $scratch.SetInMap $uniqueHit "text" $text -}} {{- $scratch.SetInMap $uniqueHit "mendix_version" $pageDot.Params.mendix_version -}} {{- $scratch.SetInMap $uniqueHit "time_stamp" $pageDot.Lastmod.UTC.Unix -}} From 5aefbd87521ba302a9f1abc504104a33ed5f9930 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Mon, 28 Sep 2026 17:47:18 +0200 Subject: [PATCH 6/8] Fix whitespace in heading fields uploaded to Algolia After plainify strips HTML tags from heading elements, trailing \r, \n, and other whitespace remained in the h2-h6 fields because htmlUnescape alone does not trim. This caused dirty values in those fields and in the unique_hierarchy breadcrumb string. Replaced htmlUnescape with strings.TrimSpace (htmlUnescape ...) for all five heading levels. Co-Authored-By: Claude Sonnet 4.6 --- layouts/_default/list.mxdocsalgolia.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index e2cc3416e85..5637f341c96 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -70,25 +70,25 @@ Define Global variables {{- $startSlice = slicestr $processSlice 0 3 -}} {{- /* Set up the heading level we are in */ -}} {{- if eq $startSlice " Date: Tue, 29 Sep 2026 10:27:33 +0200 Subject: [PATCH 7/8] Add heading anchors to Algolia record URLs Each content record's url field now includes a fragment pointing to the deepest heading in scope (e.g. /refguide/entities/#entity-types). Hugo's rendered HTML already carries id attributes on all headings, so the id is extracted with findRE as each heading chunk is processed and tracked per level alongside the existing heading text variables. The deepest non-empty anchor is appended when writing the url field, so search results in Algolia link directly to the relevant section rather than the top of the page. Co-Authored-By: Claude Sonnet 4.6 --- layouts/_default/list.mxdocsalgolia.json | 46 +++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index 5637f341c96..79859202cb7 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -59,6 +59,11 @@ Define Global variables {{- $h4 := "" }} {{- $h5 := "" }} {{- $h6 := "" }} + {{- $h2anchor := "" }} + {{- $h3anchor := "" }} + {{- $h4anchor := "" }} + {{- $h5anchor := "" }} + {{- $h6anchor := "" }} {{- $text := "" }} {{- range $processSlice := $contentSlices -}} {{- /* sliceNumber tells us where we are in the file and gives us a way of making each hit unique */ -}} @@ -71,24 +76,50 @@ Define Global variables {{- /* Set up the heading level we are in */ -}} {{- if eq $startSlice " Date: Tue, 29 Sep 2026 11:32:07 +0200 Subject: [PATCH 8/8] Add explanatory comment block to Algolia index template Replaces the brief original comment with a full description of the template's purpose, page selection criteria, content splitting approach, heading context tracking, record fields, and empty-text exclusion. Co-Authored-By: Claude Sonnet 4.6 --- layouts/_default/list.mxdocsalgolia.json | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/layouts/_default/list.mxdocsalgolia.json b/layouts/_default/list.mxdocsalgolia.json index 79859202cb7..9ff0a7eac44 100644 --- a/layouts/_default/list.mxdocsalgolia.json +++ b/layouts/_default/list.mxdocsalgolia.json @@ -1,6 +1,26 @@ {{- /* -Algolia generation based on this blog: https://web.archive.org/web/20201109041339/https://forestry.io/blog/search-with-algolia-in-hugo/ -Define Global variables +Algolia search index generator — based on https://web.archive.org/web/20201109041339/https://forestry.io/blog/search-with-algolia-in-hugo/ + +Outputs a JSON array of Algolia records, one per content chunk per page. + +Pages included: all non-draft, non-private pages of type "docs" or "swagger" +that are descendants of the current section. + +How records are created: +1. Each page's rendered HTML is split on heading tags (h2–h6), paragraph, + list item, table cell, alert div, and code block tags. This produces one + chunk per distinct piece of content. +2. As chunks are processed, heading context (h2–h6 text and id anchors) is + tracked and updated. When a higher-level heading is encountered, all + deeper heading levels are reset. +3. Heading chunks themselves are never written as records. Only non-heading + chunks produce a record, carrying the current heading context as fields. +4. Each record includes: objectID (unique per chunk), title, h2–h6 heading + text, text (plain content), url (page URL with #anchor of deepest heading + in scope), unique_hierarchy (breadcrumb string), slug, description, + content_type, type, mendix_version, menu_order, time_stamp, weight.position, + and weight.tag_name (p / li / th / td / code / alert). +5. Records with empty text are excluded. */ -}} {{- $firstloop := true -}} {{- /* Use a local scratchpad - Page scratchpad already contains other stuff */ -}}