@antora/assembler 1.0.0-rc.4 → 1.0.0-rc.6
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/lib/assemble-content.js +70 -35
- package/lib/configure.js +13 -11
- package/lib/filter-component-versions.js +1 -1
- package/lib/load-config.js +7 -6
- package/lib/produce-assembly-file.js +48 -24
- package/lib/produce-assembly-files.js +98 -94
- package/lib/util/rewriter.js +2 -2
- package/package.json +3 -3
package/lib/assemble-content.js
CHANGED
|
@@ -11,11 +11,12 @@ const produceAssemblyFiles = require('./produce-assembly-files')
|
|
|
11
11
|
const PromiseQueue = require('./util/promise-queue')
|
|
12
12
|
const runCommand = require('@antora/run-command-helper')
|
|
13
13
|
|
|
14
|
-
const invariably = {
|
|
14
|
+
const invariably = { new: () => ({}), null: () => null, void: () => undefined }
|
|
15
15
|
const PACKAGE_NAME = require('../package.json').name
|
|
16
16
|
const NEWLINE_RX = /(?:\r?\n)+/
|
|
17
17
|
|
|
18
|
-
async function assembleContent (playbook, contentCatalog, converter,
|
|
18
|
+
async function assembleContent (playbook, contentCatalog, converter, providers) {
|
|
19
|
+
const { configSource, navigationCatalog, componentVersionFilter } = providers
|
|
19
20
|
const {
|
|
20
21
|
convert = converter,
|
|
21
22
|
getDefaultCommand,
|
|
@@ -23,7 +24,8 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
23
24
|
backend: targetBackend = targetExtname.substring(1),
|
|
24
25
|
embedReferenceStyle = 'relative',
|
|
25
26
|
mediaType: targetMediaType,
|
|
26
|
-
loggerName = PACKAGE_NAME
|
|
27
|
+
loggerName = `${PACKAGE_NAME} [${targetBackend}-exporter]`,
|
|
28
|
+
xmlCompliant,
|
|
27
29
|
} = converter ?? {}
|
|
28
30
|
const assemblerConfig = await loadConfig.call(this, configSource, playbook, '-' + targetBackend)
|
|
29
31
|
if (assemblerConfig.enabled === false || !contentCatalog.publishableFamilies?.has('export')) return []
|
|
@@ -38,8 +40,9 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
38
40
|
const { loadAsciiDoc = require('@antora/asciidoc-loader') } = generatorFunctions
|
|
39
41
|
const { assembly: assemblyConfig, build: buildConfig } = assemblerConfig
|
|
40
42
|
assemblyConfig.embedReferenceStyle = embedReferenceStyle
|
|
43
|
+
if (xmlCompliant) assemblyConfig.xmlIds ??= true
|
|
41
44
|
const profile = (assemblyConfig.profile ??= targetBackend)
|
|
42
|
-
const intrinsicAttributes = { 'loader-assembler': '' }
|
|
45
|
+
const intrinsicAttributes = { 'loader-assembler': '', 'assembler-root-level': assemblyConfig.rootLevel }
|
|
43
46
|
const cwd = (buildConfig.cwd ??= process.cwd())
|
|
44
47
|
if (profile) {
|
|
45
48
|
buildConfig.dir ??= ospath.join(playbook.dir ?? process.cwd(), `build/assembler/${profile}`)
|
|
@@ -62,7 +65,8 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
62
65
|
loadAsciiDoc,
|
|
63
66
|
contentCatalog,
|
|
64
67
|
assemblerConfig,
|
|
65
|
-
generateSelectAssemblyProfile(context, contentCatalog, assemblyConfig, intrinsicAttributes, navigationCatalog)
|
|
68
|
+
generateSelectAssemblyProfile(context, contentCatalog, assemblyConfig, intrinsicAttributes, navigationCatalog),
|
|
69
|
+
typeof componentVersionFilter === 'function' ? componentVersionFilter : undefined
|
|
66
70
|
)
|
|
67
71
|
if (!(assemblyFiles.length && typeof convert === 'function')) return assemblyFiles
|
|
68
72
|
buildConfig.command ??= typeof getDefaultCommand === 'function' ? await getDefaultCommand(cwd, playbook) : null
|
|
@@ -75,8 +79,7 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
75
79
|
.add(
|
|
76
80
|
assemblyFiles.map((doc) => async () => {
|
|
77
81
|
const relativeToOutput = embedReferenceStyle === 'output-relative'
|
|
78
|
-
const convertAttributes = prepareConvertAttributes(doc, targetExtname, relativeToOutput, assemblerConfig)
|
|
79
|
-
if (buildConfig.mkdirs) await fsp.mkdir(convertAttributes.outdir, { recursive: true, force: true })
|
|
82
|
+
const convertAttributes = await prepareConvertAttributes(doc, targetExtname, relativeToOutput, assemblerConfig)
|
|
80
83
|
return boundConvert(doc, convertAttributes, buildConfig, helpers).then((result) =>
|
|
81
84
|
boundResolveFileOrContents(result, convertAttributes, buildConfig, loggerName).then((fileOrContents) =>
|
|
82
85
|
coerceToExportFormat(doc, targetBackend, targetExtname, targetMediaType, fileOrContents)
|
|
@@ -150,29 +153,34 @@ function generateSelectAssemblyProfile (context, contentCatalog, baseModel, intr
|
|
|
150
153
|
const attributes = Object.assign({}, baseModel.attributes)
|
|
151
154
|
const model = Object.assign({}, baseModel, overrides, { attributes, logger })
|
|
152
155
|
if (!overrides) return Object.assign(model, { navigation: navigation || componentVersion.navigation })
|
|
156
|
+
if ('rootLevel' in overrides) attributes['assembler-root-level'] = overrides.rootLevel
|
|
153
157
|
delete model.navFiles
|
|
154
158
|
delete model.messages
|
|
155
|
-
if (overrides.attributes)
|
|
159
|
+
if (overrides.attributes) {
|
|
160
|
+
for (const [name, val] of Object.entries(overrides.attributes)) {
|
|
161
|
+
if (!(name in intrinsicAttributes)) attributes[name] = val
|
|
162
|
+
}
|
|
163
|
+
}
|
|
156
164
|
if (navigation) return Object.assign(model, { navigation })
|
|
157
165
|
overrides.messages?.forEach(boundSendToLog)
|
|
158
166
|
const navFiles = overrides.navFiles
|
|
159
167
|
if (!navFiles) return Object.assign(model, { navigation: componentVersion.navigation })
|
|
160
168
|
if (!navFiles.length) return Object.assign(model, { navigation: [] })
|
|
161
169
|
model.navigation = buildAlternateNavigation(contentCatalog, componentVersion, navFiles, {
|
|
162
|
-
attributes:
|
|
170
|
+
attributes: model.attributes,
|
|
163
171
|
})
|
|
164
172
|
return model
|
|
165
173
|
}
|
|
166
174
|
}
|
|
167
175
|
|
|
168
|
-
function prepareConvertAttributes (doc, targetExtname, relativeToOutput, assemblerConfig) {
|
|
176
|
+
async function prepareConvertAttributes (doc, targetExtname, relativeToOutput, assemblerConfig) {
|
|
169
177
|
const {
|
|
170
178
|
asciidoc: { attributes: docAttributes } = { attributes: {} },
|
|
171
179
|
extname: docfilesuffix,
|
|
172
180
|
path: reldocfile,
|
|
173
181
|
src: { family, relative },
|
|
174
182
|
} = doc
|
|
175
|
-
const { cwd = process.cwd(), dir = cwd } = assemblerConfig.build
|
|
183
|
+
const { cwd = process.cwd(), dir = cwd, mkdirs } = assemblerConfig.build
|
|
176
184
|
const docname = family + '$' + relative.substring(0, relative.length - docfilesuffix.length)
|
|
177
185
|
const docfile = ospath.join(dir, reldocfile)
|
|
178
186
|
const outdir = ospath.dirname(docfile)
|
|
@@ -182,31 +190,54 @@ function prepareConvertAttributes (doc, targetExtname, relativeToOutput, assembl
|
|
|
182
190
|
docdir,
|
|
183
191
|
docfile,
|
|
184
192
|
docfilesuffix,
|
|
185
|
-
|
|
193
|
+
docname: `${docname}@`,
|
|
186
194
|
imagesdir: '',
|
|
187
195
|
outdir,
|
|
188
196
|
outfile,
|
|
189
197
|
outfilesuffix: targetExtname,
|
|
190
|
-
toArgs (
|
|
198
|
+
toArgs (attributeOptionFlag, outputOptionFlag) {
|
|
191
199
|
const args = []
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
val = name
|
|
200
|
+
let requireAsciidoctorLogAdapter
|
|
201
|
+
for (const [name, val] of Object.entries(this)) {
|
|
202
|
+
let optionValue
|
|
203
|
+
if (name === 'asciidoctor-log-integration') {
|
|
204
|
+
if ((val ?? false) !== false) requireAsciidoctorLogAdapter = val
|
|
205
|
+
continue
|
|
206
|
+
} else if ((val ?? false) === false) {
|
|
207
|
+
optionValue = `${name}!${val === false ? '=@' : ''}`
|
|
201
208
|
} else {
|
|
202
|
-
|
|
209
|
+
optionValue = val === '' ? name : name + '=' + val
|
|
203
210
|
}
|
|
204
|
-
args.push(
|
|
211
|
+
args.push(attributeOptionFlag, optionValue)
|
|
205
212
|
}
|
|
213
|
+
if (requireAsciidoctorLogAdapter) args.push('-r', requireAsciidoctorLogAdapter)
|
|
214
|
+
if (outputOptionFlag) args.push(outputOptionFlag, this.outfile)
|
|
206
215
|
return args
|
|
207
216
|
},
|
|
208
217
|
})
|
|
209
|
-
|
|
218
|
+
Object.defineProperty(attributes, 'outfilesuffix', {
|
|
219
|
+
get () {
|
|
220
|
+
return ospath.extname(this.outfile)
|
|
221
|
+
},
|
|
222
|
+
set (value) {
|
|
223
|
+
const outfile = this.outfile
|
|
224
|
+
const extname = ospath.extname(outfile)
|
|
225
|
+
if (extname && outfile.endsWith(extname)) this.outfile = outfile.substring(0, outfile.length - extname.length)
|
|
226
|
+
this.outfile += value
|
|
227
|
+
},
|
|
228
|
+
})
|
|
229
|
+
Object.defineProperty(attributes, 'toArgs', { enumerable: false })
|
|
230
|
+
if (mkdirs) await fsp.mkdir(outdir, { recursive: true, force: true })
|
|
231
|
+
if (attributes['asciidoctor-log-integration'] != null) {
|
|
232
|
+
const scriptSourcePath = require.resolve('#asciidoctor-log-adapter')
|
|
233
|
+
let scriptTargetPath = scriptSourcePath
|
|
234
|
+
if (attributes['asciidoctor-log-integration'] === 'copy-to-build-dir') {
|
|
235
|
+
scriptTargetPath = ospath.join(dir, 'asciidoctor-log-adapter.rb')
|
|
236
|
+
await fsp.cp(scriptSourcePath, scriptTargetPath, { force: true, recursive: true })
|
|
237
|
+
}
|
|
238
|
+
attributes['asciidoctor-log-integration'] = scriptTargetPath
|
|
239
|
+
}
|
|
240
|
+
return attributes
|
|
210
241
|
}
|
|
211
242
|
|
|
212
243
|
function coerceToExportFormat (assemblyFile, targetBackend, targetExtname, targetMediaType, fileOrContents) {
|
|
@@ -219,7 +250,8 @@ function coerceToExportFormat (assemblyFile, targetBackend, targetExtname, targe
|
|
|
219
250
|
const { path: sourcePath, extname: sourceExtname } = file
|
|
220
251
|
const relativeWithoutExtname = file.src.relative.substring(0, file.src.relative.length - sourceExtname.length)
|
|
221
252
|
const newPath = sourcePath.substring(0, sourcePath.length - sourceExtname.length) + targetExtname
|
|
222
|
-
Object.assign(file, { mediaType: (file.src.mediaType = targetMediaType), path: newPath })
|
|
253
|
+
Object.assign(file, { mediaType: (file.src.mediaType = targetMediaType), path: (file.src.path = newPath) })
|
|
254
|
+
delete file.src.abspath
|
|
223
255
|
file.src.basename = path.basename((file.src.relative = relativeWithoutExtname + (file.src.extname = targetExtname)))
|
|
224
256
|
return file
|
|
225
257
|
}
|
|
@@ -242,8 +274,9 @@ function prepareWorkspace (publishFiles, assemblyFiles, buildConfig) {
|
|
|
242
274
|
}
|
|
243
275
|
if (keepSource) {
|
|
244
276
|
for (const file of assemblyFiles) {
|
|
245
|
-
file.src.contents = file.contents
|
|
246
277
|
file.out = { path: file.path }
|
|
278
|
+
file.src.contents = file.contents
|
|
279
|
+
file.src.abspath = ospath.join(dir, file.path)
|
|
247
280
|
files.push(file)
|
|
248
281
|
}
|
|
249
282
|
}
|
|
@@ -254,7 +287,7 @@ function prepareWorkspace (publishFiles, assemblyFiles, buildConfig) {
|
|
|
254
287
|
})
|
|
255
288
|
}
|
|
256
289
|
|
|
257
|
-
|
|
290
|
+
function resolveFileOrContents (convertResult, convertAttributes, buildConfig, loggerName) {
|
|
258
291
|
let fileOrContents
|
|
259
292
|
if (convertResult?.status != null) {
|
|
260
293
|
if ('file' in convertResult) {
|
|
@@ -265,12 +298,14 @@ async function resolveFileOrContents (convertResult, convertAttributes, buildCon
|
|
|
265
298
|
fileOrContents = convertResult.stdout
|
|
266
299
|
}
|
|
267
300
|
let logger, match
|
|
268
|
-
if (buildConfig.stderrSink === 'log' && convertResult.stderr
|
|
301
|
+
if (buildConfig.stderrSink === 'log' && convertResult.stderr?.length && (logger = this.getLogger(loggerName))) {
|
|
269
302
|
const docfile = convertAttributes.docfile
|
|
270
303
|
const command = buildConfig.command
|
|
304
|
+
const file = { path: docfile }
|
|
271
305
|
const stderr = convertResult.stderr.toString().trimEnd()
|
|
306
|
+
const additionalLines = ['Additional stderr lines from command:']
|
|
272
307
|
stderr.split(NEWLINE_RX).forEach((line) => {
|
|
273
|
-
const ctx = { command, file
|
|
308
|
+
const ctx = { command, file }
|
|
274
309
|
if (line.charAt() === '{' && line.charAt(line.length - 1) === '}') {
|
|
275
310
|
const entry = JSON.parse(line)
|
|
276
311
|
if (entry.name) ctx.program = entry.name
|
|
@@ -286,17 +321,17 @@ async function resolveFileOrContents (convertResult, convertAttributes, buildCon
|
|
|
286
321
|
if (lineno) ctx.line = parseInt(lineno, 10)
|
|
287
322
|
logger[level === 'WARNING' ? 'warn' : level.toLowerCase()](ctx, msg)
|
|
288
323
|
} else {
|
|
289
|
-
|
|
324
|
+
additionalLines.push(line)
|
|
290
325
|
}
|
|
291
326
|
})
|
|
327
|
+
if (additionalLines.length > 1) logger.info({ command, file }, additionalLines.join('\n'))
|
|
292
328
|
}
|
|
293
329
|
} else if (convertResult !== undefined) {
|
|
294
|
-
return convertResult
|
|
330
|
+
return Promise.resolve(convertResult)
|
|
295
331
|
}
|
|
296
|
-
if (fileOrContents !== undefined) return fileOrContents
|
|
332
|
+
if (fileOrContents !== undefined) return Promise.resolve(fileOrContents)
|
|
297
333
|
const outfile = convertAttributes.outfile
|
|
298
|
-
|
|
299
|
-
return outfileExists ? new LazyReadable(() => fs.createReadStream(outfile)) : null
|
|
334
|
+
return fsp.access(outfile).then(() => new LazyReadable(() => fs.createReadStream(outfile)), invariably.null)
|
|
300
335
|
}
|
|
301
336
|
|
|
302
337
|
function isBound (obj) {
|
package/lib/configure.js
CHANGED
|
@@ -7,24 +7,26 @@ function configure (context, ...args) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
function internalConfigure (converter, config = {}, providers = {}) {
|
|
10
|
-
this.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
if (!this.listeners('beforeProcess').includes(enableKeepSource)) {
|
|
11
|
+
this.once('componentsRegistered', ({ contentCatalog, assemblerProfiles }) => {
|
|
12
|
+
contentCatalog.publishableFamilies.add('export')
|
|
13
|
+
if (!assemblerProfiles) this.updateVariables({ assemblerProfiles: getAssemblerProfiles(contentCatalog) })
|
|
14
|
+
})
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
this.once('beforeProcess', enableKeepSource)
|
|
17
|
+
}
|
|
17
18
|
|
|
18
19
|
this.once('navigationBuilt', async ({ playbook, contentCatalog }) => {
|
|
19
|
-
const { assembleContent = require('./assemble-content'), ...
|
|
20
|
-
if (
|
|
21
|
-
|
|
20
|
+
const { assembleContent = require('./assemble-content'), ...assembleContentProviders } = providers
|
|
21
|
+
if (config.configSource?.constructor === Object) {
|
|
22
|
+
assembleContentProviders.configSource = config.configSource
|
|
23
|
+
await assembleContent.call(this, playbook, contentCatalog, converter, assembleContentProviders)
|
|
22
24
|
} else {
|
|
23
25
|
const singleConfig = !('configFiles' in config)
|
|
24
26
|
const configFiles = singleConfig ? config.configFile : config.configFiles
|
|
25
27
|
for (const configSource of Array.isArray(configFiles) ? configFiles : [configFiles]) {
|
|
26
|
-
const
|
|
27
|
-
await assembleContent.call(this, playbook, contentCatalog, converter,
|
|
28
|
+
const assembleContentProvidersWithConfigSource = Object.assign({}, assembleContentProviders, { configSource })
|
|
29
|
+
await assembleContent.call(this, playbook, contentCatalog, converter, assembleContentProvidersWithConfigSource)
|
|
28
30
|
if (singleConfig) break
|
|
29
31
|
}
|
|
30
32
|
}
|
|
@@ -5,7 +5,7 @@ const { filterCollection, compilePattern } = require('./util/matcher')
|
|
|
5
5
|
const VERSION_SEPARATOR_RX = /@(?!\()(?=(\w)?)/g
|
|
6
6
|
const US = '\x1f'
|
|
7
7
|
|
|
8
|
-
function filterComponentVersions (
|
|
8
|
+
function filterComponentVersions ({ names: patterns, prereleases = true }, components) {
|
|
9
9
|
if (!patterns.length) return []
|
|
10
10
|
const candidateMap = components.reduce((accum, { name: componentName, latest, versions }) => {
|
|
11
11
|
for (const version of versions) {
|
package/lib/load-config.js
CHANGED
|
@@ -9,6 +9,7 @@ const yaml = require('js-yaml')
|
|
|
9
9
|
const { LEGACY_ASSEMBLY_KEYS } = require('./constants')
|
|
10
10
|
const CAMEL_CASE_STOP_PATHS = ['asciidoc.attributes', 'assembly.attributes']
|
|
11
11
|
const PACKAGE_NAME = require('../package.json').name
|
|
12
|
+
const YAML_SCHEMA = yaml.CORE_SCHEMA.withTags(yaml.mergeTag)
|
|
12
13
|
|
|
13
14
|
function loadConfig (configSource, playbook, preferredQualifier = '') {
|
|
14
15
|
let resolvedConfigSource
|
|
@@ -36,11 +37,11 @@ function loadConfig (configSource, playbook, preferredQualifier = '') {
|
|
|
36
37
|
}
|
|
37
38
|
return {}
|
|
38
39
|
}
|
|
39
|
-
return fsp
|
|
40
|
-
.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
return fsp.readFile(resolvedConfigSource).then((data) =>
|
|
41
|
+
Object.assign(camelCaseKeys(yaml.load(data, { schema: YAML_SCHEMA }), CAMEL_CASE_STOP_PATHS), {
|
|
42
|
+
file: resolvedConfigSource,
|
|
43
|
+
})
|
|
44
|
+
)
|
|
44
45
|
})
|
|
45
46
|
).then((config) => {
|
|
46
47
|
if (config.enabled === false) return config
|
|
@@ -133,7 +134,7 @@ function loadConfig (configSource, playbook, preferredQualifier = '') {
|
|
|
133
134
|
})
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
function camelCaseKeys (o, stopPaths
|
|
137
|
+
function camelCaseKeys (o, stopPaths, p = undefined) {
|
|
137
138
|
if (Array.isArray(o)) return o.map((it) => camelCaseKeys(it, stopPaths, p))
|
|
138
139
|
if (o == null || o.constructor !== Object) return o
|
|
139
140
|
const pathPrefix = p ? p + '.' : ''
|
|
@@ -20,6 +20,7 @@ const DISCARD_ATTRIBUTE_NAMES = [
|
|
|
20
20
|
'doctype',
|
|
21
21
|
'leveloffset',
|
|
22
22
|
'preface-title',
|
|
23
|
+
'assembly-doctype',
|
|
23
24
|
'assembly-header-attributes',
|
|
24
25
|
'assembly-navtitle',
|
|
25
26
|
'assembly-slug',
|
|
@@ -39,8 +40,8 @@ function produceAssemblyFile (
|
|
|
39
40
|
assemblyModel
|
|
40
41
|
) {
|
|
41
42
|
const pagesByUrl = files.reduce((map, it) => (it.src.family === 'page' ? map.set(it.pub.url, it) : map), new Map())
|
|
42
|
-
if (outline.urlType === 'internal' && !pagesByUrl.get(outline.url) && !(outline.items || []).length) return
|
|
43
43
|
const pagesInOutline = selectPagesInOutline(outline, pagesByUrl)
|
|
44
|
+
if (outline.urlType === 'internal' && !pagesByUrl.has(outline.pathname) && !outline.items?.length) return
|
|
44
45
|
const { rootLevel, xmlIds } = assemblyModel
|
|
45
46
|
const idSeparators = {
|
|
46
47
|
prefix:
|
|
@@ -77,6 +78,7 @@ function produceAssemblyFile (
|
|
|
77
78
|
mutableAttributes,
|
|
78
79
|
assemblyModel
|
|
79
80
|
)
|
|
81
|
+
if (buffer[buffer.doctypeIdx] === ':doctype: article') buffer.splice(buffer.doctypeIdx, 1)
|
|
80
82
|
const stem =
|
|
81
83
|
(buffer.slug ? sanitizeSlug(buffer.slug) : generateSlug(rootLevel === 0 ? 'index' : buffer.navtitle)) ||
|
|
82
84
|
'export-' + (assemblyModel.stemSeq = (assemblyModel.exportSeq ?? 0) + 1)
|
|
@@ -88,7 +90,7 @@ function produceAssemblyFile (
|
|
|
88
90
|
src: { component, version, componentVersion, module: 'ROOT', family: 'export', relative: stem + '.adoc' },
|
|
89
91
|
pub: false,
|
|
90
92
|
})
|
|
91
|
-
file.path = file.out.path // use out path as
|
|
93
|
+
file.path = file.src.path = file.out.path // use out path as path so assets can be published to same hierarchy
|
|
92
94
|
delete file.out
|
|
93
95
|
return file
|
|
94
96
|
}
|
|
@@ -124,7 +126,6 @@ function prepareAsciiDocConfig (contentCatalog, ctx, pagesInOutline, asciidocCon
|
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
function buildAsciiDocHeader (componentVersion, navtitle, assemblyModel) {
|
|
127
|
-
const doctype = assemblyModel.doctype ?? 'book'
|
|
128
129
|
const navtitlePlain = sanitize(navtitle)
|
|
129
130
|
const navtitleAsciiDoc = unconvertInlineAsciiDoc(navtitle)
|
|
130
131
|
const doctitle = (componentVersion.title === navtitlePlain ? '' : componentVersion.title + ': ') + navtitleAsciiDoc
|
|
@@ -133,7 +134,7 @@ function buildAsciiDocHeader (componentVersion, navtitle, assemblyModel) {
|
|
|
133
134
|
const buffer = [
|
|
134
135
|
`= ${doctitle}`,
|
|
135
136
|
...(version ? [`:revnumber: ${displayVersion}`] : []),
|
|
136
|
-
|
|
137
|
+
`:doctype: ${assemblyModel.doctype ?? 'book'}`,
|
|
137
138
|
':underscore: _',
|
|
138
139
|
// Q: should we pass these via the CLI so they cannot be modified?
|
|
139
140
|
`:page-component-name: ${componentVersion.name}`,
|
|
@@ -142,17 +143,22 @@ function buildAsciiDocHeader (componentVersion, navtitle, assemblyModel) {
|
|
|
142
143
|
`:page-component-display-version: ${displayVersion}`,
|
|
143
144
|
`:page-component-title: ${componentVersion.title}`,
|
|
144
145
|
]
|
|
146
|
+
buffer.doctypeIdx = version ? 2 : 1
|
|
145
147
|
return Object.assign(buffer, { navtitle })
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
function selectPagesInOutline (outlineEntry, pagesByUrl, accum) {
|
|
149
151
|
accum ??= Object.assign(new Map(), { assembled: { pages: new Map(), assets: new Set() } })
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
const { urlType, url, hash, unresolved, items = [] } = outlineEntry
|
|
153
|
+
if (urlType === 'internal' && !unresolved) {
|
|
154
|
+
const pathname = (outlineEntry.pathname ??= hash ? url.substring(0, url.length - hash.length) : url)
|
|
155
|
+
let page
|
|
156
|
+
if (!accum.has(pathname) && (page = pagesByUrl.get(pathname))) {
|
|
157
|
+
accum.set(createResourceKey(page.src), page)
|
|
158
|
+
accum.set(pathname, page)
|
|
159
|
+
}
|
|
154
160
|
}
|
|
155
|
-
for (const item of
|
|
161
|
+
for (const item of items) selectPagesInOutline(item, pagesByUrl, accum)
|
|
156
162
|
return accum
|
|
157
163
|
}
|
|
158
164
|
|
|
@@ -172,21 +178,22 @@ function mergeAsciiDoc (
|
|
|
172
178
|
level = 0,
|
|
173
179
|
supportsParts = false
|
|
174
180
|
) {
|
|
175
|
-
const { items = [], roles = [], unresolved, urlType, url, hash } = outlineEntry
|
|
181
|
+
const { items = [], roles = [], unresolved, urlType, url, pathname, hash } = outlineEntry
|
|
176
182
|
// TODO: we could try to be smart about it and make sure the page with fragment is included at least once
|
|
177
|
-
if (
|
|
183
|
+
if (roles.includes('site-only')) {
|
|
178
184
|
buffer.inBody ??= false
|
|
179
185
|
return buffer
|
|
180
186
|
}
|
|
181
|
-
|
|
187
|
+
const assembled = pagesInOutline.assembled
|
|
188
|
+
// FIXME: ideally, resource ID would be stored in navigation so we can look up the page more efficiently
|
|
189
|
+
const page = urlType === 'internal' && !unresolved ? pagesInOutline.get(pathname) : undefined
|
|
190
|
+
let navtitle = outlineEntry.navtitle ?? (page && hash ? page.asciidoc.navtitle : outlineEntry.content)
|
|
182
191
|
let navtitlePlain = sanitize(navtitle)
|
|
183
192
|
let navtitleAsciiDoc = unconvertInlineAsciiDoc(navtitle)
|
|
184
193
|
const { filetype, linkReferenceStyle, pubRoot, sectionMergeStrategy, siteRoot, logger, rootLevel } = assemblyModel
|
|
185
|
-
const
|
|
186
|
-
// FIXME: ideally, resource ID would be stored in navigation so we can look up the page more efficiently
|
|
187
|
-
const page = urlType === 'internal' && !unresolved ? pagesInOutline.get(url) : undefined
|
|
194
|
+
const doctype = assemblyModel.doctype ?? 'book'
|
|
188
195
|
const atDocumentRoot = !buffer.inBody
|
|
189
|
-
|
|
196
|
+
let atBookRoot = atDocumentRoot && !level && doctype === 'book' && (supportsParts = true)
|
|
190
197
|
const hasItems = items.length > 0
|
|
191
198
|
if (page && !assembled.pages.has(page)) {
|
|
192
199
|
const contents = page.src.contents
|
|
@@ -198,6 +205,7 @@ function mergeAsciiDoc (
|
|
|
198
205
|
Object.assign({}, page, { contents: trimAsciiDoc(contents), mediaType: page.src.mediaType })
|
|
199
206
|
)
|
|
200
207
|
const doc = loadAsciiDoc(pageAsAsciiDoc, contentCatalog, asciidocConfig)
|
|
208
|
+
doc.catalog.syntheticIds = {}
|
|
201
209
|
doc.logger = logger
|
|
202
210
|
? Object.assign(doc.getLogger().$dup(), {
|
|
203
211
|
delegate: {
|
|
@@ -210,6 +218,11 @@ function mergeAsciiDoc (
|
|
|
210
218
|
doc.source_header_attributes ??= doc.parent.$to_h()
|
|
211
219
|
const isRootPage = atDocumentRoot && !level
|
|
212
220
|
const { component, version, module: module_, relative, origin } = page.src
|
|
221
|
+
const doctypeOverride = doc.getAttribute('assembly-doctype')
|
|
222
|
+
if (doctypeOverride) {
|
|
223
|
+
if (doctypeOverride !== doctype) buffer[buffer.doctypeIdx] = `:doctype: ${doctypeOverride}`
|
|
224
|
+
if (doctypeOverride !== 'book') atBookRoot = supportsParts = false
|
|
225
|
+
}
|
|
213
226
|
if (isRootPage && doc.hasAttribute('assembly-slug')) buffer.slug = doc.getAttribute('assembly-slug')
|
|
214
227
|
let hasAssemblyNavtitleAttr
|
|
215
228
|
if ((hasAssemblyNavtitleAttr = !!doc.getAttribute('assembly-navtitle'))) {
|
|
@@ -278,6 +291,7 @@ function mergeAsciiDoc (
|
|
|
278
291
|
for (const entry of processDocumentHeader(doc, lines, ignoreLines, isRootPage)) {
|
|
279
292
|
if (entry.type === 'author_line') {
|
|
280
293
|
buffer.splice(1, 0, entry.lines[0])
|
|
294
|
+
buffer.doctypeIdx += 1
|
|
281
295
|
buffer.endHeaderIdx += 1
|
|
282
296
|
} else if (entry.type === 'attribute_entry') {
|
|
283
297
|
const name = entry.name
|
|
@@ -370,6 +384,7 @@ function mergeAsciiDoc (
|
|
|
370
384
|
// Q: should we use htitleAsciiDoc to generate ID if not {empty} instead of pageStyle
|
|
371
385
|
pageFragment = `#_${idSeparators.coordinate}${pageIdLeader}${pageStyle}`
|
|
372
386
|
buffer.unshift(`[#${pageId}]`)
|
|
387
|
+
buffer.doctypeIdx += 1
|
|
373
388
|
} else {
|
|
374
389
|
pageFragment = `#${pageId}`
|
|
375
390
|
}
|
|
@@ -400,6 +415,7 @@ function mergeAsciiDoc (
|
|
|
400
415
|
buffer.push(`${'='.repeat(heading.level)} ${heading.title}`)
|
|
401
416
|
} else if (atDocumentRoot) {
|
|
402
417
|
buffer.unshift(`[#${pageId}]`)
|
|
418
|
+
buffer.doctypeIdx += 1
|
|
403
419
|
}
|
|
404
420
|
if (sectionMergeStrategy === 'enclose' && hasItems && hasSections && !(atDocumentRoot && heading)) {
|
|
405
421
|
// TODO: make overview section title configurable
|
|
@@ -475,7 +491,7 @@ function mergeAsciiDoc (
|
|
|
475
491
|
if (~ignoreLines.indexOf(idx)) continue
|
|
476
492
|
let line = lines[idx]
|
|
477
493
|
if (line.startsWith('//')) {
|
|
478
|
-
if (line
|
|
494
|
+
if (line.charAt(2) !== '/') continue
|
|
479
495
|
if (line.length > 3 && line === '/'.repeat(line.length)) {
|
|
480
496
|
if (skipping) {
|
|
481
497
|
if (line === skipping) skipping = undefined
|
|
@@ -609,7 +625,7 @@ function mergeAsciiDoc (
|
|
|
609
625
|
)
|
|
610
626
|
if (resolvedAttributeEntries.length > 1) safePush(buffer, resolvedAttributeEntries)
|
|
611
627
|
}
|
|
612
|
-
} else if (level) {
|
|
628
|
+
} else if (level && !hash) {
|
|
613
629
|
if (atDocumentRoot && rootLevel === 0 && navtitlePlain === componentVersion.title) {
|
|
614
630
|
buffer.inBody ??= false
|
|
615
631
|
level--
|
|
@@ -621,7 +637,7 @@ function mergeAsciiDoc (
|
|
|
621
637
|
if (urlType === 'external') {
|
|
622
638
|
sectionTitle = `${url}[${navtitleAsciiDoc.replace(/\]/g, '\\]')}]`
|
|
623
639
|
} else if (urlType === 'internal' && !unresolved) {
|
|
624
|
-
const resource = files.find((it) => it.pub.url ===
|
|
640
|
+
const resource = files.find((it) => it.pub.url === pathname)
|
|
625
641
|
if (resource) {
|
|
626
642
|
if (resource.src.family === 'page' && pagesInOutline.has(resource.pub.url)) {
|
|
627
643
|
const refid = generateScopedId(resource.src, componentVersion, idSeparators, filetype, true)
|
|
@@ -640,7 +656,7 @@ function mergeAsciiDoc (
|
|
|
640
656
|
if (hasItems) {
|
|
641
657
|
const nextLevel = level + 1
|
|
642
658
|
// NOTE: drop first child if same as parent; should we keep if content is different?
|
|
643
|
-
;(urlType === 'internal' &&
|
|
659
|
+
;(urlType === 'internal' && items[0].urlType === 'internal' && pathname === items[0].url && !items[0].items?.length
|
|
644
660
|
? items.slice(1)
|
|
645
661
|
: items
|
|
646
662
|
).forEach((item) => {
|
|
@@ -807,10 +823,18 @@ function safePush (onto, entries) {
|
|
|
807
823
|
|
|
808
824
|
function generateIdFromTitle (titleAsciiDoc, idSeparators, idLeader) {
|
|
809
825
|
const Section = this.$class().$const_get('::Asciidoctor::Section')
|
|
810
|
-
const baseId = Section.$generate_id(titleAsciiDoc, this)
|
|
811
|
-
|
|
812
|
-
this.
|
|
813
|
-
|
|
826
|
+
const baseId = Section.$generate_id(titleAsciiDoc, this) // refs in catalog will always be empty
|
|
827
|
+
let id = `_${idSeparators.coordinate}${idLeader ?? ''}${baseId}`
|
|
828
|
+
const syntheticIds = (this.catalog.syntheticIds ??= {})
|
|
829
|
+
if (id in syntheticIds) {
|
|
830
|
+
const sep = (this.getAttribute('idseparator') ?? '_').charAt()
|
|
831
|
+
let cnt = this.$class().$const_get('::Asciidoctor::Compliance').unique_id_start_index
|
|
832
|
+
let candidate
|
|
833
|
+
while ((candidate = `${id}${sep}${cnt}`) in syntheticIds) cnt++
|
|
834
|
+
id = candidate
|
|
835
|
+
}
|
|
836
|
+
syntheticIds[id] = true
|
|
837
|
+
return id
|
|
814
838
|
}
|
|
815
839
|
|
|
816
840
|
module.exports = produceAssemblyFile
|
|
@@ -6,7 +6,13 @@ const selectMutableAttributes = require('./select-mutable-attributes')
|
|
|
6
6
|
|
|
7
7
|
const ATTR_REF_RX = /\\?\{(\w[\w-]*)\}/g
|
|
8
8
|
|
|
9
|
-
function produceAssemblyFiles (
|
|
9
|
+
function produceAssemblyFiles (
|
|
10
|
+
loadAsciiDoc,
|
|
11
|
+
contentCatalog,
|
|
12
|
+
assemblerConfig,
|
|
13
|
+
selectAssemblyProfile,
|
|
14
|
+
selectComponentVersions
|
|
15
|
+
) {
|
|
10
16
|
const { assembly: assemblyConfig } = assemblerConfig
|
|
11
17
|
selectAssemblyProfile ??= (componentVersion) => ({
|
|
12
18
|
attributes: assemblyConfig.attributes,
|
|
@@ -26,106 +32,104 @@ function produceAssemblyFiles (loadAsciiDoc, contentCatalog, assemblerConfig, se
|
|
|
26
32
|
const publishableFiles = contentCatalog.getFiles().filter((file) => file.out && file.pub)
|
|
27
33
|
let siteRoot
|
|
28
34
|
const configMdc = assemblerConfig.file ? { file: { path: assemblerConfig.file } } : {}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
selectComponentVersions ??= filterComponentVersions.bind(null, assemblerConfig.componentVersionFilter)
|
|
36
|
+
return selectComponentVersions(contentCatalog.getComponents()).reduce((accum, componentVersion) => {
|
|
37
|
+
const assemblyModel = selectAssemblyProfile(componentVersion)
|
|
38
|
+
const { attributes: assemblyAttributes, logger, navigation, rootLevel } = assemblyModel
|
|
39
|
+
if (!navigation) return accum
|
|
40
|
+
const contextualLogger = logger ? { warn: logger.warn.bind(logger, configMdc) } : undefined
|
|
41
|
+
const { name: componentName, version, title } = componentVersion
|
|
42
|
+
const componentVersionAsciiDocConfig = getAsciiDocConfigWithAsciidoctorReducerExtension(componentVersion)
|
|
43
|
+
let sourceHighlighter
|
|
44
|
+
if ('source-highlighter' in assemblyAttributes) {
|
|
45
|
+
sourceHighlighter = assemblyAttributes['source-highlighter']
|
|
46
|
+
delete assemblyAttributes['source-highlighter']
|
|
47
|
+
}
|
|
48
|
+
const mergedAsciiDocAttributes = collateAsciiDocAttributes(
|
|
49
|
+
Object.assign({}, componentVersionAsciiDocConfig.attributes),
|
|
50
|
+
assemblyAttributes,
|
|
51
|
+
contextualLogger
|
|
52
|
+
)
|
|
53
|
+
const mergedAsciiDocConfig = Object.assign({}, componentVersionAsciiDocConfig, {
|
|
54
|
+
attributes: mergedAsciiDocAttributes,
|
|
55
|
+
})
|
|
56
|
+
assemblyModel.filetype = baseAssemblyAttributes['assembler-filetype']
|
|
57
|
+
const outDirname = (assemblyModel.outDirname = contentCatalog.createFile({
|
|
58
|
+
src: {
|
|
59
|
+
component: componentName,
|
|
60
|
+
version,
|
|
61
|
+
componentVersion,
|
|
62
|
+
module: 'ROOT',
|
|
63
|
+
family: 'export',
|
|
64
|
+
relative: 'index.adoc',
|
|
65
|
+
},
|
|
66
|
+
}).out.dirname)
|
|
67
|
+
assemblyModel.pubRoot = outDirname ? '/' + outDirname : ''
|
|
68
|
+
assemblyModel.siteRoot =
|
|
69
|
+
siteRoot === undefined
|
|
70
|
+
? (siteRoot ??= ((val) => {
|
|
71
|
+
if (!val) return null
|
|
72
|
+
if (val.charAt(val.length - 1) === '/') val = val.substring(0, val.length - 1)
|
|
73
|
+
if (!val || val.charAt() === '/') return { path: val }
|
|
74
|
+
return { url: val, path: extractUrlPath(val) }
|
|
75
|
+
})(mergedAsciiDocAttributes['site-url'] || mergedAsciiDocAttributes['primary-site-url']))
|
|
76
|
+
: siteRoot
|
|
77
|
+
if (assemblyModel.filetype === 'html') {
|
|
78
|
+
let linkRefStyle = assemblyModel.linkReferenceStyle
|
|
79
|
+
if (linkRefStyle === 'absolute' && siteRoot?.url == null) linkRefStyle = 'root-relative'
|
|
80
|
+
if (linkRefStyle === 'root-relative' && siteRoot?.path == null) linkRefStyle = 'relative'
|
|
81
|
+
assemblyModel.linkReferenceStyle = linkRefStyle
|
|
82
|
+
} else if (!(assemblyModel.filetype === 'pdf' && assemblyModel.linkReferenceStyle === 'relative')) {
|
|
83
|
+
assemblyModel.linkReferenceStyle = 'absolute'
|
|
84
|
+
}
|
|
85
|
+
const rootEntry = { content: title }
|
|
86
|
+
let startPage =
|
|
87
|
+
'startPage' in componentVersion
|
|
88
|
+
? componentVersion.startPage
|
|
89
|
+
: contentCatalog.resolvePage('index.adoc', { component: componentName, version })
|
|
90
|
+
if (startPage && startPage.src.component === componentName && startPage.src.version === version) {
|
|
91
|
+
if (assemblyModel.insertStartPage) {
|
|
92
|
+
const navtitle = startPage.asciidoc?.navtitle || rootEntry.content
|
|
93
|
+
Object.assign(rootEntry, { navtitle, url: startPage.pub.url, urlType: 'internal', roles: ['page'] })
|
|
41
94
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
contextualLogger
|
|
46
|
-
)
|
|
47
|
-
const mergedAsciiDocConfig = Object.assign({}, componentVersionAsciiDocConfig, {
|
|
48
|
-
attributes: mergedAsciiDocAttributes,
|
|
49
|
-
})
|
|
50
|
-
assemblyModel.filetype = baseAssemblyAttributes['assembler-filetype']
|
|
51
|
-
const outDirname = (assemblyModel.outDirname = contentCatalog.createFile({
|
|
95
|
+
} else {
|
|
96
|
+
// Q: should we always use a reference page as startPage for computing mutableAttributes?
|
|
97
|
+
startPage = contentCatalog.createFile({
|
|
52
98
|
src: {
|
|
53
|
-
component:
|
|
54
|
-
version,
|
|
99
|
+
component: componentVersion.name,
|
|
100
|
+
version: componentVersion.version,
|
|
55
101
|
componentVersion,
|
|
56
102
|
module: 'ROOT',
|
|
57
|
-
family: '
|
|
103
|
+
family: 'page',
|
|
58
104
|
relative: 'index.adoc',
|
|
105
|
+
origin: (componentVersion.origins || [])[0],
|
|
59
106
|
},
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
'startPage' in componentVersion
|
|
82
|
-
? componentVersion.startPage
|
|
83
|
-
: contentCatalog.resolvePage('index.adoc', { component: componentName, version })
|
|
84
|
-
if (startPage && startPage.src.component === componentName && startPage.src.version === version) {
|
|
85
|
-
if (assemblyModel.insertStartPage) {
|
|
86
|
-
const navtitle = startPage.asciidoc?.navtitle || rootEntry.content
|
|
87
|
-
Object.assign(rootEntry, { navtitle, url: startPage.pub.url, urlType: 'internal', roles: ['page'] })
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
// Q: should we always use a reference page as startPage for computing mutableAttributes?
|
|
91
|
-
startPage = contentCatalog.createFile({
|
|
92
|
-
src: {
|
|
93
|
-
component: componentVersion.name,
|
|
94
|
-
version: componentVersion.version,
|
|
95
|
-
componentVersion,
|
|
96
|
-
module: 'ROOT',
|
|
97
|
-
family: 'page',
|
|
98
|
-
relative: 'index.adoc',
|
|
99
|
-
origin: (componentVersion.origins || [])[0],
|
|
100
|
-
},
|
|
101
|
-
})
|
|
102
|
-
startPage.path = ['modules', startPage.src.module, startPage.src.family + 's', startPage.src.relative].join('/')
|
|
107
|
+
})
|
|
108
|
+
startPage.path = ['modules', startPage.src.module, startPage.src.family + 's', startPage.src.relative].join('/')
|
|
109
|
+
}
|
|
110
|
+
const mutableAttributes = selectMutableAttributes(loadAsciiDoc, contentCatalog, startPage, mergedAsciiDocConfig)
|
|
111
|
+
prepareOutlines(navigation, rootEntry, rootLevel).reduce((any, outline) => {
|
|
112
|
+
const assemblyFile = produceAssemblyFile(
|
|
113
|
+
loadAsciiDoc,
|
|
114
|
+
contentCatalog,
|
|
115
|
+
componentVersion,
|
|
116
|
+
outline,
|
|
117
|
+
publishableFiles,
|
|
118
|
+
mergedAsciiDocConfig,
|
|
119
|
+
mutableAttributes,
|
|
120
|
+
assemblyModel
|
|
121
|
+
)
|
|
122
|
+
if (!assemblyFile) return any
|
|
123
|
+
// NOTE restore source highlighter for conversion if defined in Assembler config
|
|
124
|
+
if (sourceHighlighter !== undefined) {
|
|
125
|
+
assemblyFile.asciidoc.attributes['source-highlighter'] = sourceHighlighter
|
|
126
|
+
} else if (assemblyModel.filetype !== 'html') {
|
|
127
|
+
delete assemblyFile.asciidoc.attributes['source-highlighter']
|
|
103
128
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
contentCatalog,
|
|
109
|
-
componentVersion,
|
|
110
|
-
outline,
|
|
111
|
-
publishableFiles,
|
|
112
|
-
mergedAsciiDocConfig,
|
|
113
|
-
mutableAttributes,
|
|
114
|
-
assemblyModel
|
|
115
|
-
)
|
|
116
|
-
if (!assemblyFile) return any
|
|
117
|
-
// NOTE restore source highlighter for conversion if defined in Assembler config
|
|
118
|
-
if (sourceHighlighter !== undefined) {
|
|
119
|
-
assemblyFile.asciidoc.attributes['source-highlighter'] = sourceHighlighter
|
|
120
|
-
} else if (assemblyModel.filetype !== 'html') {
|
|
121
|
-
delete assemblyFile.asciidoc.attributes['source-highlighter']
|
|
122
|
-
}
|
|
123
|
-
return !!accum.push(assemblyFile)
|
|
124
|
-
}, false)
|
|
125
|
-
return accum
|
|
126
|
-
},
|
|
127
|
-
[]
|
|
128
|
-
)
|
|
129
|
+
return !!accum.push(assemblyFile)
|
|
130
|
+
}, false)
|
|
131
|
+
return accum
|
|
132
|
+
}, [])
|
|
129
133
|
}
|
|
130
134
|
|
|
131
135
|
function getAsciiDocConfigWithAsciidoctorReducerExtension (componentVersion) {
|
package/lib/util/rewriter.js
CHANGED
|
@@ -19,7 +19,7 @@ function rewriteXrefs (
|
|
|
19
19
|
doc,
|
|
20
20
|
sourceLocation
|
|
21
21
|
) {
|
|
22
|
-
return line.replace(/(?<![\\+])xref:((
|
|
22
|
+
return line.replace(/(?<![\\+])xref:((?:\.\/|:)?[\p{Alpha}0-9_/.{#].*?)\[(|[\s\S]*?[^\\])\]/gu, (_, target, text) =>
|
|
23
23
|
rewriteXref(
|
|
24
24
|
target,
|
|
25
25
|
text,
|
|
@@ -87,7 +87,7 @@ function rewriteXref (
|
|
|
87
87
|
const linkAttrlist = text
|
|
88
88
|
? (~text.indexOf(',') ? `"${text}"` : text) + ',role=unresolved'
|
|
89
89
|
: (~target.indexOf(':') ? `${rawTarget},` : '') + 'role=unresolved'
|
|
90
|
-
return `link:${rawTarget}[${linkAttrlist}]`
|
|
90
|
+
return `link:${rawTarget.charAt() === ':' ? resourceId.module + rawTarget : rawTarget}[${linkAttrlist}]`
|
|
91
91
|
}
|
|
92
92
|
if (fragment === resource.asciidoc.id) fragment = ''
|
|
93
93
|
if (
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antora/assembler",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.6",
|
|
4
4
|
"description": "A JavaScript library that merges AsciiDoc content from multiple pages in an Antora site into assembly files and delegates to an exporter to convert those files to another format, such as PDF.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": "OpenDevise Inc. (https://opendevise.com)",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"#unconvert-inline-asciidoc": "./lib/util/unconvert-inline-asciidoc.js"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@asciidoctor/reducer": "~1.1",
|
|
42
41
|
"@antora/expand-path-helper": "~3.0",
|
|
43
42
|
"@antora/run-command-helper": "~1.1",
|
|
44
|
-
"
|
|
43
|
+
"@asciidoctor/reducer": "~1.1",
|
|
44
|
+
"js-yaml": "~5.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@antora/asciidoc-loader": "3.2.0-rc.2",
|