@redpanda-data/docs-extensions-and-macros 3.0.0 → 3.0.3
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 +4 -9
- package/extensions/add-global-attributes.js +5 -3
- package/extensions/aggregate-terms.js +22 -5
- package/extensions/replace-attributes-in-attachments.js +6 -11
- package/extensions/version-fetcher/set-latest-version.js +8 -1
- package/macros/glossary.js +23 -7
- package/package.json +10 -2
package/README.adoc
CHANGED
|
@@ -115,7 +115,7 @@ This extension replaces AsciiDoc attribute placeholders with their respective va
|
|
|
115
115
|
|
|
116
116
|
[IMPORTANT]
|
|
117
117
|
====
|
|
118
|
-
-
|
|
118
|
+
- This extension processes attachments only if the component version includes the attribute `replace-attributes-in-attachments: true`.
|
|
119
119
|
- The `@` character is removed from attribute values to prevent potential issues with CSS or HTML syntax.
|
|
120
120
|
- If the same attribute placeholder is used multiple times within a file, all instances will be replaced with the attribute's value.
|
|
121
121
|
====
|
|
@@ -132,14 +132,9 @@ antora:
|
|
|
132
132
|
|
|
133
133
|
This extension aggregates all term pages from the {url-playbook}[`shared` component] and does the following:
|
|
134
134
|
|
|
135
|
-
- Makes all `term-name
|
|
136
|
-
- Looks for glossary pages named `reference:glossary.adoc` in all versions of
|
|
137
|
-
- If a glossary page is found, sets the `glossary-page` attribute of the `glossterm` macro to `reference:glossary.adoc
|
|
138
|
-
|
|
139
|
-
[IMPORTANT]
|
|
140
|
-
====
|
|
141
|
-
By default, this extension processes glossary pages for the `ROOT` (redpanda) component only. This behavior is hardcoded and cannot be changed in the configuration.
|
|
142
|
-
====
|
|
135
|
+
- Makes all `term-name`, `hover-text`, and `link` 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` so that terms can be linked to the glossary page.
|
|
143
138
|
|
|
144
139
|
==== Registration example
|
|
145
140
|
|
|
@@ -33,10 +33,12 @@ module.exports.register = function ({ config }) {
|
|
|
33
33
|
.on('contentClassified', ({ siteCatalog, contentCatalog }) => {
|
|
34
34
|
const components = contentCatalog.getComponents()
|
|
35
35
|
try {
|
|
36
|
-
components.forEach(({
|
|
37
|
-
|
|
36
|
+
components.forEach(({versions}) => {
|
|
37
|
+
versions.forEach(({asciidoc}) => {
|
|
38
|
+
asciidoc.attributes = _.merge(asciidoc.attributes, siteCatalog.attributeFile);
|
|
39
|
+
})
|
|
38
40
|
});
|
|
39
|
-
console.log(chalk.green('Merged global attributes into each component.'));
|
|
41
|
+
console.log(chalk.green('Merged global attributes into each component version.'));
|
|
40
42
|
} catch (error) {
|
|
41
43
|
logger.error(`Error merging attributes: ${error.message}`);
|
|
42
44
|
}
|
|
@@ -32,8 +32,7 @@ module.exports.register = function ({ config }) {
|
|
|
32
32
|
try {
|
|
33
33
|
for (const { versions } of components) {
|
|
34
34
|
for (const { name: component, version, asciidoc, title } of versions) {
|
|
35
|
-
|
|
36
|
-
if (component !== 'ROOT') continue;
|
|
35
|
+
if (component == 'shared') continue;
|
|
37
36
|
const glossaryPage = contentCatalog.resolvePage(`${version?version +'@':''}${component}:reference:glossary.adoc`);
|
|
38
37
|
if (glossaryPage) {
|
|
39
38
|
asciidoc.attributes['glossary-page'] = 'reference:glossary.adoc'
|
|
@@ -42,19 +41,37 @@ module.exports.register = function ({ config }) {
|
|
|
42
41
|
const sortedTerms = Object.keys(siteCatalog.terms).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
43
42
|
for (i = 0; i < sortedTerms.length; i++) {
|
|
44
43
|
const termName = sortedTerms[i];
|
|
45
|
-
|
|
44
|
+
let termContent = siteCatalog.terms[termName];
|
|
45
|
+
const hoverTextMatch = termContent.match(/:hover-text: (.*)/);
|
|
46
|
+
const hoverText = hoverTextMatch ? hoverTextMatch[1] : '';
|
|
47
|
+
const linkMatch = termContent.match(/:link: (.*)/);
|
|
48
|
+
const link = linkMatch ? linkMatch[1] : '';
|
|
49
|
+
// If the hover-text attribute is found and the content does not already contain {hover-text}, append it as a new line after the first newline
|
|
50
|
+
if (hoverText && !termContent.includes('{hover-text}')) {
|
|
51
|
+
const firstNewlineIndex = termContent.indexOf('\n\n');
|
|
52
|
+
if (firstNewlineIndex !== -1) {
|
|
53
|
+
termContent = termContent.slice(0, firstNewlineIndex + 1) + hoverText + '\n' + termContent.slice(firstNewlineIndex + 1);
|
|
54
|
+
} else {
|
|
55
|
+
// If there's no newline, just append at the end
|
|
56
|
+
termContent += '\n' + hoverText;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// If the link attribute is found, append it at the end of the term content
|
|
60
|
+
if (link) {
|
|
61
|
+
termContent += `\n\nFor more details, see ${link}`;
|
|
62
|
+
}
|
|
46
63
|
newContent += '\n\n' + termContent;
|
|
47
64
|
}
|
|
48
65
|
glossaryPage.contents = Buffer.from(newContent, 'utf8');
|
|
49
66
|
|
|
50
|
-
console.log(chalk.green(`
|
|
67
|
+
console.log(chalk.green(`Merged terms into glossary for ${component} component${version? version: ''}.`));
|
|
51
68
|
} else {
|
|
52
69
|
logger.warn(`Skipping ${title} ${version} - No glossary page (reference:glossary.adoc) found`)
|
|
53
70
|
}
|
|
54
71
|
}
|
|
55
72
|
}
|
|
56
73
|
} catch (error) {
|
|
57
|
-
logger.error(`Error
|
|
74
|
+
logger.error(`Error merging terms: ${error.message}`);
|
|
58
75
|
}
|
|
59
76
|
});
|
|
60
77
|
}
|
|
@@ -4,22 +4,17 @@ module.exports.register = function ({ config }) {
|
|
|
4
4
|
|
|
5
5
|
const sanitizeAttributeValue = (value) => String(value).replace("@", "");
|
|
6
6
|
|
|
7
|
-
this.on('documentsConverted', ({
|
|
7
|
+
this.on('documentsConverted', ({contentCatalog}) => {
|
|
8
8
|
for (const { versions } of contentCatalog.getComponents()) {
|
|
9
|
-
for (const { name: component, version } of versions) {
|
|
10
|
-
// TODO: will need a better way to filter when we have more content components
|
|
11
|
-
if (component !== 'ROOT') continue;
|
|
9
|
+
for (const { name: component, version, asciidoc } of versions) {
|
|
12
10
|
const attachments = contentCatalog.findBy({ component, version, family });
|
|
13
11
|
for (const attachment of attachments) {
|
|
14
12
|
let contentString = String.fromCharCode(...attachment['_contents']);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
...attributes
|
|
19
|
-
};
|
|
20
|
-
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) {
|
|
21
16
|
const placeholder = "{" + key + "}";
|
|
22
|
-
const sanitizedValue = sanitizeAttributeValue(
|
|
17
|
+
const sanitizedValue = sanitizeAttributeValue(asciidoc.attributes[key]);
|
|
23
18
|
contentString = contentString.replace(new RegExp(placeholder, 'g'), sanitizedValue);
|
|
24
19
|
}
|
|
25
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
|
|
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) {
|
package/macros/glossary.js
CHANGED
|
@@ -23,6 +23,8 @@ module.exports.register = function (registry, config = {}) {
|
|
|
23
23
|
// Extract the term definitions from the files
|
|
24
24
|
const ATTRIBUTE_REGEX = /^:([a-zA-Z0-9_-]+):[ \t]*(.*)$/gm
|
|
25
25
|
|
|
26
|
+
const termMap = new Map();
|
|
27
|
+
|
|
26
28
|
const terms = termFiles.map(file => {
|
|
27
29
|
const content = file.contents.toString()
|
|
28
30
|
const attributes = {}
|
|
@@ -34,15 +36,27 @@ module.exports.register = function (registry, config = {}) {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
if (!attributes['term-name'] || !attributes['hover-text']) {
|
|
37
|
-
console.warn(`Skipping
|
|
39
|
+
console.warn(`Skipping term ${file.path} due to missing 'term-name' and/or 'hover-text attributes'.`)
|
|
38
40
|
return null
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
if (termMap.has(attributes['term-name'])) {
|
|
44
|
+
throw new Error(`Error: Duplicate term-name '${attributes['term-name']}' found in ${file.src.fileUri || file.src.editUrl}.`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
termMap.set(attributes['term-name'], true);
|
|
48
|
+
|
|
49
|
+
const termObject = {
|
|
42
50
|
term: attributes['term-name'],
|
|
43
51
|
def: attributes['hover-text'],
|
|
44
52
|
content
|
|
45
53
|
}
|
|
54
|
+
|
|
55
|
+
if (attributes['link'] && attributes['link'].trim() !== '') {
|
|
56
|
+
termObject.link = attributes['link']
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return termObject
|
|
46
60
|
}).filter(Boolean)
|
|
47
61
|
|
|
48
62
|
// Store the terms in the cache
|
|
@@ -81,9 +95,11 @@ module.exports.register = function (registry, config = {}) {
|
|
|
81
95
|
const term = attributes.term || target
|
|
82
96
|
const document = parent.document
|
|
83
97
|
const context = vfs.getContext()
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
const customLinkCandidate = context.gloss.find(candidate => 'link' in candidate && candidate.term === term);
|
|
99
|
+
let customLink;
|
|
100
|
+
if (customLinkCandidate) {
|
|
101
|
+
customLink = customLinkCandidate.link;
|
|
102
|
+
}
|
|
87
103
|
var tooltip = document.getAttribute('glossary-tooltip')
|
|
88
104
|
if (tooltip === 'true') tooltip = 'data-glossary-tooltip'
|
|
89
105
|
if (tooltip && tooltip !== 'title' && !tooltip.startsWith('data-')) {
|
|
@@ -96,7 +112,7 @@ module.exports.register = function (registry, config = {}) {
|
|
|
96
112
|
if (index >= 0) {
|
|
97
113
|
definition = context.gloss[index].def
|
|
98
114
|
} else {
|
|
99
|
-
definition =
|
|
115
|
+
definition = attributes.definition;
|
|
100
116
|
}
|
|
101
117
|
if (definition) {
|
|
102
118
|
logTerms && console.log(`${term}:: ${definition}`)
|
|
@@ -115,7 +131,7 @@ module.exports.register = function (registry, config = {}) {
|
|
|
115
131
|
const attrs = glossaryTermRole ? { role: glossaryTermRole } : {}
|
|
116
132
|
var inline;
|
|
117
133
|
const termExistsInContext = context.gloss.some((candidate) => candidate.term === term);
|
|
118
|
-
if (termExistsInContext && links) {
|
|
134
|
+
if ((termExistsInContext && links) || (links && customLink)) {
|
|
119
135
|
inline = customLink
|
|
120
136
|
? self.createInline(parent, 'anchor', target, { type: 'link', target: customLink, attributes: attrs })
|
|
121
137
|
: self.createInline(parent, 'anchor', target, { type: 'xref', target: `${glossaryPage}#${termId(term)}`, reftext: target, attributes: attrs })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redpanda-data/docs-extensions-and-macros",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Antora extensions and macros developed for Redpanda documentation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antora",
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
"author": {
|
|
13
13
|
"name": "Redpanda Docs Team"
|
|
14
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
|
+
},
|
|
15
19
|
"contributors": [
|
|
16
20
|
{
|
|
17
21
|
"name": "JakeSCahill",
|
|
@@ -41,7 +45,6 @@
|
|
|
41
45
|
"url": "git+https://github.com/redpanda-data/docs-extensions-and-macros"
|
|
42
46
|
},
|
|
43
47
|
"dependencies": {
|
|
44
|
-
"@antora/site-generator": "3.1.2",
|
|
45
48
|
"@octokit/plugin-retry": "^4.1.3",
|
|
46
49
|
"@octokit/rest": "^19.0.7",
|
|
47
50
|
"algoliasearch": "^4.17.0",
|
|
@@ -52,5 +55,10 @@
|
|
|
52
55
|
"js-yaml": "^4.1.0",
|
|
53
56
|
"lodash": "^4.17.21",
|
|
54
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"
|
|
55
63
|
}
|
|
56
64
|
}
|