@antora/assembler 1.0.0-beta.9 → 1.0.0-rc.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/adapters/asciidoctor/jsonl-logger.rb +25 -0
- package/lib/assemble-content.js +93 -70
- package/lib/configure.js +31 -7
- package/lib/constants.js +22 -0
- package/lib/filter-component-versions.js +25 -62
- package/lib/load-config.js +79 -39
- package/lib/log-command.js +20 -0
- package/lib/produce-assembly-file.js +372 -405
- package/lib/produce-assembly-files.js +51 -60
- package/lib/select-mutable-attributes.js +1 -0
- package/lib/util/create-resource-key.js +7 -0
- package/lib/util/generate-scoped-id.js +25 -0
- package/lib/util/matcher.js +150 -0
- package/lib/util/parse-resource-ref.js +36 -0
- package/lib/util/resolver.js +36 -0
- package/lib/util/rewriter.js +206 -0
- package/lib/util/rx.js +5 -0
- package/lib/util/unconvert-inline-asciidoc.js +22 -14
- package/package.json +14 -12
- package/lib/util/compute-out.js +0 -57
- package/lib/util/create-asciidoc-file.js +0 -17
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
autoload :JSON, 'json'
|
|
4
|
+
|
|
5
|
+
class JsonlFormatter < Asciidoctor::Logger::BasicFormatter
|
|
6
|
+
def call severity, time, progname, msg
|
|
7
|
+
entry = { 'time' => time.utc.to_i, 'level' => severity.downcase, 'name' => progname }
|
|
8
|
+
if ::String === msg
|
|
9
|
+
entry['msg'] = msg
|
|
10
|
+
else
|
|
11
|
+
loc = msg[:source_location]
|
|
12
|
+
entry['file'] = { 'path' => loc.file, 'line' => loc.lineno }
|
|
13
|
+
entry['msg'] = msg[:text]
|
|
14
|
+
end
|
|
15
|
+
(JSON.generate entry) + ?\n
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
proc do
|
|
20
|
+
logger = Asciidoctor::LoggerManager.logger
|
|
21
|
+
logger.formatter = JsonlFormatter.new
|
|
22
|
+
unless (progname = ::File.basename $PROGRAM_NAME).empty?
|
|
23
|
+
logger.progname = progname
|
|
24
|
+
end
|
|
25
|
+
end.call
|
package/lib/assemble-content.js
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const computeOut = require('./util/compute-out')
|
|
4
3
|
const fs = require('node:fs')
|
|
5
4
|
const { promises: fsp } = fs
|
|
6
5
|
const LazyReadable = require('./util/lazy-readable')
|
|
7
6
|
const loadConfig = require('./load-config')
|
|
7
|
+
const logCommand = require('./log-command')
|
|
8
8
|
const ospath = require('node:path')
|
|
9
9
|
const { posix: path } = ospath
|
|
10
10
|
const produceAssemblyFiles = require('./produce-assembly-files')
|
|
11
11
|
const PromiseQueue = require('./util/promise-queue')
|
|
12
|
-
const
|
|
12
|
+
const runCommand = require('@antora/run-command-helper')
|
|
13
13
|
|
|
14
14
|
const invariably = { new: () => ({}), void: () => undefined }
|
|
15
15
|
const PACKAGE_NAME = require('../package.json').name
|
|
16
16
|
const NEWLINE_RX = /(?:\r?\n)+/
|
|
17
17
|
|
|
18
18
|
async function assembleContent (playbook, contentCatalog, converter, { configSource, navigationCatalog }) {
|
|
19
|
-
const
|
|
20
|
-
|
|
19
|
+
const {
|
|
20
|
+
convert = converter,
|
|
21
|
+
getDefaultCommand,
|
|
22
|
+
extname: targetExtname = '',
|
|
23
|
+
backend: targetBackend = targetExtname.substring(1),
|
|
24
|
+
embedReferenceStyle = 'relative',
|
|
25
|
+
mediaType: targetMediaType,
|
|
26
|
+
loggerName = PACKAGE_NAME,
|
|
27
|
+
} = converter ?? {}
|
|
28
|
+
const assemblerConfig = await loadConfig.call(this, playbook, configSource, '-' + targetBackend)
|
|
29
|
+
if (assemblerConfig.enabled === false) return []
|
|
21
30
|
const context = isBound(this)
|
|
22
31
|
? this
|
|
23
32
|
: {
|
|
@@ -27,22 +36,13 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
27
36
|
}
|
|
28
37
|
const generatorFunctions = context.getFunctions()
|
|
29
38
|
const { loadAsciiDoc = require('@antora/asciidoc-loader') } = generatorFunctions
|
|
30
|
-
const {
|
|
31
|
-
convert = converter,
|
|
32
|
-
getDefaultCommand,
|
|
33
|
-
extname: targetExtname = '',
|
|
34
|
-
backend: targetBackend = targetExtname.slice(1),
|
|
35
|
-
embedReferenceStyle = 'relative',
|
|
36
|
-
mediaType: targetMediaType,
|
|
37
|
-
loggerName = PACKAGE_NAME,
|
|
38
|
-
} = converter ?? {}
|
|
39
39
|
const { assembly: assemblyConfig, build: buildConfig } = assemblerConfig
|
|
40
40
|
assemblyConfig.embedReferenceStyle = embedReferenceStyle
|
|
41
|
-
const
|
|
41
|
+
const profile = (assemblyConfig.profile ??= targetBackend)
|
|
42
42
|
const intrinsicAttributes = { 'loader-assembler': '' }
|
|
43
43
|
buildConfig.cwd ??= process.cwd()
|
|
44
44
|
if (profile) {
|
|
45
|
-
buildConfig.dir ??= ospath.join(playbook.dir ?? process.cwd(), `build/assembler
|
|
45
|
+
buildConfig.dir ??= ospath.join(playbook.dir ?? process.cwd(), `build/assembler/${profile}`)
|
|
46
46
|
intrinsicAttributes[`assembler-profile-${profile}`] = ''
|
|
47
47
|
intrinsicAttributes['assembler-profile'] = profile
|
|
48
48
|
if (targetBackend) {
|
|
@@ -50,19 +50,19 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
50
50
|
intrinsicAttributes['assembler-backend'] = targetBackend
|
|
51
51
|
}
|
|
52
52
|
} else {
|
|
53
|
-
buildConfig.dir ??= ospath.join(playbook.dir ?? process.cwd(), 'build/assembler')
|
|
53
|
+
buildConfig.dir ??= ospath.join(playbook.dir ?? process.cwd(), 'build/assembler/_')
|
|
54
54
|
}
|
|
55
55
|
if (targetExtname) {
|
|
56
|
-
const targetFiletype = targetExtname.
|
|
56
|
+
const targetFiletype = targetExtname.substring(1)
|
|
57
57
|
intrinsicAttributes[`assembler-filetype-${targetFiletype}`] = ''
|
|
58
58
|
intrinsicAttributes['assembler-filetype'] = targetFiletype
|
|
59
59
|
}
|
|
60
|
-
Object.assign(
|
|
60
|
+
Object.assign(assemblyConfig.attributes, intrinsicAttributes)
|
|
61
61
|
const assemblyFiles = produceAssemblyFiles(
|
|
62
62
|
loadAsciiDoc,
|
|
63
63
|
contentCatalog,
|
|
64
64
|
assemblerConfig,
|
|
65
|
-
|
|
65
|
+
generateSelectAssemblyProfile(context, contentCatalog, assemblyConfig, intrinsicAttributes, navigationCatalog)
|
|
66
66
|
)
|
|
67
67
|
if (!(assemblyFiles.length && typeof convert === 'function')) return assemblyFiles
|
|
68
68
|
if (buildConfig.command == null && typeof getDefaultCommand === 'function') {
|
|
@@ -70,14 +70,15 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
70
70
|
}
|
|
71
71
|
const { publishSite: publishFiles = require('@antora/site-publisher') } = generatorFunctions
|
|
72
72
|
await prepareWorkspace(publishFiles, assemblyFiles, buildConfig)
|
|
73
|
+
const helpers = { logCommand: logCommand.bind(context, loggerName), runCommand }
|
|
73
74
|
const boundConvert = convert.bind(context)
|
|
74
75
|
return new PromiseQueue({ concurrency: buildConfig.processLimit })
|
|
75
76
|
.add(
|
|
76
77
|
assemblyFiles.map((doc) => async () => {
|
|
77
78
|
const relativeToOutput = embedReferenceStyle === 'output-relative'
|
|
78
|
-
const convertAttributes = prepareConvertAttributes(doc, targetExtname, relativeToOutput,
|
|
79
|
+
const convertAttributes = prepareConvertAttributes(doc, targetExtname, relativeToOutput, assemblerConfig)
|
|
79
80
|
if (buildConfig.mkdirs) await fsp.mkdir(convertAttributes.outdir, { recursive: true, force: true })
|
|
80
|
-
return boundConvert(doc, convertAttributes, buildConfig).then((result) => {
|
|
81
|
+
return boundConvert(doc, convertAttributes, buildConfig, helpers).then((result) => {
|
|
81
82
|
const fileOrContents = resolveFileOrContents.call(context, result, convertAttributes, buildConfig, loggerName)
|
|
82
83
|
return coerceToExportFormat(doc, targetBackend, targetExtname, targetMediaType, fileOrContents)
|
|
83
84
|
})
|
|
@@ -93,7 +94,7 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
93
94
|
return files.map((file) => {
|
|
94
95
|
const pages = file.assembler.assembled.pages
|
|
95
96
|
delete file.assembler.assembled
|
|
96
|
-
file = contentCatalog.addFile(
|
|
97
|
+
file = contentCatalog.addFile(file)
|
|
97
98
|
const extname = file.extname
|
|
98
99
|
const download = file.assembler.downloadStem + extname
|
|
99
100
|
if (qualifyExports) {
|
|
@@ -103,8 +104,14 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
103
104
|
}
|
|
104
105
|
pages.forEach((fragment, page) => {
|
|
105
106
|
const assemblerMeta = (page.assembler ??= {})
|
|
106
|
-
|
|
107
|
-
const
|
|
107
|
+
const exports = (assemblerMeta.exports ??= [])
|
|
108
|
+
const exportEntry = { fragment, file }
|
|
109
|
+
const insertIdx = exports.findIndex(
|
|
110
|
+
({ file: candidate }) =>
|
|
111
|
+
!(candidate.src.component === page.src.component && candidate.src.version === page.src.version)
|
|
112
|
+
)
|
|
113
|
+
~insertIdx ? exports.splice(insertIdx, 0, exportEntry) : exports.push(exportEntry)
|
|
114
|
+
const extnameProp = extname.substring(1)
|
|
108
115
|
if (extnameProp in assemblerMeta) return
|
|
109
116
|
Object.defineProperty(assemblerMeta, extnameProp, {
|
|
110
117
|
configurable: true,
|
|
@@ -117,85 +124,81 @@ async function assembleContent (playbook, contentCatalog, converter, { configSou
|
|
|
117
124
|
})
|
|
118
125
|
}
|
|
119
126
|
|
|
120
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Generates a function that selects the active assembly profile, initializes an assembly model using
|
|
129
|
+
* the keys from the profile as well as any inherited shared keys, builds the navigation for the assembly, and
|
|
130
|
+
* returns the initialized assembly model. The assembly model is further populated after the call to this function.
|
|
131
|
+
*/
|
|
132
|
+
function generateSelectAssemblyProfile (context, contentCatalog, baseModel, intrinsicAttributes, navigationCatalog) {
|
|
121
133
|
const logger = context.getLogger?.(PACKAGE_NAME)
|
|
122
134
|
const { assemblerProfiles } = context.getVariables()
|
|
123
135
|
if (!assemblerProfiles) {
|
|
124
136
|
return (componentVersion) => {
|
|
125
137
|
const navigation =
|
|
126
138
|
navigationCatalog?.getNavigation(componentVersion.name, componentVersion.version) ?? componentVersion.navigation
|
|
127
|
-
return Object.assign({
|
|
139
|
+
return Object.assign({}, baseModel, { attributes: Object.assign({}, baseModel.attributes), navigation, logger })
|
|
128
140
|
}
|
|
129
141
|
}
|
|
130
142
|
const boundSendToLog = sendToLog.bind(logger)
|
|
131
|
-
const {
|
|
143
|
+
const { buildAlternateNavigation = require('@antora/navigation-builder').buildAlternateNavigation } =
|
|
144
|
+
context.getFunctions()
|
|
132
145
|
return (componentVersion) => {
|
|
133
146
|
const componentVersionProfiles = assemblerProfiles.get(componentVersion.version + '@' + componentVersion.name)
|
|
134
|
-
const overrides =
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
const model = Object.assign({
|
|
147
|
+
const overrides = componentVersionProfiles?.get(baseModel.profile) ?? componentVersionProfiles?.get()
|
|
148
|
+
const navigation = navigationCatalog?.getNavigation(componentVersion.name, componentVersion.version)
|
|
149
|
+
const attributes = Object.assign({}, baseModel.attributes)
|
|
150
|
+
const model = Object.assign({}, baseModel, overrides, { attributes, logger })
|
|
151
|
+
if (!overrides) return Object.assign(model, { navigation: navigation || componentVersion.navigation })
|
|
138
152
|
delete model.navFiles
|
|
139
153
|
delete model.messages
|
|
140
|
-
|
|
141
|
-
if (
|
|
142
|
-
messages?.forEach(boundSendToLog)
|
|
143
|
-
|
|
144
|
-
if (!navFiles) return model
|
|
154
|
+
if (overrides.attributes) Object.entries(overrides.attributes).forEach(([name, val]) => (attributes[name] = val))
|
|
155
|
+
if (navigation) return Object.assign(model, { navigation })
|
|
156
|
+
overrides.messages?.forEach(boundSendToLog)
|
|
157
|
+
const navFiles = overrides.navFiles
|
|
158
|
+
if (!navFiles) return Object.assign(model, { navigation: componentVersion.navigation })
|
|
145
159
|
if (!navFiles.length) return Object.assign(model, { navigation: [] })
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
componentVersion.asciidoc = Object.assign({}, asciidoc_, {
|
|
149
|
-
attributes: Object.assign({}, asciidoc_.attributes, intrinsicAttributes),
|
|
160
|
+
model.navigation = buildAlternateNavigation(contentCatalog, componentVersion, navFiles, {
|
|
161
|
+
attributes: intrinsicAttributes,
|
|
150
162
|
})
|
|
151
|
-
buildNavigation(
|
|
152
|
-
new Proxy(contentCatalog, {
|
|
153
|
-
get (target, property) {
|
|
154
|
-
const method = target[property]
|
|
155
|
-
if (property !== 'findBy') return method
|
|
156
|
-
return (criteria) => (toJSON(criteria) === '{"family":"nav"}' ? navFiles : method.call(target, criteria))
|
|
157
|
-
},
|
|
158
|
-
})
|
|
159
|
-
)
|
|
160
|
-
model.navigation = componentVersion.navigation
|
|
161
|
-
Object.assign(componentVersion, { asciidoc: asciidoc_, navigation: navigation_ })
|
|
162
163
|
return model
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
function prepareConvertAttributes (doc, targetExtname, relativeToOutput,
|
|
167
|
+
function prepareConvertAttributes (doc, targetExtname, relativeToOutput, assemblerConfig) {
|
|
167
168
|
const {
|
|
168
169
|
asciidoc: { attributes: docAttributes } = { attributes: {} },
|
|
169
170
|
extname: docfilesuffix,
|
|
170
171
|
path: reldocfile,
|
|
171
172
|
src: { family, relative },
|
|
172
173
|
} = doc
|
|
173
|
-
const { cwd = process.cwd(), dir = cwd } =
|
|
174
|
-
const docname = family + '$' + relative.
|
|
174
|
+
const { cwd = process.cwd(), dir = cwd } = assemblerConfig.build
|
|
175
|
+
const docname = family + '$' + relative.substring(0, relative.length - docfilesuffix.length)
|
|
175
176
|
const docfile = ospath.join(dir, reldocfile)
|
|
176
177
|
const outdir = ospath.dirname(docfile)
|
|
177
178
|
const docdir = relativeToOutput ? dir : outdir
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
const attributes = Object.assign({}, docAttributes, {
|
|
179
|
+
const outfile = docfile.substring(0, docfile.length - docfilesuffix.length) + targetExtname
|
|
180
|
+
const attributes = Object.assign({ revdate: `${assemblerConfig.assembly.revdate}@` }, docAttributes, {
|
|
181
181
|
docdir,
|
|
182
182
|
docfile,
|
|
183
183
|
docfilesuffix,
|
|
184
184
|
'docname@': docname,
|
|
185
|
-
imagesdir,
|
|
185
|
+
imagesdir: '',
|
|
186
186
|
outdir,
|
|
187
187
|
outfile,
|
|
188
188
|
outfilesuffix: targetExtname,
|
|
189
|
-
toArgs (optionFlag
|
|
190
|
-
const padCharRef = process.platform === 'win32' && command.startsWith('bundle exec ')
|
|
189
|
+
toArgs (optionFlag) {
|
|
191
190
|
const args = []
|
|
192
191
|
for (let [name, val] of Object.entries(this)) {
|
|
193
192
|
if (val) {
|
|
194
|
-
val =
|
|
193
|
+
val = name + '=' + val
|
|
195
194
|
} else if (val === '') {
|
|
195
|
+
if (name === 'asciidoctor-log-integration') {
|
|
196
|
+
args.push('-r', require.resolve('#asciidoctor-log-adapter'))
|
|
197
|
+
continue
|
|
198
|
+
}
|
|
196
199
|
val = name
|
|
197
200
|
} else {
|
|
198
|
-
val =
|
|
201
|
+
val = `${name}!${val === false ? '@' : ''}`
|
|
199
202
|
}
|
|
200
203
|
args.push(optionFlag, val)
|
|
201
204
|
}
|
|
@@ -212,10 +215,9 @@ function coerceToExportFormat (originalFile, targetBackend, targetExtname, targe
|
|
|
212
215
|
: fileOrContents
|
|
213
216
|
;(file.assembler ??= {}).backend = targetBackend
|
|
214
217
|
if (file.extname === targetExtname) return file
|
|
215
|
-
const sourcePath = file
|
|
216
|
-
const
|
|
217
|
-
const
|
|
218
|
-
const newPath = sourcePath.slice(0, sourcePath.length - sourceExtname.length) + targetExtname
|
|
218
|
+
const { path: sourcePath, extname: sourceExtname } = file
|
|
219
|
+
const relativeWithoutExtname = file.src.relative.substring(0, file.src.relative.length - sourceExtname.length)
|
|
220
|
+
const newPath = sourcePath.substring(0, sourcePath.length - sourceExtname.length) + targetExtname
|
|
219
221
|
Object.assign(file, { mediaType: (file.src.mediaType = targetMediaType), path: newPath })
|
|
220
222
|
file.src.basename = path.basename((file.src.relative = relativeWithoutExtname + (file.src.extname = targetExtname)))
|
|
221
223
|
return file
|
|
@@ -237,14 +239,30 @@ function prepareWorkspace (publishFiles, assemblyFiles, buildConfig) {
|
|
|
237
239
|
outPaths.add(asset.out.path)
|
|
238
240
|
}
|
|
239
241
|
}
|
|
240
|
-
if (keepSource)
|
|
241
|
-
|
|
242
|
+
if (keepSource) {
|
|
243
|
+
for (const file of assemblyFiles) {
|
|
244
|
+
file.src.contents = file.contents
|
|
245
|
+
file.out = { path: file.path }
|
|
246
|
+
files.push(file)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return publishFiles({ output: { clean, dir } }, { getFiles: () => files }).then(() => {
|
|
250
|
+
if (keepSource) {
|
|
251
|
+
for (const file of assemblyFiles) delete file.out
|
|
252
|
+
}
|
|
253
|
+
})
|
|
242
254
|
}
|
|
243
255
|
|
|
244
256
|
function resolveFileOrContents (convertResult, convertAttributes, buildConfig, loggerName) {
|
|
245
257
|
let fileOrContents
|
|
246
258
|
if (convertResult?.status != null) {
|
|
247
|
-
|
|
259
|
+
if ('file' in convertResult) {
|
|
260
|
+
fileOrContents = convertResult.file
|
|
261
|
+
} else if ('contents' in convertResult) {
|
|
262
|
+
fileOrContents = convertResult.contents
|
|
263
|
+
} else if (buildConfig.outputOptionFlag === false) {
|
|
264
|
+
fileOrContents = convertResult.stdout
|
|
265
|
+
}
|
|
248
266
|
let logger, match
|
|
249
267
|
if (buildConfig.stderrSink === 'log' && convertResult.stderr.length && (logger = this.getLogger(loggerName))) {
|
|
250
268
|
const docfile = convertAttributes.docfile
|
|
@@ -257,10 +275,15 @@ function resolveFileOrContents (convertResult, convertAttributes, buildConfig, l
|
|
|
257
275
|
if (entry.name) ctx.program = entry.name
|
|
258
276
|
if (entry.file?.line) ctx.line = entry.file.line
|
|
259
277
|
logger[entry.level](ctx, entry.msg)
|
|
260
|
-
} else if ((match = /^(
|
|
278
|
+
} else if ((match = /^([^:]+):(\d+): warning: (.+)/.exec(line))) {
|
|
261
279
|
const [, scriptPath, lineno, msg] = match
|
|
262
280
|
ctx.stack = [{ file: { path: scriptPath }, line: parseInt(lineno, 10) }]
|
|
263
281
|
logger.warn(ctx, msg)
|
|
282
|
+
} else if ((match = /^asciidoctor: ([A-Z]+): (?:[^:]+: line (\d+): )?(.+)/.exec(line))) {
|
|
283
|
+
// NOTE we don't care about the filename in the message since it can only be docfile
|
|
284
|
+
const [, level, lineno, msg] = match
|
|
285
|
+
if (lineno) ctx.line = parseInt(lineno, 10)
|
|
286
|
+
logger[level === 'WARNING' ? 'warn' : level.toLowerCase()](ctx, msg)
|
|
264
287
|
} else {
|
|
265
288
|
logger.info(ctx, line)
|
|
266
289
|
}
|
package/lib/configure.js
CHANGED
|
@@ -1,30 +1,54 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { ASSEMBLY_KEYS } = require('./constants')
|
|
4
|
+
|
|
3
5
|
function configure (context, ...args) {
|
|
4
6
|
internalConfigure.apply(context, args)
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
function internalConfigure (converter, config = {}, providers = {}) {
|
|
8
10
|
this.once('componentsRegistered', ({ contentCatalog, assemblerProfiles }) => {
|
|
11
|
+
contentCatalog.publishableFamilies.add('export')
|
|
9
12
|
if (assemblerProfiles) return
|
|
10
13
|
this.updateVariables({ assemblerProfiles: getAssemblerProfiles(contentCatalog) })
|
|
11
14
|
})
|
|
12
15
|
|
|
13
|
-
this.once('beforeProcess',
|
|
14
|
-
siteAsciiDocConfig.keepSource = true
|
|
15
|
-
})
|
|
16
|
+
this.once('beforeProcess', enableKeepSource)
|
|
16
17
|
|
|
17
18
|
this.once('navigationBuilt', async ({ playbook, contentCatalog }) => {
|
|
18
19
|
const { assembleContent = require('./assemble-content'), ...assembleContentConfig } = providers
|
|
19
|
-
assembleContentConfig.configSource
|
|
20
|
-
|
|
20
|
+
if (assembleContentConfig.configSource?.constructor === Object) {
|
|
21
|
+
await assembleContent.call(this, playbook, contentCatalog, converter, assembleContentConfig)
|
|
22
|
+
} else {
|
|
23
|
+
const singleConfig = !('configFiles' in config)
|
|
24
|
+
const configFiles = singleConfig ? config.configFile : config.configFiles
|
|
25
|
+
for (const configSource of Array.isArray(configFiles) ? configFiles : [configFiles]) {
|
|
26
|
+
const assembleContentConfigWithConfigSource = Object.assign({}, assembleContentConfig, { configSource })
|
|
27
|
+
await assembleContent.call(this, playbook, contentCatalog, converter, assembleContentConfigWithConfigSource)
|
|
28
|
+
if (singleConfig) break
|
|
29
|
+
}
|
|
30
|
+
}
|
|
21
31
|
})
|
|
22
32
|
}
|
|
23
33
|
|
|
34
|
+
function enableKeepSource ({ siteAsciiDocConfig }) {
|
|
35
|
+
if (siteAsciiDocConfig.keepSource instanceof Boolean) return
|
|
36
|
+
siteAsciiDocConfig.keepSource = Object.assign(new Boolean(true), { oldValue: siteAsciiDocConfig.keepSource })
|
|
37
|
+
this.once('navigationBuilt', restoreKeepSource)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function restoreKeepSource ({ siteAsciiDocConfig, contentCatalog }) {
|
|
41
|
+
if (!(siteAsciiDocConfig.keepSource instanceof Boolean)) return
|
|
42
|
+
if ((siteAsciiDocConfig.keepSource = siteAsciiDocConfig.keepSource.oldValue)) return
|
|
43
|
+
contentCatalog.getPages((page) => delete page.src.contents)
|
|
44
|
+
}
|
|
45
|
+
|
|
24
46
|
function getAssemblerProfiles (contentCatalog, assemblerProfiles = new Map()) {
|
|
25
47
|
contentCatalog.getComponents().forEach((component) => {
|
|
26
48
|
component.versions.forEach((componentVersion) => {
|
|
27
|
-
const source =
|
|
49
|
+
const source =
|
|
50
|
+
componentVersion.nav?.origin ??
|
|
51
|
+
[...(componentVersion.origins ?? [])].find((it) => it.descriptor?.ext?.assembler)
|
|
28
52
|
const assemblerConfig = getAssemblerConfigFromDescriptor(source?.descriptor)
|
|
29
53
|
if (!assemblerConfig) return
|
|
30
54
|
const componentVersionRef = `${componentVersion.version}@${componentVersion.name}`
|
|
@@ -37,7 +61,7 @@ function getAssemblerProfiles (contentCatalog, assemblerProfiles = new Map()) {
|
|
|
37
61
|
Object.entries(entry).forEach(([key, val]) => {
|
|
38
62
|
if (key === 'profile' || key === 'nav') return
|
|
39
63
|
const camelKey = key.toLowerCase().replace(/[_-]([a-z0-9])/g, (_, l, idx) => (idx ? l.toUpperCase() : l))
|
|
40
|
-
data[camelKey] = val
|
|
64
|
+
if (ASSEMBLY_KEYS.includes(camelKey)) data[camelKey] = val
|
|
41
65
|
})
|
|
42
66
|
if (nav) {
|
|
43
67
|
data.navFiles = (nav.length ? [...new Set(nav)] : nav).reduce((navFiles, path_) => {
|
package/lib/constants.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = Object.freeze({
|
|
4
|
+
ASSEMBLY_KEYS: [
|
|
5
|
+
'attributes',
|
|
6
|
+
'doctype',
|
|
7
|
+
'dropExplicitXrefText',
|
|
8
|
+
'linkReferenceStyle',
|
|
9
|
+
'insertStartPage',
|
|
10
|
+
'profile',
|
|
11
|
+
'rootLevel',
|
|
12
|
+
'sectionMergeStrategy',
|
|
13
|
+
'xmlIds',
|
|
14
|
+
],
|
|
15
|
+
LEGACY_ASSEMBLY_KEYS: [
|
|
16
|
+
'dropExplicitXrefText',
|
|
17
|
+
'linkReferenceStyle',
|
|
18
|
+
'insertStartPage',
|
|
19
|
+
'rootLevel',
|
|
20
|
+
'sectionMergeStrategy',
|
|
21
|
+
],
|
|
22
|
+
})
|
|
@@ -1,71 +1,34 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
const { makeRe: makePicomatchRx } = require('picomatch')
|
|
3
|
+
const { filterCollection, compilePattern } = require('./util/matcher')
|
|
5
4
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
expandRange: (begin, end, step, opts) => bracesToGroup(opts ? `{${begin}..${end}..${step}}` : `{${begin}..${end}}`),
|
|
9
|
-
fastpaths: false,
|
|
10
|
-
nobracket: true,
|
|
11
|
-
noglobstar: true,
|
|
12
|
-
nonegate: true,
|
|
13
|
-
noquantifiers: true,
|
|
14
|
-
regex: false,
|
|
15
|
-
strictSlashes: true,
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const VERSION_SEPARATOR_RX = /@(?!\()/
|
|
19
|
-
|
|
20
|
-
function compilePatterns (patterns) {
|
|
21
|
-
if (patterns[0].charAt() === '!') patterns = ['**', ...patterns]
|
|
22
|
-
return patterns.map((pattern) => {
|
|
23
|
-
const negated = pattern.charAt() === '!'
|
|
24
|
-
if (negated) pattern = pattern.slice(1)
|
|
25
|
-
let version
|
|
26
|
-
const separatorIdx = pattern.search(VERSION_SEPARATOR_RX)
|
|
27
|
-
if (~separatorIdx) {
|
|
28
|
-
pattern = (version = true) && `${pattern.slice(0, separatorIdx)}%${pattern.slice(separatorIdx + 1) || '*'}`
|
|
29
|
-
}
|
|
30
|
-
return Object.assign(makePicomatchRx(pattern, PICOMATCH_OPTS), {
|
|
31
|
-
globstar: pattern === '**',
|
|
32
|
-
negated,
|
|
33
|
-
star: pattern === '*',
|
|
34
|
-
version,
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
}
|
|
5
|
+
const VERSION_SEPARATOR_RX = /@(?!\()(?=(\w)?)/g
|
|
6
|
+
const US = '\x1f'
|
|
38
7
|
|
|
39
|
-
function filterComponentVersions (components, patterns) {
|
|
8
|
+
function filterComponentVersions (components, { names: patterns, prereleases = true }) {
|
|
40
9
|
if (!patterns.length) return []
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
for (const rx of rxs) {
|
|
47
|
-
let voteIfMatched
|
|
48
|
-
if (matched) {
|
|
49
|
-
if (rx.negated) voteIfMatched = false
|
|
50
|
-
} else if (!rx.negated) {
|
|
51
|
-
voteIfMatched = true
|
|
52
|
-
}
|
|
53
|
-
if (voteIfMatched == null) continue
|
|
54
|
-
if (rx.globstar) {
|
|
55
|
-
matched = voteIfMatched
|
|
56
|
-
} else if (rx.star) {
|
|
57
|
-
if (version === latest) matched = voteIfMatched
|
|
58
|
-
} else if (rx.version) {
|
|
59
|
-
if (rx.test(`${version.version}%${version.name}`)) matched = voteIfMatched
|
|
60
|
-
} else if (version === latest && rx.test(version.name)) {
|
|
61
|
-
matched = voteIfMatched
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return matched
|
|
65
|
-
})
|
|
66
|
-
)
|
|
10
|
+
const candidateMap = components.reduce((accum, { name: componentName, latest, versions }) => {
|
|
11
|
+
for (const version of versions) {
|
|
12
|
+
if (!prereleases && version.prerelease && version !== latest) continue
|
|
13
|
+
accum[`${version.version}${US}${componentName}`] = { componentName, latest: version === latest, value: version }
|
|
14
|
+
}
|
|
67
15
|
return accum
|
|
68
|
-
},
|
|
16
|
+
}, {})
|
|
17
|
+
if (patterns[0].charAt() === '!') patterns = ['**', ...patterns]
|
|
18
|
+
const result = filterCollection(Object.keys(candidateMap), patterns, {
|
|
19
|
+
compilePattern: new Proxy(compilePattern, {
|
|
20
|
+
apply: (target, self, [pattern]) => {
|
|
21
|
+
if (~pattern.indexOf('@')) pattern = pattern.replace(VERSION_SEPARATOR_RX, (_, c) => US + (c ? '' : '*'))
|
|
22
|
+
return target.call(self, pattern)
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
test: (rx, candidate) => {
|
|
26
|
+
if (rx.globstar) return true
|
|
27
|
+
if (rx.star) return candidateMap[candidate].latest
|
|
28
|
+
return rx.test(candidate) || (candidateMap[candidate].latest && rx.test(candidateMap[candidate].componentName))
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
return result.map((it) => candidateMap[it].value)
|
|
69
32
|
}
|
|
70
33
|
|
|
71
34
|
module.exports = filterComponentVersions
|