@antora/assembler 1.0.0-rc.5 → 1.0.0-rc.7
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 +36 -83
- package/lib/compile-conversion-attributes.js +73 -0
- package/lib/configure.js +18 -15
- package/lib/constants.js +1 -0
- package/lib/filter-component-versions.js +1 -1
- package/lib/index.js +1 -1
- package/lib/load-config.js +6 -6
- package/lib/log-command.js +3 -3
- package/lib/produce-assembly-file.js +164 -126
- package/lib/produce-assembly-files.js +126 -144
- package/lib/util/collate-asciidoc-attributes.js +32 -0
- package/lib/util/deep-clone.js +18 -0
- package/lib/util/identify-mutable-attributes.js +25 -0
- package/lib/util/lazy-readable.js +12 -9
- package/lib/util/rewriter.js +36 -11
- package/lib/util/to-hash.js +7 -0
- package/package.json +4 -6
- package/lib/select-mutable-attributes.js +0 -27
|
@@ -11,19 +11,22 @@ const {
|
|
|
11
11
|
rewriteStyleAttribute,
|
|
12
12
|
} = require('./util/rewriter')
|
|
13
13
|
const sanitize = require('./util/sanitize')
|
|
14
|
+
const toHash = require('./util/to-hash')
|
|
14
15
|
const unconvertInlineAsciiDoc = require('./util/unconvert-inline-asciidoc')
|
|
15
16
|
|
|
16
17
|
const ATTR_ENTRY_RX = /^:(!?[\p{Alpha}0-9_][^:]*):(?: |$)/u
|
|
17
18
|
const BUILT_IN_NAMED_ENTITIES = { amp: '&', apos: "'", gt: '>', lt: '<', nbsp: ' ', quot: '"' }
|
|
18
19
|
const CHAR_REF_RX = /&(?:([a-z][a-z]+\d{0,2})|#(?:(\d{2,6})|x([a-z\d]{2,5})));/g
|
|
19
20
|
const DISCARD_ATTRIBUTE_NAMES = [
|
|
20
|
-
'doctype',
|
|
21
|
-
'leveloffset',
|
|
22
|
-
'preface-title',
|
|
21
|
+
'assembly-doctype',
|
|
23
22
|
'assembly-header-attributes',
|
|
24
23
|
'assembly-navtitle',
|
|
25
24
|
'assembly-slug',
|
|
26
25
|
'assembly-style',
|
|
26
|
+
'doctype',
|
|
27
|
+
'leveloffset',
|
|
28
|
+
'page-aliases',
|
|
29
|
+
'preface-title',
|
|
27
30
|
'underscore',
|
|
28
31
|
]
|
|
29
32
|
const { NAMED_ID_ATTR_RX } = require('./util/rx')
|
|
@@ -39,21 +42,20 @@ function produceAssemblyFile (
|
|
|
39
42
|
assemblyModel
|
|
40
43
|
) {
|
|
41
44
|
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
45
|
const pagesInOutline = selectPagesInOutline(outline, pagesByUrl)
|
|
46
|
+
if (outline.urlType === 'internal' && !pagesByUrl.has(outline.pathname) && !outline.items?.length) return
|
|
44
47
|
const { rootLevel, xmlIds } = assemblyModel
|
|
48
|
+
const scratchDoc = loadAsciiDoc(
|
|
49
|
+
{ contents: Buffer.alloc(0), src: { family: 'page', relative: '_scratch.adoc' } },
|
|
50
|
+
undefined,
|
|
51
|
+
asciidocConfig
|
|
52
|
+
)
|
|
45
53
|
const idSeparators = {
|
|
46
54
|
prefix:
|
|
47
55
|
'assembler-idprefix' in asciidocConfig.attributes ? (asciidocConfig.attributes['assembler-idprefix'] ?? '') : '_',
|
|
48
56
|
scope: xmlIds ? '---' : ':::',
|
|
49
57
|
coordinate: xmlIds ? '----' : ':',
|
|
50
|
-
generateIdFromTitle: generateIdFromTitle.bind(
|
|
51
|
-
loadAsciiDoc(
|
|
52
|
-
{ contents: Buffer.alloc(0), src: { family: 'page', relative: 'generate-id-from-title.adoc' } },
|
|
53
|
-
undefined,
|
|
54
|
-
asciidocConfig
|
|
55
|
-
)
|
|
56
|
-
),
|
|
58
|
+
generateIdFromTitle: generateIdFromTitle.bind(scratchDoc),
|
|
57
59
|
}
|
|
58
60
|
const { name: component, version } = componentVersion
|
|
59
61
|
asciidocConfig = prepareAsciiDocConfig(
|
|
@@ -62,12 +64,14 @@ function produceAssemblyFile (
|
|
|
62
64
|
pagesInOutline,
|
|
63
65
|
asciidocConfig,
|
|
64
66
|
assemblyModel,
|
|
65
|
-
idSeparators
|
|
67
|
+
idSeparators,
|
|
68
|
+
scratchDoc
|
|
66
69
|
)
|
|
67
|
-
const
|
|
70
|
+
const builder = buildAsciiDocHeader(componentVersion, outline.content, assemblyModel)
|
|
71
|
+
mergeAsciiDoc(
|
|
68
72
|
loadAsciiDoc,
|
|
69
73
|
contentCatalog,
|
|
70
|
-
|
|
74
|
+
builder,
|
|
71
75
|
componentVersion,
|
|
72
76
|
outline,
|
|
73
77
|
files,
|
|
@@ -78,22 +82,22 @@ function produceAssemblyFile (
|
|
|
78
82
|
assemblyModel
|
|
79
83
|
)
|
|
80
84
|
const stem =
|
|
81
|
-
(
|
|
85
|
+
(builder.slug ? sanitizeSlug(builder.slug) : generateSlug(rootLevel === 0 ? 'index' : builder.navtitle)) ||
|
|
82
86
|
'export-' + (assemblyModel.stemSeq = (assemblyModel.exportSeq ?? 0) + 1)
|
|
83
87
|
const downloadStem = [component, version, stem === 'index' ? '' : stem].filter((it) => it).join('-')
|
|
84
88
|
const file = contentCatalog.createFile({
|
|
85
89
|
asciidoc: asciidocConfig,
|
|
86
90
|
assembler: { assembled: pagesInOutline.assembled, downloadStem, rootLevel },
|
|
87
|
-
contents:
|
|
91
|
+
contents: builder.serialize(),
|
|
88
92
|
src: { component, version, componentVersion, module: 'ROOT', family: 'export', relative: stem + '.adoc' },
|
|
89
93
|
pub: false,
|
|
90
94
|
})
|
|
91
|
-
file.path = file.out.path // use out path as
|
|
95
|
+
file.path = file.src.path = file.out.path // use out path as path so assets can be published to same hierarchy
|
|
92
96
|
delete file.out
|
|
93
97
|
return file
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
function prepareAsciiDocConfig (contentCatalog, ctx, pagesInOutline, asciidocConfig, assemblyModel, idSeparators) {
|
|
100
|
+
function prepareAsciiDocConfig (contentCatalog, ctx, pagesInOutline, asciidocConfig, assemblyModel, idSeparators, doc) {
|
|
97
101
|
let attributesModified
|
|
98
102
|
const configShared = asciidocConfig.$shared
|
|
99
103
|
const sharedAttributes = asciidocConfig.attributes
|
|
@@ -114,7 +118,17 @@ function prepareAsciiDocConfig (contentCatalog, ctx, pagesInOutline, asciidocCon
|
|
|
114
118
|
for (const [name, val] of Object.entries(sharedAttributes)) {
|
|
115
119
|
if (!(val?.constructor === String && ~val.indexOf(':'))) continue
|
|
116
120
|
if (~val.indexOf('xref:')) {
|
|
117
|
-
const newVal = rewriteXrefs(
|
|
121
|
+
const newVal = rewriteXrefs(
|
|
122
|
+
val,
|
|
123
|
+
contentCatalog,
|
|
124
|
+
assemblyModel,
|
|
125
|
+
ctx,
|
|
126
|
+
false,
|
|
127
|
+
pagesInOutline,
|
|
128
|
+
idSeparators,
|
|
129
|
+
null,
|
|
130
|
+
doc
|
|
131
|
+
)
|
|
118
132
|
if (newVal !== val) (attributesModified ??= {})[name] = newVal
|
|
119
133
|
}
|
|
120
134
|
}
|
|
@@ -124,42 +138,65 @@ function prepareAsciiDocConfig (contentCatalog, ctx, pagesInOutline, asciidocCon
|
|
|
124
138
|
}
|
|
125
139
|
|
|
126
140
|
function buildAsciiDocHeader (componentVersion, navtitle, assemblyModel) {
|
|
127
|
-
const
|
|
141
|
+
const { name: componentName, version, displayVersion, title } = componentVersion
|
|
128
142
|
const navtitlePlain = sanitize(navtitle)
|
|
129
143
|
const navtitleAsciiDoc = unconvertInlineAsciiDoc(navtitle)
|
|
130
|
-
const doctitle = (
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
const doctitle = (title === navtitlePlain ? '' : title + ': ') + navtitleAsciiDoc
|
|
145
|
+
const versioned = !!(version && version !== 'master')
|
|
146
|
+
return {
|
|
147
|
+
header: [
|
|
148
|
+
`= ${doctitle}`,
|
|
149
|
+
...(versioned ? [`:revnumber: ${displayVersion}`] : []),
|
|
150
|
+
`:doctype: ${(assemblyModel.doctype ??= 'book')}`,
|
|
151
|
+
':underscore: _',
|
|
152
|
+
`:page-component-name: ${componentName}`,
|
|
153
|
+
`:page-component-version:${versioned ? ' ' + version : ''}`,
|
|
154
|
+
':page-version: {page-component-version}',
|
|
155
|
+
`:page-component-display-version: ${displayVersion}`,
|
|
156
|
+
`:page-component-title: ${title}`,
|
|
157
|
+
],
|
|
158
|
+
currentComponentVersion: componentVersion,
|
|
159
|
+
navtitle,
|
|
160
|
+
setAuthor (author) {
|
|
161
|
+
this.header.splice(1, 0, author)
|
|
162
|
+
},
|
|
163
|
+
setDoctitle (doctitle_) {
|
|
164
|
+
this.header[0] = `= ${doctitle_}`
|
|
165
|
+
},
|
|
166
|
+
setDoctype (doctype) {
|
|
167
|
+
this.header[this.header.findIndex((line) => line.startsWith(':doctype: '))] = `:doctype: ${doctype}`
|
|
168
|
+
},
|
|
169
|
+
setDocid (docid) {
|
|
170
|
+
this.header.unshift(`[#${docid}]`)
|
|
171
|
+
},
|
|
172
|
+
serialize () {
|
|
173
|
+
const normalizedHeader = this.header.filter((it) => it !== ':doctype: article')
|
|
174
|
+
return this.body
|
|
175
|
+
? Buffer.from(normalizedHeader.join('\n') + '\n\n' + this.body.join('\n') + '\n')
|
|
176
|
+
: Buffer.from(normalizedHeader.join('\n') + '\n')
|
|
177
|
+
},
|
|
178
|
+
}
|
|
146
179
|
}
|
|
147
180
|
|
|
148
181
|
function selectPagesInOutline (outlineEntry, pagesByUrl, accum) {
|
|
149
182
|
accum ??= Object.assign(new Map(), { assembled: { pages: new Map(), assets: new Set() } })
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
183
|
+
const { urlType, url, hash, unresolved, items = [] } = outlineEntry
|
|
184
|
+
if (urlType === 'internal' && !unresolved) {
|
|
185
|
+
const pathname = (outlineEntry.pathname ??= hash ? url.substring(0, url.length - hash.length) : url)
|
|
186
|
+
let page
|
|
187
|
+
if (!accum.has(pathname) && (page = pagesByUrl.get(pathname))) {
|
|
188
|
+
accum.set(createResourceKey(page.src), page)
|
|
189
|
+
accum.set(pathname, page)
|
|
190
|
+
}
|
|
154
191
|
}
|
|
155
|
-
for (const item of
|
|
192
|
+
for (const item of items) selectPagesInOutline(item, pagesByUrl, accum)
|
|
156
193
|
return accum
|
|
157
194
|
}
|
|
158
195
|
|
|
159
196
|
function mergeAsciiDoc (
|
|
160
197
|
loadAsciiDoc,
|
|
161
198
|
contentCatalog,
|
|
162
|
-
|
|
199
|
+
builder,
|
|
163
200
|
componentVersion,
|
|
164
201
|
outlineEntry,
|
|
165
202
|
files,
|
|
@@ -168,31 +205,31 @@ function mergeAsciiDoc (
|
|
|
168
205
|
asciidocConfig,
|
|
169
206
|
mutableAttributes,
|
|
170
207
|
assemblyModel,
|
|
171
|
-
lastComponentVersion = componentVersion,
|
|
172
208
|
level = 0,
|
|
173
209
|
supportsParts = false
|
|
174
210
|
) {
|
|
175
|
-
const { items = [], roles = [], unresolved, urlType, url, hash } = outlineEntry
|
|
211
|
+
const { items = [], roles = [], unresolved, urlType, url, pathname, hash } = outlineEntry
|
|
176
212
|
// TODO: we could try to be smart about it and make sure the page with fragment is included at least once
|
|
177
|
-
if (
|
|
178
|
-
|
|
179
|
-
return
|
|
213
|
+
if (roles.includes('site-only') || (urlType === 'external' && !URL.canParse(url))) {
|
|
214
|
+
builder.body ??= []
|
|
215
|
+
return builder
|
|
180
216
|
}
|
|
181
|
-
|
|
217
|
+
const assembled = pagesInOutline.assembled
|
|
218
|
+
// FIXME: ideally, resource ID would be stored in navigation so we can look up the page more efficiently
|
|
219
|
+
const page = urlType === 'internal' && !unresolved ? pagesInOutline.get(pathname) : undefined
|
|
220
|
+
let navtitle = outlineEntry.navtitle ?? (page && hash ? page.asciidoc.navtitle : outlineEntry.content)
|
|
182
221
|
let navtitlePlain = sanitize(navtitle)
|
|
183
222
|
let navtitleAsciiDoc = unconvertInlineAsciiDoc(navtitle)
|
|
184
223
|
const { filetype, linkReferenceStyle, pubRoot, sectionMergeStrategy, siteRoot, logger, rootLevel } = assemblyModel
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const atDocumentRoot = !buffer.inBody
|
|
189
|
-
const atBookRoot = atDocumentRoot && !level && assemblyModel.doctype === 'book' && (supportsParts = true)
|
|
224
|
+
const doctype = assemblyModel.doctype
|
|
225
|
+
const atDocumentRoot = !builder.body?.length
|
|
226
|
+
let atBookRoot = atDocumentRoot && !level && doctype === 'book' && (supportsParts = true)
|
|
190
227
|
const hasItems = items.length > 0
|
|
191
228
|
if (page && !assembled.pages.has(page)) {
|
|
192
229
|
const contents = page.src.contents
|
|
193
230
|
if (contents == null) {
|
|
194
|
-
|
|
195
|
-
return
|
|
231
|
+
builder.body ??= []
|
|
232
|
+
return builder
|
|
196
233
|
}
|
|
197
234
|
const pageAsAsciiDoc = new page.constructor(
|
|
198
235
|
Object.assign({}, page, { contents: trimAsciiDoc(contents), mediaType: page.src.mediaType })
|
|
@@ -208,20 +245,25 @@ function mergeAsciiDoc (
|
|
|
208
245
|
},
|
|
209
246
|
})
|
|
210
247
|
: doc.getLogger()
|
|
211
|
-
doc.source_header_attributes ??=
|
|
248
|
+
doc.source_header_attributes ??= toHash()
|
|
212
249
|
const isRootPage = atDocumentRoot && !level
|
|
213
250
|
const { component, version, module: module_, relative, origin } = page.src
|
|
214
|
-
|
|
251
|
+
const doctypeOverride = doc.getAttribute('assembly-doctype')
|
|
252
|
+
if (doctypeOverride) {
|
|
253
|
+
if (doctypeOverride !== doctype) builder.setDoctype(doctypeOverride)
|
|
254
|
+
if (doctypeOverride !== 'book') atBookRoot = supportsParts = false
|
|
255
|
+
}
|
|
256
|
+
if (isRootPage && doc.hasAttribute('assembly-slug')) builder.slug = doc.getAttribute('assembly-slug')
|
|
215
257
|
let hasAssemblyNavtitleAttr
|
|
216
258
|
if ((hasAssemblyNavtitleAttr = !!doc.getAttribute('assembly-navtitle'))) {
|
|
217
259
|
navtitleAsciiDoc = doc.getAttribute('assembly-navtitle')
|
|
218
260
|
navtitlePlain = sanitize((navtitle = doc.$apply_reftext_subs(navtitleAsciiDoc)))
|
|
219
|
-
if (
|
|
220
|
-
|
|
261
|
+
if (builder.body == null) {
|
|
262
|
+
builder.navtitle = navtitle
|
|
221
263
|
if (rootLevel) {
|
|
222
|
-
|
|
264
|
+
builder.setDoctitle(
|
|
223
265
|
(componentVersion.title === navtitlePlain ? '' : componentVersion.title + ': ') + navtitleAsciiDoc
|
|
224
|
-
|
|
266
|
+
)
|
|
225
267
|
}
|
|
226
268
|
}
|
|
227
269
|
}
|
|
@@ -247,13 +289,10 @@ function mergeAsciiDoc (
|
|
|
247
289
|
let nextSectionLevel = 1
|
|
248
290
|
const lines = doc.getSourceLines()
|
|
249
291
|
const ignoreLines = []
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
buffer.endHeaderIdx = buffer.length - 1
|
|
253
|
-
}
|
|
254
|
-
buffer.push('')
|
|
292
|
+
const buffer = (builder.body ??= [])
|
|
293
|
+
if (buffer.length) buffer.push('')
|
|
255
294
|
buffer.push(`:docname: ${docname}`)
|
|
256
|
-
if (component !==
|
|
295
|
+
if (component !== builder.currentComponentVersion.name) {
|
|
257
296
|
const thisComponentVersion =
|
|
258
297
|
component === componentVersion.name && version === componentVersion.version
|
|
259
298
|
? componentVersion
|
|
@@ -264,7 +303,7 @@ function mergeAsciiDoc (
|
|
|
264
303
|
buffer.push(':page-version: {page-component-version}')
|
|
265
304
|
buffer.push(`:page-component-display-version: ${thisComponentVersion.displayVersion}`)
|
|
266
305
|
buffer.push(`:page-component-title: ${thisComponentVersion.title}`)
|
|
267
|
-
|
|
306
|
+
builder.currentComponentVersion = thisComponentVersion
|
|
268
307
|
}
|
|
269
308
|
}
|
|
270
309
|
buffer.push(`:page-module: ${module_}`)
|
|
@@ -274,12 +313,10 @@ function mergeAsciiDoc (
|
|
|
274
313
|
buffer.push(`:page-origin-refname: ${origin.branch || origin.tag}`)
|
|
275
314
|
buffer.push(`:page-origin-reftype: ${origin.branch ? 'branch' : 'tag'}`)
|
|
276
315
|
buffer.push(`:page-origin-refhash: ${origin.worktree ? '(worktree)' : origin.refhash}`)
|
|
277
|
-
let headerHasBlockAttrs
|
|
278
316
|
if (doc.hasHeader()) {
|
|
279
317
|
for (const entry of processDocumentHeader(doc, lines, ignoreLines, isRootPage)) {
|
|
280
318
|
if (entry.type === 'author_line') {
|
|
281
|
-
|
|
282
|
-
buffer.endHeaderIdx += 1
|
|
319
|
+
builder.setAuthor(entry.lines[0])
|
|
283
320
|
} else if (entry.type === 'attribute_entry') {
|
|
284
321
|
const name = entry.name
|
|
285
322
|
if (!entry.negated && !doc.isAttributeLocked(name)) {
|
|
@@ -320,14 +357,9 @@ function mergeAsciiDoc (
|
|
|
320
357
|
if (newVal !== val) entry.lines = `:${entry.name}: ${newVal}`.split('\n')
|
|
321
358
|
}
|
|
322
359
|
}
|
|
323
|
-
|
|
324
|
-
buffer.splice(buffer.endHeaderIdx + 1, 0, ...entry.lines)
|
|
325
|
-
buffer.endHeaderIdx += entry.lines.length
|
|
326
|
-
} else {
|
|
327
|
-
buffer.push(...entry.lines)
|
|
328
|
-
}
|
|
360
|
+
;(entry.promote ? builder.header : buffer).push(...entry.lines)
|
|
329
361
|
} else {
|
|
330
|
-
if (entry.type === 'attrlist') headerHasBlockAttrs = true
|
|
362
|
+
if (entry.type === 'attrlist') builder.headerHasBlockAttrs = true
|
|
331
363
|
buffer.push(...entry.lines)
|
|
332
364
|
}
|
|
333
365
|
}
|
|
@@ -351,15 +383,15 @@ function mergeAsciiDoc (
|
|
|
351
383
|
if (htitleOverride != null) {
|
|
352
384
|
const keepSections = hasSections && sectionMergeStrategy !== 'discrete'
|
|
353
385
|
if (htitleOverride === '') {
|
|
354
|
-
if (headerHasBlockAttrs || keepSections) {
|
|
386
|
+
if (builder.headerHasBlockAttrs || keepSections) {
|
|
355
387
|
htitleAsciiDoc = '{empty}'
|
|
356
388
|
notitle = true
|
|
357
389
|
} else {
|
|
358
|
-
if (hasPrefaceTitleAttr)
|
|
390
|
+
if (hasPrefaceTitleAttr) builder.header.push(':preface-title:')
|
|
359
391
|
htitleAsciiDoc = undefined
|
|
360
392
|
}
|
|
361
|
-
} else if (hasPrefaceTitleAttr && !headerHasBlockAttrs && !keepSections) {
|
|
362
|
-
|
|
393
|
+
} else if (hasPrefaceTitleAttr && !builder.headerHasBlockAttrs && !keepSections) {
|
|
394
|
+
builder.header.push(`:preface-title: ${unconvertInlineAsciiDoc(htitleOverride)}`)
|
|
363
395
|
htitleAsciiDoc = undefined
|
|
364
396
|
} else {
|
|
365
397
|
htitleAsciiDoc = unconvertInlineAsciiDoc(htitleOverride)
|
|
@@ -370,7 +402,7 @@ function mergeAsciiDoc (
|
|
|
370
402
|
if (atDocumentRoot) {
|
|
371
403
|
// Q: should we use htitleAsciiDoc to generate ID if not {empty} instead of pageStyle
|
|
372
404
|
pageFragment = `#_${idSeparators.coordinate}${pageIdLeader}${pageStyle}`
|
|
373
|
-
|
|
405
|
+
builder.setDocid(pageId)
|
|
374
406
|
} else {
|
|
375
407
|
pageFragment = `#${pageId}`
|
|
376
408
|
}
|
|
@@ -400,7 +432,7 @@ function mergeAsciiDoc (
|
|
|
400
432
|
buffer.push(`[${heading.style ?? pageStyle}${pageFragment}${rolesAttr}${notitleAttrs}]`)
|
|
401
433
|
buffer.push(`${'='.repeat(heading.level)} ${heading.title}`)
|
|
402
434
|
} else if (atDocumentRoot) {
|
|
403
|
-
|
|
435
|
+
builder.setDocid(pageId)
|
|
404
436
|
}
|
|
405
437
|
if (sectionMergeStrategy === 'enclose' && hasItems && hasSections && !(atDocumentRoot && heading)) {
|
|
406
438
|
// TODO: make overview section title configurable
|
|
@@ -408,7 +440,7 @@ function mergeAsciiDoc (
|
|
|
408
440
|
//if (overviewTitle === navtitle) overviewTitle = doc.getAttribute('overview-title', 'Overview')
|
|
409
441
|
const overviewTitle = doc.getAttribute('overview-title', 'Overview')
|
|
410
442
|
const syntheticId = idSeparators.generateIdFromTitle(overviewTitle, idSeparators, pageIdLeader)
|
|
411
|
-
if (heading) buffer.push('')
|
|
443
|
+
if (heading && buffer.length) buffer.push('')
|
|
412
444
|
let hlevel = level + (nextSectionLevel = 2)
|
|
413
445
|
if (hlevel > 6) {
|
|
414
446
|
const blockStyle = `discrete.h${hlevel}`
|
|
@@ -429,7 +461,7 @@ function mergeAsciiDoc (
|
|
|
429
461
|
if (doc.getDoctype() === 'manpage') {
|
|
430
462
|
const firstSectionIdx = hasSections ? doc.getSections()[0].getLineNumber() - 1 : lines.length
|
|
431
463
|
for (let idx = 0; idx < firstSectionIdx; idx++) {
|
|
432
|
-
if (
|
|
464
|
+
if (ignoreLines.includes(idx)) continue
|
|
433
465
|
const line = lines[idx]
|
|
434
466
|
if (line.startsWith('== ') && line.length > 3) {
|
|
435
467
|
allBlocks.unshift({
|
|
@@ -473,7 +505,7 @@ function mergeAsciiDoc (
|
|
|
473
505
|
})
|
|
474
506
|
let skipping
|
|
475
507
|
for (let idx = 0, lastIdx = lines.length - 1; idx <= lastIdx; idx++) {
|
|
476
|
-
if (
|
|
508
|
+
if (ignoreLines.includes(idx)) continue
|
|
477
509
|
let line = lines[idx]
|
|
478
510
|
if (line.startsWith('//')) {
|
|
479
511
|
if (line.charAt(2) !== '/') continue
|
|
@@ -589,10 +621,13 @@ function mergeAsciiDoc (
|
|
|
589
621
|
buffer,
|
|
590
622
|
lines.filter((it) => it !== undefined)
|
|
591
623
|
)
|
|
592
|
-
const attributeEntries =
|
|
624
|
+
const attributeEntries = doc.source_header_attributes.$entries()
|
|
593
625
|
if (attributeEntries.length) {
|
|
594
626
|
const resolvedAttributeEntries = attributeEntries.reduce(
|
|
595
627
|
(accum, [name, val]) => {
|
|
628
|
+
if (val) {
|
|
629
|
+
if (val['$nil?']()) val = null
|
|
630
|
+
}
|
|
596
631
|
// Q: couldn't we just check if attribute is locked?
|
|
597
632
|
if (name in mutableAttributes) {
|
|
598
633
|
const initialVal = mutableAttributes[name]
|
|
@@ -610,19 +645,18 @@ function mergeAsciiDoc (
|
|
|
610
645
|
)
|
|
611
646
|
if (resolvedAttributeEntries.length > 1) safePush(buffer, resolvedAttributeEntries)
|
|
612
647
|
}
|
|
613
|
-
} else if (level) {
|
|
648
|
+
} else if (level && !hash) {
|
|
649
|
+
const buffer = (builder.body ??= [])
|
|
614
650
|
if (atDocumentRoot && rootLevel === 0 && navtitlePlain === componentVersion.title) {
|
|
615
|
-
buffer.inBody ??= false
|
|
616
651
|
level--
|
|
617
652
|
} else {
|
|
618
|
-
buffer.
|
|
619
|
-
buffer.push('')
|
|
653
|
+
if (buffer.length) buffer.push('')
|
|
620
654
|
const syntheticId = idSeparators.generateIdFromTitle(navtitleAsciiDoc, idSeparators)
|
|
621
655
|
let sectionTitle = navtitleAsciiDoc
|
|
622
656
|
if (urlType === 'external') {
|
|
623
657
|
sectionTitle = `${url}[${navtitleAsciiDoc.replace(/\]/g, '\\]')}]`
|
|
624
658
|
} else if (urlType === 'internal' && !unresolved) {
|
|
625
|
-
const resource = files.find((it) => it.pub.url ===
|
|
659
|
+
const resource = files.find((it) => it.pub.url === pathname)
|
|
626
660
|
if (resource) {
|
|
627
661
|
if (resource.src.family === 'page' && pagesInOutline.has(resource.pub.url)) {
|
|
628
662
|
const refid = generateScopedId(resource.src, componentVersion, idSeparators, filetype, true)
|
|
@@ -632,38 +666,39 @@ function mergeAsciiDoc (
|
|
|
632
666
|
}
|
|
633
667
|
}
|
|
634
668
|
}
|
|
669
|
+
if (supportsParts && level === 1 && roles.includes('part')) {
|
|
670
|
+
roles.splice(roles.indexOf('part', 1))
|
|
671
|
+
level--
|
|
672
|
+
}
|
|
635
673
|
const hlevel = level > 5 ? 6 : level + 1
|
|
636
674
|
const hroles = urlType === 'internal' ? roles.slice(1) : roles
|
|
637
675
|
buffer.push(`[${hlevel > 6 ? 'discrete' : ''}#${syntheticId}${hroles.reduce((str, it) => str + '.' + it, '')}]`)
|
|
638
676
|
buffer.push(`${'='.repeat(hlevel)} ${sectionTitle}`)
|
|
639
677
|
}
|
|
640
678
|
}
|
|
641
|
-
if (hasItems)
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
})
|
|
665
|
-
}
|
|
666
|
-
return buffer
|
|
679
|
+
if (!hasItems) return
|
|
680
|
+
const nextLevel = level + 1
|
|
681
|
+
// NOTE: drop first child if same as parent; should we keep if content is different?
|
|
682
|
+
;(urlType === 'internal' && items[0].urlType === 'internal' && pathname === items[0].url && !items[0].items?.length
|
|
683
|
+
? items.slice(1)
|
|
684
|
+
: items
|
|
685
|
+
).forEach((item) => {
|
|
686
|
+
mergeAsciiDoc(
|
|
687
|
+
loadAsciiDoc,
|
|
688
|
+
contentCatalog,
|
|
689
|
+
builder,
|
|
690
|
+
componentVersion,
|
|
691
|
+
item,
|
|
692
|
+
files,
|
|
693
|
+
pagesInOutline,
|
|
694
|
+
idSeparators,
|
|
695
|
+
asciidocConfig,
|
|
696
|
+
mutableAttributes,
|
|
697
|
+
assemblyModel,
|
|
698
|
+
nextLevel,
|
|
699
|
+
atBookRoot
|
|
700
|
+
)
|
|
701
|
+
})
|
|
667
702
|
}
|
|
668
703
|
|
|
669
704
|
function processDocumentHeader (doc, lines, ignoreLines, isRootPage) {
|
|
@@ -702,7 +737,7 @@ function processDocumentHeader (doc, lines, ignoreLines, isRootPage) {
|
|
|
702
737
|
}
|
|
703
738
|
const line = lines[idx]
|
|
704
739
|
if (open === ':' || open === '-:') {
|
|
705
|
-
if (open === ':') current.
|
|
740
|
+
if (open === ':') current.appendLine(line)
|
|
706
741
|
if (!line?.endsWith(' \\')) current = open = undefined
|
|
707
742
|
} else if (line) {
|
|
708
743
|
let attributeEntryMatch
|
|
@@ -710,13 +745,14 @@ function processDocumentHeader (doc, lines, ignoreLines, isRootPage) {
|
|
|
710
745
|
if (chr0 === '/' && line.charAt(1) === '/') {
|
|
711
746
|
if (line.startsWith('////') && line === '/'.repeat(line.length)) {
|
|
712
747
|
if (open) {
|
|
713
|
-
current.
|
|
748
|
+
current.appendLine(line)
|
|
714
749
|
if (open === line) current = open = undefined
|
|
715
750
|
} else {
|
|
716
751
|
entries.push((current = { type: 'block_comment', lines: [(open = line)] }))
|
|
752
|
+
current.appendLine = Array.prototype.push.bind(current.lines)
|
|
717
753
|
}
|
|
718
754
|
} else if (open) {
|
|
719
|
-
current.
|
|
755
|
+
current.appendLine(line)
|
|
720
756
|
} else if (belowDoctitle && line.charAt(2) === '/') {
|
|
721
757
|
break
|
|
722
758
|
} else {
|
|
@@ -724,7 +760,7 @@ function processDocumentHeader (doc, lines, ignoreLines, isRootPage) {
|
|
|
724
760
|
current = undefined
|
|
725
761
|
}
|
|
726
762
|
} else if (open) {
|
|
727
|
-
current.
|
|
763
|
+
current.appendLine(line)
|
|
728
764
|
} else if (chr0 === ':' && ~line.indexOf(':', 2) && (attributeEntryMatch = line.match(ATTR_ENTRY_RX))) {
|
|
729
765
|
let name = attributeEntryMatch[1]
|
|
730
766
|
const negated = name.charAt() === '!' || name.charAt(name.length - 1) === '!'
|
|
@@ -733,7 +769,9 @@ function processDocumentHeader (doc, lines, ignoreLines, isRootPage) {
|
|
|
733
769
|
if (line.endsWith(' \\')) open = '-:' // disallow value continuation
|
|
734
770
|
} else {
|
|
735
771
|
if (line.endsWith(' \\')) open = ':'
|
|
736
|
-
entries.push((current = { type: 'attribute_entry', name, negated, lines: [
|
|
772
|
+
entries.push((current = { type: 'attribute_entry', name, negated, lines: [], lineno: idx + 1 }))
|
|
773
|
+
current.lines.push(negated ? `:!${name}:` : line)
|
|
774
|
+
current.appendLine = Array.prototype.push.bind(negated ? [] : current.lines)
|
|
737
775
|
if (assemblyHeaderAttributes.has(name)) current.promote = true
|
|
738
776
|
}
|
|
739
777
|
} else if (belowDoctitle) {
|
|
@@ -807,13 +845,13 @@ function safePush (onto, entries) {
|
|
|
807
845
|
}
|
|
808
846
|
|
|
809
847
|
function generateIdFromTitle (titleAsciiDoc, idSeparators, idLeader) {
|
|
810
|
-
const Section = this.$class()
|
|
848
|
+
const Section = this.$class().$$base_module.Section
|
|
811
849
|
const baseId = Section.$generate_id(titleAsciiDoc, this) // refs in catalog will always be empty
|
|
812
850
|
let id = `_${idSeparators.coordinate}${idLeader ?? ''}${baseId}`
|
|
813
851
|
const syntheticIds = (this.catalog.syntheticIds ??= {})
|
|
814
852
|
if (id in syntheticIds) {
|
|
815
853
|
const sep = (this.getAttribute('idseparator') ?? '_').charAt()
|
|
816
|
-
let cnt = this.$class()
|
|
854
|
+
let cnt = this.$class().$$base_module.Compliance.unique_id_start_index
|
|
817
855
|
let candidate
|
|
818
856
|
while ((candidate = `${id}${sep}${cnt}`) in syntheticIds) cnt++
|
|
819
857
|
id = candidate
|