@antora/assembler 1.0.0-rc.10 → 1.0.0-rc.11

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.
@@ -18,12 +18,13 @@ const ATTR_ENTRY_RX = /^:(!?[\p{Alpha}0-9_][^:]*):(?: |$)/u
18
18
  const BUILT_IN_NAMED_ENTITIES = { amp: '&', apos: "'", gt: '>', lt: '<', nbsp: ' ', quot: '"' }
19
19
  const CHAR_REF_RX = /&(?:([a-z][a-z]+\d{0,2})|#(?:(\d{2,6})|x([a-z\d]{2,5})));/g
20
20
  const DISCARD_ATTRIBUTE_NAMES = [
21
+ 'assembly-docname',
22
+ 'assembly-doctitle',
21
23
  'assembly-doctype',
22
24
  'assembly-header-attributes',
23
25
  'assembly-overview-title',
24
26
  'assembly-navtitle',
25
27
  'assembly-root-title',
26
- 'assembly-slug',
27
28
  'assembly-style',
28
29
  'doctype',
29
30
  'leveloffset',
@@ -88,7 +89,9 @@ function produceAssemblyFile (
88
89
  assemblyModel
89
90
  )
90
91
  const stem =
91
- (builder.slug ? sanitizeSlug(builder.slug) : generateSlug(rootLevel === 0 ? 'index' : builder.baseDoctitle)) ||
92
+ (builder.docname
93
+ ? sanitizeDocname(builder.docname)
94
+ : generateDocname(rootLevel === 0 ? 'index' : builder.baseDoctitle)) ||
92
95
  'export-' + (assemblyModel.stemSeq = (assemblyModel.exportSeq ?? 0) + 1)
93
96
  const downloadStem = [component, version, stem === 'index' ? '' : stem].filter((it) => it).join('-')
94
97
  const file = contentCatalog.createFile({
@@ -147,7 +150,7 @@ function buildAssemblyHeader (componentVersion, navtitle, assemblyModel) {
147
150
  const { name: componentName, version, displayVersion, title } = componentVersion
148
151
  const navtitleAsciiDoc = unconvertInlineAsciiDoc(navtitle)
149
152
  const navtitlePlain = sanitize(navtitle)
150
- const doctitleQualifier = assemblyModel.rootLevel === 0 ? '' : title
153
+ const doctitleQualifier = assemblyModel.rootLevel === 0 ? undefined : title
151
154
  const versioned = !!(version && version !== 'master')
152
155
  return {
153
156
  header: [
@@ -168,10 +171,10 @@ function buildAssemblyHeader (componentVersion, navtitle, assemblyModel) {
168
171
  setAuthor (author) {
169
172
  this.header.splice(1, 0, author)
170
173
  },
171
- setDoctitle (doctitle, doctitleAsciiDoc, doctitlePlain) {
174
+ updateDoctitle (doctitle, doctitleAsciiDoc, doctitlePlain, useQualifier = true) {
172
175
  this.baseDoctitle = doctitle
173
176
  this.baseDoctitlePlain = doctitlePlain
174
- const qualifyDoctitle = this.doctitleQualifier ? this.doctitleQualifier !== doctitlePlain : false
177
+ const qualifyDoctitle = useQualifier && !!this.doctitleQualifier && this.doctitleQualifier !== doctitlePlain
175
178
  this.header[0] = `= ${qualifyDoctitle ? this.doctitleQualifier + ': ' : ''}${doctitleAsciiDoc}`
176
179
  },
177
180
  matchesDoctitle (candidate) {
@@ -234,7 +237,7 @@ function mergeAsciiDoc (
234
237
  let navtitle = outlineEntry.navtitle ?? (page && hash ? page.asciidoc.navtitle : outlineEntry.content)
235
238
  let navtitleAsciiDoc = unconvertInlineAsciiDoc(navtitle)
236
239
  let navtitlePlain = sanitize(navtitle)
237
- const { doctype, filetype, linkReferenceStyle, pubRoot, siteRoot, logger, rootPageStyle } = assemblyModel
240
+ const { doctype, filetype, linkReferenceStyle, pubRoot, siteRoot, logger, rootLevel, rootPageStyle } = assemblyModel
238
241
  let sectionMergeStrategy = assemblyModel.sectionMergeStrategy
239
242
  const atStartOfBody = !builder.body?.length
240
243
  const isRootEntry = atStartOfBody && !level
@@ -256,22 +259,32 @@ function mergeAsciiDoc (
256
259
  doc.source_header_attributes ??= toHash()
257
260
  const isRootPage = isRootEntry
258
261
  const { component, version, module: module_, relative, origin } = page.src
259
- const doctypeOverride = doc.getAttribute('assembly-doctype')
260
- if (doctypeOverride) {
261
- if (doctypeOverride !== doctype) builder.setDoctype(doctypeOverride)
262
- if (doctypeOverride !== 'book') atBookRoot = supportsParts = false
263
- }
264
- if (isRootPage && doc.hasAttribute('assembly-slug')) builder.slug = doc.getAttribute('assembly-slug')
265
262
  let hasAssemblyNavtitleAttr
266
263
  if ((hasAssemblyNavtitleAttr = !!doc.getAttribute('assembly-navtitle'))) {
267
- navtitleAsciiDoc = doc.getAttribute('assembly-navtitle')
268
- navtitlePlain = sanitize((navtitle = doc.$apply_reftext_subs(navtitleAsciiDoc)))
269
- if (isRootPage) builder.setDoctitle(navtitle, navtitleAsciiDoc, navtitlePlain)
264
+ navtitleAsciiDoc = unconvertInlineAsciiDoc(doc.getAttribute('assembly-navtitle'))
265
+ navtitlePlain = sanitize((navtitle = doc.$sub_attributes(doc.$apply_reftext_subs(navtitleAsciiDoc))))
266
+ }
267
+ if (isRootPage) {
268
+ const doctypeOverride = doc.getAttribute('assembly-doctype')
269
+ if (doctypeOverride && doctypeOverride !== doctype) {
270
+ builder.setDoctype(doctypeOverride)
271
+ if (doctypeOverride !== 'book') atBookRoot = supportsParts = false
272
+ }
273
+ if (doc.hasAttribute('assembly-docname')) builder.docname = doc.getAttribute('assembly-docname')
274
+ const doctitleOverride = doc.getAttribute('assembly-doctitle')
275
+ if (doctitleOverride) {
276
+ let doctitle
277
+ const doctitleAsciiDoc = unconvertInlineAsciiDoc(doctitleOverride)
278
+ const doctitlePlain = sanitize((doctitle = doc.$sub_attributes(doc.$apply_reftext_subs(doctitleAsciiDoc))))
279
+ builder.updateDoctitle(doctitle, doctitleAsciiDoc, doctitlePlain, false)
280
+ } else if (hasAssemblyNavtitleAttr && rootLevel) {
281
+ builder.updateDoctitle(navtitle, navtitleAsciiDoc, navtitlePlain)
282
+ }
270
283
  }
271
- const overviewTitle = doc.getAttribute('assembly-overview-title', 'Overview')
284
+ const overviewTitle = doc.getAttribute('assembly-overview-title') || 'Overview'
272
285
  let overviewTitleAsciiDoc
273
286
  // NOTE: in Antora, docname is relative src path from module without file extension
274
- const docname = doc.getAttribute('docname')
287
+ const pageDocname = doc.getAttribute('docname')
275
288
  const pageId = generateScopedId(page.src, componentVersion, idSeparators, filetype)
276
289
  const pageIdLeader = pageId + idSeparators.scope
277
290
  let pageFragment = `#${pageId}`
@@ -299,6 +312,7 @@ function mergeAsciiDoc (
299
312
  const ignoreLines = []
300
313
  const buffer = (builder.body ??= [])
301
314
  if (buffer.length) buffer.push('')
315
+ let headerHasBlockAttrs
302
316
  if (doc.hasHeader()) {
303
317
  for (const entry of processPageHeader(doc, lines, ignoreLines, isRootPage)) {
304
318
  if (entry.type === 'author_line') {
@@ -315,8 +329,8 @@ function mergeAsciiDoc (
315
329
  (val = doc.getAttribute(name)) &&
316
330
  (newVal = rewriteImageAttr(val, contentCatalog, assemblyModel, page.src, assembled.assets)) != null
317
331
  ) {
318
- if (newVal !== val) entry.lines = [`:${name}: ${newVal}`]
319
- } else if (~(val = entry.lines.join('\n').substring(name.length + 3)).indexOf(':')) {
332
+ if (newVal !== val) entry.value = newVal
333
+ } else if (~(val = entry.value).indexOf(':')) {
320
334
  newVal = val
321
335
  if (~newVal.indexOf('image:')) {
322
336
  newVal = rewriteInlineImages(
@@ -343,19 +357,19 @@ function mergeAsciiDoc (
343
357
  { file: relative, lineno: entry.lineno }
344
358
  )
345
359
  }
346
- if (newVal !== val) entry.lines = `:${entry.name}: ${newVal}`.split('\n')
360
+ if (newVal !== val) entry.value = newVal
347
361
  }
348
362
  }
349
363
  ;(entry.promote ? builder.header : buffer).push(...entry.lines)
350
364
  } else {
351
- if (entry.type === 'attrlist') builder.headerHasBlockAttrs = true
365
+ if (entry.type === 'attrlist') headerHasBlockAttrs = true
352
366
  buffer.push(...entry.lines)
353
367
  }
354
368
  }
355
369
  pageRoles = doc.getRoles()
356
370
  }
357
371
  if (roles.length) pageRoles = pageRoles.concat(roles[0] === 'page' ? roles.slice(1) : roles)
358
- buffer.push(`:page-docname: ${docname}`)
372
+ buffer.push(`:page-docname: ${pageDocname}`)
359
373
  if (component !== builder.currentComponentVersion.name) {
360
374
  const thisComponentVersion =
361
375
  component === componentVersion.name && version === componentVersion.version
@@ -398,7 +412,7 @@ function mergeAsciiDoc (
398
412
  }
399
413
  if (htitleOverride === '') {
400
414
  nextSectionLevel = 2
401
- if (builder.headerHasBlockAttrs) {
415
+ if (headerHasBlockAttrs) {
402
416
  htitleAsciiDoc = ''
403
417
  } else {
404
418
  sectionMergeStrategy = 'discrete'
@@ -410,7 +424,7 @@ function mergeAsciiDoc (
410
424
  htitleAsciiDoc = htitleOverride == null ? navtitleAsciiDoc : unconvertInlineAsciiDoc(htitleOverride)
411
425
  if (htitleOverride === overviewTitle) overviewTitleAsciiDoc = htitleAsciiDoc // optimization
412
426
  if (atBookRoot && hasPrefaceTitleAttr) {
413
- if (!builder.headerHasBlockAttrs && (sectionMergeStrategy === 'discrete' || !hasSections)) {
427
+ if (!headerHasBlockAttrs && (sectionMergeStrategy === 'discrete' || !hasSections)) {
414
428
  builder.header.push(`:preface-title: ${htitleAsciiDoc}`)
415
429
  htitleAsciiDoc = undefined
416
430
  }
@@ -447,15 +461,17 @@ function mergeAsciiDoc (
447
461
  } else if (level) {
448
462
  if (atStartOfBody && !pageStyle && builder.matchesDoctitle(navtitlePlain)) {
449
463
  level--
450
- } else if ((heading = { title: navtitleAsciiDoc, hlevel: level + 1 }).hlevel > 6) {
451
- Object.assign(heading, { hlevel: 6, style: `discrete.h${heading.hlevel}` })
464
+ if (headerHasBlockAttrs) heading = { title: '', hlevel: ++level + 1 }
465
+ } else {
466
+ heading = { title: navtitleAsciiDoc, hlevel: level + 1 }
452
467
  }
453
468
  }
454
469
  if (heading) {
470
+ if (heading.hlevel > 6) Object.assign(heading, { hlevel: 6, style: `discrete.h${heading.hlevel}` })
455
471
  const rolesAttr = pageRoles.reduce((str, it) => str + '.' + it, '')
456
472
  const notitle = (heading.title ||= '{empty}') === '{empty}'
457
473
  // remove conditional if we always want to promote ID of root page to docid
458
- if (notitle) {
474
+ if (notitle && atStartOfBody) {
459
475
  builder.setDocid(pageId)
460
476
  pageFragment = '#' + idSeparators.generateIdFromTitle('', idSeparators, pageIdLeader)
461
477
  }
@@ -799,6 +815,14 @@ function processPageHeader (doc, lines, ignoreLines, isRootPage) {
799
815
  } else {
800
816
  if (line.endsWith(' \\')) open = ':'
801
817
  entries.push((current = { type: 'attribute_entry', name, negated, lines: [], lineno: idx + 1 }))
818
+ Object.defineProperty(current, 'value', {
819
+ get () {
820
+ return this.lines.join('\n').substring(this.name.length + 3)
821
+ },
822
+ set (newValue) {
823
+ this.lines = `:${this.name}: ${newValue}`.split('\n')
824
+ },
825
+ })
802
826
  current.lines.push(negated ? `:!${name}:` : line)
803
827
  current.appendLine = Array.prototype.push.bind(negated ? [] : current.lines)
804
828
  if (assemblyHeaderAttributes.has(name)) current.promote = true
@@ -824,9 +848,9 @@ function processPageHeader (doc, lines, ignoreLines, isRootPage) {
824
848
  return entries
825
849
  }
826
850
 
827
- function generateSlug (string) {
851
+ function generateDocname (string) {
828
852
  if (string === 'index') return string
829
- return sanitizeSlug(
853
+ return sanitizeDocname(
830
854
  string
831
855
  .toLowerCase()
832
856
  .replace(/<[^>]+>/g, '')
@@ -839,8 +863,8 @@ function generateSlug (string) {
839
863
  )
840
864
  }
841
865
 
842
- function sanitizeSlug (slug) {
843
- return slug.replace(/[^\p{Alpha}0-9_.-]/gu, '-').replace(/^-+|-+$|(-)-+/g, '$1')
866
+ function sanitizeDocname (docname) {
867
+ return docname.replace(/[^\p{Alpha}0-9_.-]/gu, '-').replace(/^-+|-+$|(-)-+/g, '$1')
844
868
  }
845
869
 
846
870
  function fixSectionLevels (sections, expectedLevel) {
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const ATTRIBUTE_REFERENCE_RX = /\{[a-z0-9_][a-z0-9_-]*\}/g
3
+ const ATTRIBUTE_REFERENCE_RX = /\{[A-Za-z0-9_][A-Za-z0-9_-]*\}/g
4
4
  const STRICT_WORD_CHAR_RX = /[\p{L}\d_]/u
5
5
  const WORD_CHAR_RX = /[\p{L}\d_;}:<>]/u
6
6
  const XML_SPECIAL_CHARS = { '&lt;': '<', '&gt;': '>', '&amp;': '&' }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antora/assembler",
3
- "version": "1.0.0-rc.10",
3
+ "version": "1.0.0-rc.11",
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)",