From 1263f7a0831ddc03f983b556bb1415c19856a688 Mon Sep 17 00:00:00 2001 From: fantkolja Date: Thu, 19 Mar 2026 19:08:28 +0200 Subject: [PATCH 01/11] add extension --- antora-playbook.yml | 1 + lib/algolia-tags-extension.js | 74 +++++++++++++++++++++++++++++++++++ package-lock.json | 61 +++++++++++++++++++++++++++++ package.json | 1 + search-config.json | 2 +- 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 lib/algolia-tags-extension.js diff --git a/antora-playbook.yml b/antora-playbook.yml index e93d231f..d6e758bf 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -245,6 +245,7 @@ ui: static_files: [ netlify.toml ] antora: extensions: + - require: ./lib/algolia-tags-extension.js - require: ./node_modules/hazelcast-docs-tools/antora-extensions/api-json.js tags: - Favorites diff --git a/lib/algolia-tags-extension.js b/lib/algolia-tags-extension.js new file mode 100644 index 00000000..7415ea44 --- /dev/null +++ b/lib/algolia-tags-extension.js @@ -0,0 +1,74 @@ +'use strict' + +/** + * Antora extension: algolia-tags + * + * Fetches all facet values for the `tags` facet from the Algolia search index + * and registers them as a Handlebars helper so they are available in HBS + * templates as {{algolia-tags}}. + * + * The helper returns an array of tag value strings: + * ['hazelcast-5.6', 'hazelcast-5.7-snapshot', 'operator-5.16', ...] + * + * Example usage in a layout/partial: + * {{#each (algolia-tags)}} + *
  • {{this}}
  • + * {{/each}} + * + * Reads credentials from the playbook's site.keys: + * - docsearch_id → Algolia Application ID + * - docsearch_api → Algolia Search API key + * - docsearch_index → Algolia index name + * + * Usage in antora-playbook.yml: + * antora: + * extensions: + * - require: ./lib/algolia-tags-extension.js + */ + +const { searchClient } = require('@algolia/client-search') + +module.exports.register = function () { + const logger = this.getLogger('algolia-tags-extension') + let tags = [] + + this.on('playbookBuilt', async ({ playbook }) => { + const keys = playbook.site.keys || {} + const appId = keys.docsearch_id + const apiKey = keys.docsearch_api + const indexName = keys.docsearch_index + + if (!appId || !apiKey || !indexName) { + logger.warn('algolia-tags-extension: missing docsearch_id, docsearch_api, or docsearch_index in site.keys — skipping tag fetch') + return + } + + try { + logger.info(`algolia-tags-extension: fetching tags from index "${indexName}"`) + const client = searchClient(appId, apiKey) + const result = await client.searchForFacetValues({ + indexName, + facetName: 'tags', + searchForFacetValuesRequest: { maxFacetHits: 100 }, + }) + tags = (result.facetHits || []).map((hit) => hit.value) + logger.info(`algolia-tags-extension: fetched ${tags.length} tag(s)`) + } catch (err) { + logger.error(`algolia-tags-extension: failed to fetch Algolia tags — ${err.message}`) + } + }) + + this.on('uiLoaded', ({ uiCatalog }) => { + // Serialize the fetched hits into a self-contained HBS helper module. + // The page-composer loads helpers via requireFromString(contents, path), + // so the module must export the helper function directly. + const contents = Buffer.from(`'use strict'\nmodule.exports = () => ${JSON.stringify(tags)}`) + uiCatalog.addFile({ + type: 'helper', + path: 'helpers/algolia-tags.js', + stem: 'algolia-tags', + contents, + }) + logger.info('algolia-tags-extension: registered {{algolia-tags}} Handlebars helper') + }) +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b617f05d..9770b7f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@algolia/client-search": "^5.49.2", "@antora/pdf-extension": "^1.0.0-alpha.1", "hazelcast-docs-tools": "github:hazelcast/hazelcast-docs-tools#semver:2.3.5" }, @@ -20,6 +21,66 @@ "serve": "^13.0.2" } }, + "node_modules/@algolia/client-common": { + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.49.2.tgz", + "integrity": "sha512-bn0biLequn3epobCfjUqCxlIlurLr4RHu7RaE4trgN+RDcUq6HCVC3/yqq1hwbNYpVtulnTOJzcaxYlSr1fnuw==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.49.2.tgz", + "integrity": "sha512-y1IOpG6OSmTpGg/CT0YBb/EAhR2nsC18QWp9Jy8HO9iGySpcwaTvs5kHa17daP3BMTwWyaX9/1tDTDQshZzXdg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.49.2", + "@algolia/requester-browser-xhr": "5.49.2", + "@algolia/requester-fetch": "5.49.2", + "@algolia/requester-node-http": "5.49.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.49.2.tgz", + "integrity": "sha512-3UhYCcWX6fbtN8ABcxZlhaQEwXFh3CsFtARyyadQShHMPe3mJV9Wel4FpJTa+seugRkbezFz0tt6aPTZSYTBuA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.49.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.49.2.tgz", + "integrity": "sha512-G94VKSGbsr+WjsDDOBe5QDQ82QYgxvpxRGJfCHZBnYKYsy/jv9qGIDb93biza+LJWizQBUtDj7bZzp3QZyzhPQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.49.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.49.2.tgz", + "integrity": "sha512-UuihBGHafG/ENsrcTGAn5rsOffrCIRuHMOsD85fZGLEY92ate+BMTUqxz60dv5zerh8ZumN4bRm8eW2z9L11jA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.49.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/@antora/asciidoc-loader": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.7.tgz", diff --git a/package.json b/package.json index 2496cdda..d9b91e9c 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "serve": "^13.0.2" }, "dependencies": { + "@algolia/client-search": "^5.49.2", "@antora/pdf-extension": "^1.0.0-alpha.1", "hazelcast-docs-tools": "github:hazelcast/hazelcast-docs-tools#semver:2.3.5" } diff --git a/search-config.json b/search-config.json index dfc2225b..c0eefc02 100644 --- a/search-config.json +++ b/search-config.json @@ -397,7 +397,7 @@ }, "custom_settings": { "attributesForFaceting": [ - "tags" + "searchable(tags)" ], "distinct": true, "attributeForDistinct": "url_without_anchor", From 981577806538548f5e4df1426e9fe7a07f20b5cd Mon Sep 17 00:00:00 2001 From: fantkolja Date: Thu, 19 Mar 2026 23:05:43 +0200 Subject: [PATCH 02/11] add extension --- antora-playbook-local.yml | 1 + lib/algolia-tags-extension.js | 147 +++++++++++++++++++++++++--------- 2 files changed, 111 insertions(+), 37 deletions(-) diff --git a/antora-playbook-local.yml b/antora-playbook-local.yml index 3f464622..0045d360 100644 --- a/antora-playbook-local.yml +++ b/antora-playbook-local.yml @@ -220,6 +220,7 @@ ui: snapshot: true antora: extensions: + - require: ./lib/algolia-tags-extension.js - require: ./node_modules/hazelcast-docs-tools/antora-extensions/api-json.js tags: - Favorites diff --git a/lib/algolia-tags-extension.js b/lib/algolia-tags-extension.js index 7415ea44..f519f93d 100644 --- a/lib/algolia-tags-extension.js +++ b/lib/algolia-tags-extension.js @@ -3,22 +3,22 @@ /** * Antora extension: algolia-tags * - * Fetches all facet values for the `tags` facet from the Algolia search index - * and registers them as a Handlebars helper so they are available in HBS - * templates as {{algolia-tags}}. + * Fetches all facet values for the `tags` facet from the Algolia search index, + * parses each tag as "{component}-{version}", and registers a Handlebars helper + * that returns a map of component name → sorted version strings. * - * The helper returns an array of tag value strings: - * ['hazelcast-5.6', 'hazelcast-5.7-snapshot', 'operator-5.16', ...] + * Helper: (get-algolia-versions [componentName]) * - * Example usage in a layout/partial: - * {{#each (algolia-tags)}} - *
  • {{this}}
  • - * {{/each}} + * With a component name — returns a sorted version strings array for HBS iteration: + * {{#each (get-algolia-versions page.component.name)}} {{this}} {{/each}} * - * Reads credentials from the playbook's site.keys: - * - docsearch_id → Algolia Application ID - * - docsearch_api → Algolia Search API key - * - docsearch_index → Algolia index name + * Without arguments — returns SafeString JSON of the full map for