@redpanda-data/docs-extensions-and-macros 2.5.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.adoc CHANGED
@@ -1,5 +1,7 @@
1
1
  = Antora Extensions and Macros for Redpanda Docs
2
- :url-project: https://github.com/JakeSCahill/antora-extensions-and-macros
2
+ :url-org: https://github.com/redpanda-data
3
+ :url-project: {url-org}/docs-extensions-and-macros
4
+ :url-playbook: {url-org}/docs-site
3
5
  :url-git: https://git-scm.com
4
6
  :url-git-dl: {url-git}/downloads
5
7
  :url-nodejs: https://nodejs.org
@@ -33,7 +35,7 @@ When you have Node.js installed, use the following command to install the `antor
33
35
 
34
36
  [,bash]
35
37
  ----
36
- npm i antora-extensions-and-macros
38
+ npm i @redpanda-data/docs-extensions-and-macros
37
39
  ----
38
40
 
39
41
  To use the development version instead, refer to the <<development-quickstart,Development Quickstart>>.
@@ -70,7 +72,7 @@ Whether to index all versions or just the latest version of a component.
70
72
  ```yaml
71
73
  antora:
72
74
  extensions:
73
- - require: 'node_modules/antora-extensions-and-macros/extensions/algolia-indexer/index.js'
75
+ - require: '@redpanda-data/docs-extensions-and-macros/extensions/algolia-indexer/index'
74
76
  excludes: ['.thumbs','script', '.page-versions','.feedback-section','.banner-container']
75
77
  index-latest-only: true
76
78
  ```
@@ -92,48 +94,19 @@ NOTE: If you don't set the environment variable, the latest versions may not be
92
94
  ```yaml
93
95
  antora:
94
96
  extensions:
95
- - 'node_modules/antora-extensions-and-macros/extensions/version-fetcher/set-latest-version.js'
97
+ - '@redpanda-data/docs-extensions-and-macros/extensions/version-fetcher/set-latest-version'
96
98
  ```
97
99
 
98
100
  === Global attributes
99
101
 
100
- This extension fetches the content of all YAML files in a GitHub directory and merges the contents with the `asciidoc.attributes` object in the Antora playbook. This allows you to define Asciidoc attributes in an external repository and automatically include them in your documentation.
101
-
102
- [IMPORTANT]
103
- ====
104
- - The GitHub directory that contains the global attributes must be named `global-attributes`.
105
- - Only YAML files are supported. Other types of files are ignored.
106
- - If a key is present in both the global attributes and the playbook's `asciidoc.attributes`, the value in the playbook takes precedence.
107
- ====
108
-
109
- ==== Environment variables
110
-
111
- - `GLOBAL_ATTRIBUTES_GITHUB_TOKEN` (optional): A Personal access token (PAT) that has `repo` permissions for the GitHub organization defined in `org`.
112
-
113
- NOTE: If you don't set the environment variable, global attributes may not be made available to your build. When the environment variable is not set, the extension sends unauthenticated requests to GitHub. Unauthenticated requests may result in hitting the API rate limit and cause GitHub to reject the request.
114
-
115
- ==== Configuration options
116
-
117
- The extension accepts the following configuration options:
118
-
119
- org (required)::
120
- The GitHub organization that owns the repository.
121
-
122
- repo (required)::
123
- The name of the repository.
124
-
125
- branch (required)::
126
- The branch in the repository where the global attributes are located.
102
+ This extension collects Asciidoc attributes from the {url-playbook}[`shared` component] and makes them available to all component versions. Having global attributes is useful for consistent configuration of local and production builds.
127
103
 
128
104
  ==== Registration example
129
105
 
130
106
  ```yaml
131
107
  antora:
132
108
  extensions:
133
- - require: 'node_modules/antora-extensions-and-macros/extensions/add-global-attributes.js'
134
- org: example
135
- repo: test
136
- branch: main
109
+ - require: '@redpanda-data/docs-extensions-and-macros/extensions/add-global-attributes'
137
110
  ```
138
111
 
139
112
  === Replace attributes in attachments
@@ -142,7 +115,7 @@ This extension replaces AsciiDoc attribute placeholders with their respective va
142
115
 
143
116
  [IMPORTANT]
144
117
  ====
145
- - By default, this extension processes attachments for the `ROOT` (redpanda) component only. This behavior is hardcoded and cannot be changed in the configuration.
118
+ - This extension processes attachments only if the component version includes the attribute `replace-attributes-in-attachments: true`.
146
119
  - The `@` character is removed from attribute values to prevent potential issues with CSS or HTML syntax.
147
120
  - If the same attribute placeholder is used multiple times within a file, all instances will be replaced with the attribute's value.
148
121
  ====
@@ -152,7 +125,23 @@ This extension replaces AsciiDoc attribute placeholders with their respective va
152
125
  ```yaml
153
126
  antora:
154
127
  extensions:
155
- - 'node_modules/antora-extensions-and-macros/extensions/replace-attributes-in-attachments.js'
128
+ - '@redpanda-data/docs-extensions-and-macros/extensions/replace-attributes-in-attachments'
129
+ ```
130
+
131
+ === Aggregate terms
132
+
133
+ This extension aggregates all term pages from the {url-playbook}[`shared` component] and does the following:
134
+
135
+ - Makes all `term-name` and `hover-text` attributes available to the <<glossterm-macro,`glossterm` macro>>.
136
+ - Looks for glossary pages named `reference:glossary.adoc` in all versions of all components and appends the contents of each term file to the glossary in alphabetical order.
137
+ - If a glossary page is found, sets the `glossary-page` attribute of the <<glossterm, `glossterm` macro>> to `reference:glossary.adoc`.
138
+
139
+ ==== Registration example
140
+
141
+ ```yaml
142
+ antora:
143
+ extensions:
144
+ - '@redpanda-data/docs-extensions-and-macros/extensions/aggregate-terms'
156
145
  ```
157
146
 
158
147
  === Unlisted pages
@@ -176,7 +165,7 @@ The heading under which to list the unlisted pages in the navigation. The defaul
176
165
  ```yaml
177
166
  antora:
178
167
  extensions:
179
- - require: 'node_modules/antora-extensions-and-macros/extensions/unlisted-pages.js'
168
+ - require: '@redpanda-data/docs-extensions-and-macros/extensions/unlisted-pages'
180
169
  addToNavigation: true
181
170
  unlistedPagesHeading: 'Additional Resources'
182
171
  ```
@@ -228,33 +217,22 @@ config_ref:example_config,true,tunable-properties[]
228
217
  ----
229
218
  asciidoc:
230
219
  extensions:
231
- - 'node_modules/antora-extensions-and-macros/macros/config-ref.js'
220
+ - '@redpanda-data/docs-extensions-and-macros/macros/config-ref'
232
221
  ----
233
222
 
234
- === glossary and glossterm
235
-
236
- The glossary module provides a way to define and reference glossary terms in your AsciiDoc documents.
223
+ === glossterm
237
224
 
238
- This module consists of two parts: a block macro (`glossary`) and an inline macro (`glossterm`).
225
+ The `glossterm` inline macro provides a way to define and reference glossary terms in your AsciiDoc documents.
239
226
 
240
- NOTE: This macro is a customized version of https://gitlab.com/djencks/asciidoctor-glossary[`asciidoctor-glossary`]. We added the ability to define terms globally in <<global-attributes, global attributes>> as well as link to external URLs.
227
+ NOTE: This macro is a customized version of https://gitlab.com/djencks/asciidoctor-glossary[`asciidoctor-glossary`].
241
228
 
242
229
  ==== Usage
243
230
 
244
- To insert a glossary dlist, use the glossary block macro.
245
-
246
- [,asciidoc]
247
- ----
248
- glossary::[]
249
- ----
250
-
251
- Glossary terms defined in the `glossterm` inline macro before the `glossary` macro is used appear as a definition list, sorted by term.
252
-
253
- The `glossterm` inline macro is used to reference a term within the text of the document:
231
+ Use the `glossterm` inline macro to reference a term within the text of the document:
254
232
 
255
233
  [,asciidoc]
256
234
  ----
257
- glossterm:myTerm[myDefinition]
235
+ glossterm:my term[myDefinition]
258
236
  ----
259
237
 
260
238
  It takes two parameters:
@@ -263,7 +241,7 @@ term::
263
241
  The term to be defined.
264
242
 
265
243
  definition (optional)::
266
- The definition of the term. If the term is defined in the <<global-attributes, global attributes>>, you can omit the definition as it will always be replaced by the definition in the global attributes.
244
+ The definition of the term. If the term is defined in the {url-playbook}[`shared` component] or the `local-terms` object of the `antora.yml` file, you can omit the definition as it will always be replaced by those definitions.
267
245
 
268
246
  ==== Configuration options
269
247
 
@@ -290,22 +268,13 @@ Whether to enable tooltips for the defined terms. Valid values are:
290
268
 
291
269
  The last two options are intended to support js/css tooltip solutions such as tippy.js.
292
270
 
293
- [IMPORTANT]
294
- .Multi-page use
295
- ====
296
- In Antora, a glossary is constructed for each component-version.
297
- When the `glossary` block macro is evaluated, only terms known as of the rendering can be included.
298
- Therefore, it is necessary that the page containing this macro in a component-version be rendered last.
299
- It may be possible to arrange this by naming the page starting with a lot of 'z’s, such as `zzzzzz-glossary.adoc`.
300
- ====
301
-
302
271
  ==== Registration example
303
272
 
304
273
  [,yaml]
305
274
  ----
306
275
  asciidoc:
307
276
  extensions:
308
- - 'node_modules/antora-extensions-and-macros/macros/glossary.js'
277
+ - '@redpanda-data/docs-extensions-and-macros/macros/glossary'
309
278
  ----
310
279
 
311
280
  === helm_ref
@@ -347,7 +316,7 @@ If you do not specify a Helm reference value, the macro generates a link without
347
316
  ----
348
317
  asciidoc:
349
318
  extensions:
350
- - 'node_modules/antora-extensions-and-macros/macros/helm-ref.js'
319
+ - '@redpanda-data/docs-extensions-and-macros/macros/helm-ref'
351
320
  ----
352
321
 
353
322
  == Development quickstart
@@ -418,5 +387,5 @@ If you want to use the project locally before it is published, you can specify t
418
387
  asciidoc:
419
388
  attributes:
420
389
  extensions:
421
- - '<path-to-local-project>/antora-extensions-and-macros/extensions/<extension-name>'
422
- ----
390
+ - '<path-to-local-project>/docs-extensions-and-macros/extensions/<extension-name>'
391
+ ----
@@ -2,76 +2,45 @@
2
2
  * antora:
3
3
  extensions:
4
4
  * - require: ./extensions/add-global-attributes.js
5
- org: example
6
- repo: test
7
- branch: main
8
5
  */
9
6
 
10
- const yaml = require('js-yaml');
11
- const { Octokit } = require("@octokit/rest");
12
- const { retry } = require("@octokit/plugin-retry");
13
- const OctokitWithRetries = Octokit.plugin(retry);
14
- const chalk = require('chalk')
15
-
16
-
17
7
  module.exports.register = function ({ config }) {
18
- const logger = this.getLogger('global-attributes-extension')
19
-
20
- this
21
- .on('playbookBuilt', async ({ playbook }) => {
22
-
23
- const globalAttributesUrl = `/repos/${config.org}/${config.repo}/contents/global-attributes?ref=${config.branch}`;
24
-
25
- let githubOptions = {
26
- userAgent: 'Redpanda Docs',
27
- baseUrl: 'https://api.github.com',
28
- };
29
-
30
- if(process.env.GLOBAL_ATTRIBUTES_GITHUB_TOKEN){
31
- githubOptions.auth = process.env.GLOBAL_ATTRIBUTES_GITHUB_TOKEN;
32
- } else {
33
- logger.warn('GLOBAL_ATTRIBUTES_GITHUB_TOKEN environment variable not set. Attempting unauthenticated request.')
34
- }
35
-
36
- const github = new OctokitWithRetries(githubOptions);
37
-
38
- try {
39
- // Request the contents of the directory from the GitHub API
40
- const response = await github.request('GET ' + globalAttributesUrl);
41
-
42
- if (response.status === 200) {
43
- const directoryContents = response.data;
44
-
45
- // Filter out only YAML files
46
- const yamlFiles = directoryContents.filter(file => file.name.endsWith('.yaml') || file.name.endsWith('.yml'));
47
-
48
- let globalAttributes = {};
49
- for (let file of yamlFiles) {
50
- const fileResponse = await github.request('GET ' + file.download_url);
51
- const fileData = yaml.load(fileResponse.data);
52
- globalAttributes = {...globalAttributes, ...fileData};
8
+ const yaml = require('js-yaml');
9
+ const _ = require('lodash');
10
+ const logger = this.getLogger('global-attributes-extension');
11
+ const chalk = require('chalk')
12
+
13
+ this.on('contentAggregated', ({ siteCatalog, contentAggregate }) => {
14
+ let attributeFile;
15
+ try {
16
+ for (const component of contentAggregate) {
17
+ if (component.name === 'shared') {
18
+ attributeFile = component.files.find(file => file.path.includes('attributes.yml'));
19
+ if (!attributeFile) {
20
+ logger.warn("No attributes.yml file found in 'shared' component.");
21
+ } else {
22
+ siteCatalog.attributeFile = yaml.load(attributeFile.contents.toString('utf8'));
23
+ console.log(chalk.green('Loaded attributes from shared component.'));
53
24
  }
54
-
55
- let mergedAttributes = {
56
- ...globalAttributes,
57
- ...playbook.asciidoc.attributes
58
- };
59
-
60
- playbook.asciidoc.attributes = mergedAttributes;
61
-
62
- console.log(chalk.green('Merged global attributes into playbook'));
63
-
64
- } else {
65
- logger.warn(`Could not fetch global attributes: ${response.statusText}`);
66
- return null
67
- }
68
- } catch(error) {
69
- if (error.response.url) {
70
- logger.warn(error.status + ' Could not get ' + error.response.url)
71
- }
72
- else {
73
- logger.warn(error)
25
+ break
74
26
  }
75
27
  }
76
- })
77
- }
28
+ } catch (error) {
29
+ logger.error(`Error loading attributes: ${error.message}`);
30
+ }
31
+ })
32
+
33
+ .on('contentClassified', ({ siteCatalog, contentCatalog }) => {
34
+ const components = contentCatalog.getComponents()
35
+ try {
36
+ components.forEach(({versions}) => {
37
+ versions.forEach(({asciidoc}) => {
38
+ asciidoc.attributes = _.merge(asciidoc.attributes, siteCatalog.attributeFile);
39
+ })
40
+ });
41
+ console.log(chalk.green('Merged global attributes into each component version.'));
42
+ } catch (error) {
43
+ logger.error(`Error merging attributes: ${error.message}`);
44
+ }
45
+ });
46
+ }
@@ -0,0 +1,59 @@
1
+ /* Example use in the playbook
2
+ * antora:
3
+ extensions:
4
+ * - require: ./extensions/aggregate-terms.js
5
+ */
6
+
7
+ module.exports.register = function ({ config }) {
8
+ const logger = this.getLogger('term-aggregation-extension');
9
+ const chalk = require('chalk')
10
+
11
+ this.on('contentAggregated', ({ siteCatalog, contentAggregate }) => {
12
+ try {
13
+ for (const component of contentAggregate) {
14
+ if (component.name === 'shared') {
15
+ const termFiles = component.files.filter(file => file.path.includes('modules/terms/partials/'));
16
+ siteCatalog.terms = {}
17
+ termFiles.forEach(file => {
18
+ const termContent = file.contents.toString('utf8');
19
+ siteCatalog.terms[file.basename] = termContent;
20
+ });
21
+ console.log(chalk.green('Loaded terms from shared component.'));
22
+ break
23
+ }
24
+ }
25
+ } catch (error) {
26
+ logger.error(`Error loading terms: ${error.message}`);
27
+ }
28
+ })
29
+
30
+ .on('contentClassified', ({ siteCatalog, contentCatalog }) => {
31
+ const components = contentCatalog.getComponents()
32
+ try {
33
+ for (const { versions } of components) {
34
+ for (const { name: component, version, asciidoc, title } of versions) {
35
+ if (component == 'shared') continue;
36
+ const glossaryPage = contentCatalog.resolvePage(`${version?version +'@':''}${component}:reference:glossary.adoc`);
37
+ if (glossaryPage) {
38
+ asciidoc.attributes['glossary-page'] = 'reference:glossary.adoc'
39
+ const glossaryContent = glossaryPage.contents.toString('utf8');
40
+ let newContent = glossaryContent;
41
+ const sortedTerms = Object.keys(siteCatalog.terms).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
42
+ for (i = 0; i < sortedTerms.length; i++) {
43
+ const termName = sortedTerms[i];
44
+ const termContent = siteCatalog.terms[termName];
45
+ newContent += '\n\n' + termContent;
46
+ }
47
+ glossaryPage.contents = Buffer.from(newContent, 'utf8');
48
+
49
+ console.log(chalk.green(`Transposed terms into glossary for ${component}.`));
50
+ } else {
51
+ logger.warn(`Skipping ${title} ${version} - No glossary page (reference:glossary.adoc) found`)
52
+ }
53
+ }
54
+ }
55
+ } catch (error) {
56
+ logger.error(`Error transposing terms: ${error.message}`);
57
+ }
58
+ });
59
+ }
@@ -4,21 +4,17 @@ module.exports.register = function ({ config }) {
4
4
 
5
5
  const sanitizeAttributeValue = (value) => String(value).replace("@", "");
6
6
 
7
- this.on('documentsConverted', ({playbook, contentCatalog}) => {
7
+ this.on('documentsConverted', ({contentCatalog}) => {
8
8
  for (const { versions } of contentCatalog.getComponents()) {
9
- for (const { name: component, version } of versions) {
10
- if (component !== 'ROOT') continue;
9
+ for (const { name: component, version, asciidoc } of versions) {
11
10
  const attachments = contentCatalog.findBy({ component, version, family });
12
11
  for (const attachment of attachments) {
13
12
  let contentString = String.fromCharCode(...attachment['_contents']);
14
- const attributes = attachment.src.origin.descriptor.asciidoc.attributes;
15
- const mergedAttributes = {
16
- ...playbook.asciidoc.attributes,
17
- ...attributes
18
- };
19
- for (const key in mergedAttributes) {
13
+ if (!asciidoc.attributes) continue
14
+ if (!asciidoc.attributes.hasOwnProperty('replace-attributes-in-attachments')) continue;
15
+ for (const key in asciidoc.attributes) {
20
16
  const placeholder = "{" + key + "}";
21
- const sanitizedValue = sanitizeAttributeValue(mergedAttributes[key]);
17
+ const sanitizedValue = sanitizeAttributeValue(asciidoc.attributes[key]);
22
18
  contentString = contentString.replace(new RegExp(placeholder, 'g'), sanitizedValue);
23
19
  }
24
20
  attachment['_contents'] = Buffer.from(contentString, "utf-8");
@@ -18,6 +18,10 @@ module.exports.register = function ({ config }) {
18
18
  .on('playbookBuilt', async ({ playbook }) => {
19
19
  try {
20
20
  const LatestConsoleVersion = await GetLatestConsoleVersion();
21
+ if (!LatestConsoleVersion) {
22
+ logger.warn(`Failed to get latest Console version from GitHub`)
23
+ return
24
+ }
21
25
  if (!playbook.asciidoc) {
22
26
  playbook.asciidoc = {};
23
27
  }
@@ -37,7 +41,10 @@ module.exports.register = function ({ config }) {
37
41
  const components = await contentCatalog.getComponents();
38
42
  for (let i = 0; i < components.length; i++) {
39
43
  let component = components[i];
40
- if (LatestRedpandaVersion.length !== 2) logger.warn('Could not find the latest Redpanda versions - using defaults');
44
+ if (LatestRedpandaVersion.length !== 2 || !LatestRedpandaVersion[0]) {
45
+ logger.warn('Failed to get the latest Redpanda versions - using defaults');
46
+ return
47
+ }
41
48
  if (component.name === 'ROOT') {
42
49
 
43
50
  if (!component.latest.asciidoc) {
@@ -12,16 +12,47 @@ module.exports.register = function (registry, config = {}) {
12
12
  function getKey (src) {
13
13
  return `${src.version}@${src.component}`
14
14
  }
15
-
16
15
  const contentCatalog = config.contentCatalog
17
16
  if (!contentCatalog[$glossaryContexts]) contentCatalog[$glossaryContexts] = {}
18
17
  const glossaryContexts = contentCatalog[$glossaryContexts]
18
+ // Check if the terms have been cached
19
+ const sharedKey = 'sharedTerms'
20
+ if (!glossaryContexts[sharedKey]) {
21
+ // Get the term files from the 'shared' component
22
+ const termFiles = contentCatalog.findBy({ component: 'shared', module: 'terms', family: 'partial' })
23
+ // Extract the term definitions from the files
24
+ const ATTRIBUTE_REGEX = /^:([a-zA-Z0-9_-]+):[ \t]*(.*)$/gm
25
+
26
+ const terms = termFiles.map(file => {
27
+ const content = file.contents.toString()
28
+ const attributes = {}
29
+
30
+ let match
31
+ while ((match = ATTRIBUTE_REGEX.exec(content)) !== null) {
32
+ const [ , name, value ] = match
33
+ attributes[name] = value
34
+ }
35
+
36
+ if (!attributes['term-name'] || !attributes['hover-text']) {
37
+ console.warn(`Skipping file ${file.path} due to missing 'term-name' and/or 'hover-text'.`)
38
+ return null
39
+ }
40
+
41
+ return {
42
+ term: attributes['term-name'],
43
+ def: attributes['hover-text'],
44
+ content
45
+ }
46
+ }).filter(Boolean)
47
+
48
+ // Store the terms in the cache
49
+ glossaryContexts[sharedKey] = terms
50
+ }
19
51
  const key = getKey(config.file.src)
20
52
  if (!glossaryContexts[key]) {
21
53
  glossaryContexts[key] = {
22
- gloss: [],
54
+ gloss: glossaryContexts[sharedKey],
23
55
  self: undefined,
24
- dlist: undefined,
25
56
  }
26
57
  }
27
58
  const context = glossaryContexts[key]
@@ -34,35 +65,7 @@ module.exports.register = function (registry, config = {}) {
34
65
  const IDRX = /[/ _.-]+/g
35
66
 
36
67
  function termId (term) {
37
- return '_glossterm_' + term.toLowerCase().replace(IDRX, '_')
38
- }
39
-
40
- function dlistItem (context, term, def) {
41
- const id = termId(term)
42
- term = `anchor:${id}[${term}]${term}`
43
- const termItem = context.self.createListItem(context.dlist, term)
44
- const defItem = context.self.createListItem(context.dlist, def)
45
- return [[termItem], defItem]
46
- }
47
-
48
- function glossaryBlockMacro () {
49
- return function () {
50
- const self = this
51
- self.named('glossary')
52
- self.$option('format', 'short') //no target between glossary:: and [params]
53
- // self.positionalAttributes(['name', 'parameters'])
54
- self.process(function (parent, target, attributes) {
55
- const context = vfs.getContext()
56
- const dlist = self.createList(parent, 'dlist')
57
- context.self = self
58
- context.dlist = dlist
59
- context.gloss
60
- .forEach(({ term, def }) => {
61
- dlist.blocks.push(dlistItem(context, term, def))
62
- })
63
- return dlist
64
- })
65
- }
68
+ return term.toLowerCase().replace(IDRX, '-')
66
69
  }
67
70
 
68
71
  const TRX = /(<[a-z]+)([^>]*>.*)/
@@ -78,23 +81,9 @@ module.exports.register = function (registry, config = {}) {
78
81
  const term = attributes.term || target
79
82
  const document = parent.document
80
83
  const context = vfs.getContext()
81
- // See if a predefined list of terms is available
82
- const globalTerms = document.getAttribute("terms") || [];
83
84
  const localTerms = document.getAttribute("local-terms") || [];
84
- let mergedTerms;
85
- if(globalTerms.length > 0 && localTerms.length > 0){
86
- // Convert globalTerms to a Map for fast look up
87
- let globalTermsMap = new Map(globalTerms.map(i => [i.term, i]));
88
-
89
- // Create a new array based on localTerms, but replace items if they exist in globalTerms
90
- mergedTerms = localTerms.map(item => globalTermsMap.has(item.term) ? globalTermsMap.get(item.term) : item);
91
-
92
- // Update localTerms with the mergedTerms
93
- document.setAttribute("terms", mergedTerms);
94
- console.log(chalk.green('Merged global terms with local terms'))
95
- }
96
- const termData = (mergedTerms || []).find((t) => t.term === term) || {};
97
- const customLink = termData.link;
85
+ const localTermData = (localTerms || []).find((t) => t.term === term) || {};
86
+ const customLink = localTermData.link;
98
87
  var tooltip = document.getAttribute('glossary-tooltip')
99
88
  if (tooltip === 'true') tooltip = 'data-glossary-tooltip'
100
89
  if (tooltip && tooltip !== 'title' && !tooltip.startsWith('data-')) {
@@ -102,13 +91,17 @@ module.exports.register = function (registry, config = {}) {
102
91
  tooltip = undefined
103
92
  }
104
93
  const logTerms = document.hasAttribute('glossary-log-terms')
105
- var definition = termData.definition || attributes.definition
94
+ var definition;
95
+ const index = context.gloss.findIndex((candidate) => candidate.term === term)
96
+ if (index >= 0) {
97
+ definition = context.gloss[index].def
98
+ } else {
99
+ definition = localTermData.definition || attributes.definition;
100
+ }
106
101
  if (definition) {
107
102
  logTerms && console.log(`${term}:: ${definition}`)
108
- addItem(context, term, definition)
109
103
  } else if (tooltip) {
110
- const index = context.gloss.findIndex((candidate) => candidate.term === term)
111
- definition = ~index ? context.gloss[index].def : `${term} not yet defined`
104
+ definition = `${term} not yet defined`
112
105
  }
113
106
  const links = document.getAttribute('glossary-links', 'true') === 'true'
114
107
  var glossaryPage = document.getAttribute('glossary-page', '')
@@ -120,11 +113,15 @@ module.exports.register = function (registry, config = {}) {
120
113
  }
121
114
  const glossaryTermRole = document.getAttribute('glossary-term-role', 'glossary-term')
122
115
  const attrs = glossaryTermRole ? { role: glossaryTermRole } : {}
123
- const inline = links
124
- ? customLink
116
+ var inline;
117
+ const termExistsInContext = context.gloss.some((candidate) => candidate.term === term);
118
+ if ((termExistsInContext && links) || (links && customLink)) {
119
+ inline = customLink
125
120
  ? self.createInline(parent, 'anchor', target, { type: 'link', target: customLink, attributes: attrs })
126
121
  : self.createInline(parent, 'anchor', target, { type: 'xref', target: `${glossaryPage}#${termId(term)}`, reftext: target, attributes: attrs })
127
- : self.createInline(parent, 'quoted', target, { attributes: attrs })
122
+ } else {
123
+ inline = self.createInline(parent, 'quoted', target, { attributes: attrs })
124
+ }
128
125
  if (tooltip) {
129
126
  const a = inline.convert()
130
127
  const matches = a.match(TRX)
@@ -139,27 +136,7 @@ module.exports.register = function (registry, config = {}) {
139
136
  }
140
137
  }
141
138
 
142
- function addItem (context, term, def) {
143
- let i = 0
144
- let comp = -1
145
- for (; i < context.gloss.length && ((comp = term.localeCompare(context.gloss[i].term)) > 0); i++) {
146
- }
147
- if (comp < 0) {
148
- context.gloss.splice(i, 0, { term, def })
149
- if (context.self && context.dlist) {
150
- context.dlist.blocks.splice(i, 0, dlistItem(context, term, def))
151
- }
152
- } else {
153
- console.log(`duplicate glossary term ${term}`)
154
- }
155
- }
156
-
157
139
  function doRegister (registry) {
158
- if (typeof registry.blockMacro === 'function') {
159
- registry.blockMacro(glossaryBlockMacro())
160
- } else {
161
- console.warn('no \'blockMacro\' method on alleged registry')
162
- }
163
140
  if (typeof registry.inlineMacro === 'function') {
164
141
  registry.inlineMacro(glossaryInlineMacro())
165
142
  } else {
package/package.json CHANGED
@@ -1,11 +1,21 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "2.5.1",
3
+ "version": "3.0.2",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
- "keywords": ["antora", "extension", "macro", "documentation", "redpanda"],
5
+ "keywords": [
6
+ "antora",
7
+ "extension",
8
+ "macro",
9
+ "documentation",
10
+ "redpanda"
11
+ ],
6
12
  "author": {
7
13
  "name": "Redpanda Docs Team"
8
14
  },
15
+ "scripts": {
16
+ "build": "antora --to-dir docs --fetch local-antora-playbook.yml",
17
+ "serve": "wds --node-resolve --open preview/test.html --watch --root-dir docs"
18
+ },
9
19
  "contributors": [
10
20
  {
11
21
  "name": "JakeSCahill",
@@ -20,6 +30,7 @@
20
30
  "./extensions/add-global-attributes": "./extensions/add-global-attributes.js",
21
31
  "./extensions/version-fetcher/set-latest-version": "./extensions/version-fetcher/set-latest-version.js",
22
32
  "./extensions/algolia-indexer/index": "./extensions/algolia-indexer/index.js",
33
+ "./extensions/aggregate-terms": "./extensions/aggregate-terms.js",
23
34
  "./macros/glossary": "./macros/glossary.js",
24
35
  "./macros/config-ref": "./macros/config-ref.js",
25
36
  "./macros/helm-ref": "./macros/helm-ref.js"
@@ -34,15 +45,20 @@
34
45
  "url": "git+https://github.com/redpanda-data/docs-extensions-and-macros"
35
46
  },
36
47
  "dependencies": {
37
- "@antora/site-generator": "3.1.2",
38
48
  "@octokit/plugin-retry": "^4.1.3",
39
49
  "@octokit/rest": "^19.0.7",
40
50
  "algoliasearch": "^4.17.0",
41
51
  "chalk": "4.1.2",
42
- "js-yaml": "^4.1.0",
43
52
  "gulp": "^4.0.2",
44
53
  "gulp-connect": "^5.7.0",
45
54
  "html-entities": "2.3",
55
+ "js-yaml": "^4.1.0",
56
+ "lodash": "^4.17.21",
46
57
  "node-html-parser": "5.4.2-0"
58
+ },
59
+ "devDependencies": {
60
+ "@antora/cli": "3.1.4",
61
+ "@antora/site-generator": "3.1.4",
62
+ "@web/dev-server": "^0.2.5"
47
63
  }
48
64
  }