Skip to content

Commit 442679d

Browse files
committed
Add root-attachments-extension
Closes gh-34
1 parent 0b009ec commit 442679d

6 files changed

+272
-0
lines changed

README.adoc

+10
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ It applies the following extensions in the proper order:
6060
* <<Collector Cache Config>>
6161
* https://gitlab.com/antora/antora-collector-extension[@antora/collector-extension]
6262
* <<Root Component>>
63+
* <<Root Attachments>>
6364
* <<Static Page>>
6465

6566

@@ -316,6 +317,15 @@ root_component_name::
316317
A required attribute that indicates the name of the component that should not be included in the URLs.
317318

318319

320+
=== Root Attachments
321+
322+
*require name:* @springio/antora-extensions/root-attachments-extension
323+
324+
IMPORTANT: Be sure to register this extension under the `antora.extensions` key in the playbook, not the `asciidoc.extensions` key!
325+
326+
This removes the `_attachments` portion of the URL from attachments.
327+
328+
319329
=== Tabs Migration
320330

321331
*require name:* @springio/antora-extensions/tabs-migration-extension

lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ module.exports.register = function ({ playbook, config }) {
1010
this.require(`${packageName}/inject-collector-cache-config-extension`).register.call(this, { playbook, config })
1111
this.require('@antora/collector-extension').register.call(this, { config })
1212
this.require(`${packageName}/root-component-extension`).register.call(this, { config })
13+
this.require(`${packageName}/root-attachments-extension`).register.call(this, { config })
1314
this.require(`${packageName}/static-page-extension`).register.call(this, { config })
1415
}

lib/root-attachments-extension.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict'
2+
3+
module.exports.register = function ({ config = {} }) {
4+
this.once('contentClassified', ({ contentCatalog }) => {
5+
contentCatalog.findBy({ family: 'attachment' }).forEach((file) => {
6+
removeRootComponentNameFromFile(file)
7+
})
8+
})
9+
}
10+
11+
function removeRootComponentNameFromFile (file) {
12+
if (file.out) {
13+
file.out.rootPath = removeFirstSegment(file.out.rootPath)
14+
file.out.moduleRootPath = removeFirstSegment(file.out.moduleRootPath)
15+
file.out.dirname = removeAttachmentsFromPath(file.out.dirname)
16+
file.out.path = removeAttachmentsFromPath(file.out.path)
17+
}
18+
if (file.pub) {
19+
if (file.pub.rootPath) {
20+
file.pub.rootPath = removeFirstSegment(file.pub.rootPath)
21+
}
22+
if (file.pub.moduleRootPath) {
23+
file.pub.moduleRootPath = removeFirstSegment(file.pub.moduleRootPath)
24+
}
25+
file.pub.url = removeAttachmentsFromPath(file.pub.url)
26+
}
27+
}
28+
29+
function removeFirstSegment (path) {
30+
return path ? path.split('/').slice(1).join('/') || '.' : path
31+
}
32+
33+
function removeAttachmentsFromPath (path) {
34+
return path.replace('/_attachments', '').replace('_attachments/', '')
35+
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"./latest-version-extension": "./lib/latest-version-extension.js",
3737
"./partial-build-extension": "./lib/partial-build-extension.js",
3838
"./publish-docsearch-config-extension": "./lib/publish-docsearch-config-extension.js",
39+
"./root-attachments-extension": "./lib/root-attachments-extension.js",
3940
"./root-component-extension": "./lib/root-component-extension.js",
4041
"./tabs-migration-extension": "./lib/tabs-migration-extension.js",
4142
"./static-page-extension": "./lib/static-page-extension.js",

test/extensions-test.js

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ describe('extensions', () => {
4242
`${packageName}/inject-collector-cache-config-extension`,
4343
'@antora/collector-extension',
4444
`${packageName}/root-component-extension`,
45+
`${packageName}/root-attachments-extension`,
4546
`${packageName}/static-page-extension`,
4647
])
4748
})
+224
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const { expect } = require('./harness')
5+
const { name: packageName } = require('#package')
6+
7+
describe('root-attachments-extension', () => {
8+
const ext = require(packageName + '/root-attachments-extension')
9+
10+
const createContentCatalog = () => ({
11+
files: [],
12+
component: { versions: [] },
13+
findByArgs: {},
14+
findBy (args) {
15+
this.findByArgs = args
16+
return this.files
17+
},
18+
getComponent () {
19+
return this.component
20+
},
21+
})
22+
23+
const createGeneratorContext = () => ({
24+
variables: {},
25+
once (eventName, fn) {
26+
this[eventName] = fn
27+
},
28+
updateVariables (updates) {
29+
Object.assign(this.variables, updates)
30+
},
31+
})
32+
33+
const contentClassified = (config = { rootComponentName: 'framework' }) => {
34+
ext.register.call(generatorContext, config ? { config } : {})
35+
return generatorContext.contentClassified({ contentCatalog })
36+
}
37+
38+
let generatorContext
39+
let contentCatalog
40+
41+
beforeEach(() => {
42+
generatorContext = createGeneratorContext()
43+
contentCatalog = createContentCatalog()
44+
})
45+
46+
describe('bootstrap', () => {
47+
it('should be able to require extension', () => {
48+
expect(ext).to.be.instanceOf(Object)
49+
expect(ext.register).to.be.instanceOf(Function)
50+
})
51+
52+
it('should be able to call register function exported by extension', () => {
53+
ext.register.call(generatorContext, {})
54+
expect(generatorContext.contentClassified).to.be.instanceOf(Function)
55+
})
56+
})
57+
58+
describe('contentClassified', () => {
59+
it("findBy uses { family: 'attachment' }", () => {
60+
contentClassified()
61+
expect(contentCatalog.findByArgs).is.eqls({ family: 'attachment' })
62+
})
63+
describe('file.pub', () => {
64+
it('file.pub ROOT module', () => {
65+
contentCatalog.files.push({
66+
pub: {
67+
url: '/_attachments/api/java/org/springframework/security/core/Authentication.html',
68+
moduleRootPath: '../../../../../..',
69+
rootPath: '../../../../../../..',
70+
},
71+
})
72+
contentClassified()
73+
expect(contentCatalog.files).is.eqls([
74+
{
75+
pub: {
76+
url: '/api/java/org/springframework/security/core/Authentication.html',
77+
moduleRootPath: '../../../../..',
78+
rootPath: '../../../../../..',
79+
},
80+
},
81+
])
82+
})
83+
it('file.pub named module', () => {
84+
contentCatalog.files.push({
85+
pub: {
86+
url: '/java-project/_attachments/api/java/org/springframework/security/core/Authentication.html',
87+
moduleRootPath: '../../../../../../..',
88+
rootPath: '../../../../../../../..',
89+
},
90+
})
91+
contentClassified()
92+
expect(contentCatalog.files).is.eqls([
93+
{
94+
pub: {
95+
url: '/java-project/api/java/org/springframework/security/core/Authentication.html',
96+
moduleRootPath: '../../../../../..',
97+
rootPath: '../../../../../../..',
98+
},
99+
},
100+
])
101+
})
102+
it('file.pub named module no path', () => {
103+
contentCatalog.files.push({
104+
pub: {
105+
url: '/java-project/_attachments/index.html',
106+
moduleRootPath: '..',
107+
rootPath: '../..',
108+
},
109+
})
110+
contentClassified()
111+
expect(contentCatalog.files).is.eqls([
112+
{
113+
pub: {
114+
url: '/java-project/index.html',
115+
moduleRootPath: '.',
116+
rootPath: '..',
117+
},
118+
},
119+
])
120+
})
121+
it('file.pub ROOT module no path', () => {
122+
contentCatalog.files.push({
123+
pub: {
124+
url: '/_attachments/index.html',
125+
moduleRootPath: '..',
126+
rootPath: '../..',
127+
},
128+
})
129+
contentClassified()
130+
expect(contentCatalog.files).is.eqls([
131+
{
132+
pub: {
133+
url: '/index.html',
134+
moduleRootPath: '.',
135+
rootPath: '..',
136+
},
137+
},
138+
])
139+
})
140+
it('file.pub null rootPath', () => {
141+
contentCatalog.files.push({
142+
pub: {
143+
url: '/_attachments/api/java/org/springframework/security/core/Authentication.html',
144+
moduleRootPath: '../../../../../..',
145+
},
146+
})
147+
contentClassified()
148+
expect(contentCatalog.files).is.eqls([
149+
{
150+
pub: {
151+
url: '/api/java/org/springframework/security/core/Authentication.html',
152+
moduleRootPath: '../../../../..',
153+
},
154+
},
155+
])
156+
})
157+
it('file.pub null moduleRootPath', () => {
158+
contentCatalog.files.push({
159+
pub: {
160+
url: '/_attachments/api/java/org/springframework/security/core/Authentication.html',
161+
rootPath: '../../../../../../..',
162+
},
163+
})
164+
contentClassified()
165+
expect(contentCatalog.files).is.eqls([
166+
{
167+
pub: {
168+
url: '/api/java/org/springframework/security/core/Authentication.html',
169+
rootPath: '../../../../../..',
170+
},
171+
},
172+
])
173+
})
174+
})
175+
describe('file.out', () => {
176+
it('file.out ROOT module', () => {
177+
contentCatalog.files.push({
178+
out: {
179+
dirname: '_attachments/api/java/org/springframework/security/core',
180+
basename: 'Authentication.html',
181+
path: '_attachments/api/java/porg/springframework/security/core/Authentication.html',
182+
moduleRootPath: '../../../../../..',
183+
rootPath: '../../../../../../..',
184+
},
185+
})
186+
contentClassified()
187+
expect(contentCatalog.files).is.eqls([
188+
{
189+
out: {
190+
dirname: 'api/java/org/springframework/security/core',
191+
basename: 'Authentication.html',
192+
path: 'api/java/porg/springframework/security/core/Authentication.html',
193+
moduleRootPath: '../../../../..',
194+
rootPath: '../../../../../..',
195+
},
196+
},
197+
])
198+
})
199+
it('file.out named module', () => {
200+
contentCatalog.files.push({
201+
out: {
202+
dirname: 'java-project/_attachments/api/java/org/springframework/security/core',
203+
basename: 'Authentication.html',
204+
path: 'java-project/_attachments/api/java/porg/springframework/security/core/Authentication.html',
205+
moduleRootPath: '../../../../../../..',
206+
rootPath: '../../../../../../../..',
207+
},
208+
})
209+
contentClassified()
210+
expect(contentCatalog.files).is.eqls([
211+
{
212+
out: {
213+
dirname: 'java-project/api/java/org/springframework/security/core',
214+
basename: 'Authentication.html',
215+
path: 'java-project/api/java/porg/springframework/security/core/Authentication.html',
216+
moduleRootPath: '../../../../../..',
217+
rootPath: '../../../../../../..',
218+
},
219+
},
220+
])
221+
})
222+
})
223+
})
224+
})

0 commit comments

Comments
 (0)