@antora/assembler 1.0.0-beta.14 → 1.0.0-beta.16

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.
@@ -121,6 +121,7 @@ function mergeAsciiDoc (
121
121
  outDirname,
122
122
  siteRoot,
123
123
  xmlIds,
124
+ logger,
124
125
  } = assemblyModel
125
126
  // FIXME: ideally, resource ID would be stored in navigation so we can look up the page more efficiently
126
127
  const page = urlType === 'internal' && !unresolved ? pagesInOutline.get(url) : undefined
@@ -142,6 +143,16 @@ function mergeAsciiDoc (
142
143
  Object.assign({}, page, { contents: trimAsciiDoc(contents), mediaType })
143
144
  )
144
145
  const doc = loadAsciiDoc(pageAsAsciiDoc, contentCatalog, asciidocConfig)
146
+ let asciidoctorLogger = doc.getLogger()
147
+ if (logger) {
148
+ asciidoctorLogger = Object.assign(asciidoctorLogger.$dup(), {
149
+ delegate: {
150
+ warn () {
151
+ return logger.warn.apply(logger, arguments)
152
+ },
153
+ },
154
+ })
155
+ }
145
156
  if (doc.hasAttribute('assembly-navtitle')) {
146
157
  navtitleAsciiDoc = doc.getAttribute('assembly-navtitle')
147
158
  navtitlePlain = sanitize((navtitle = doc.$apply_reftext_subs(navtitleAsciiDoc)))
@@ -307,6 +318,10 @@ function mergeAsciiDoc (
307
318
  }
308
319
  }
309
320
  const refs = doc.getCatalog().refs
321
+ const scannedInlineAnchors = Object.values(refs.$$smap).reduce((accum, it) => {
322
+ if (it.node_name === 'inline_anchor') accum[it.id] = it
323
+ return accum
324
+ }, {})
310
325
  allBlocks.forEach((block) => {
311
326
  const contentModel = block.content_model
312
327
  if (
@@ -365,16 +380,22 @@ function mergeAsciiDoc (
365
380
  if (!refs['$key?'](refid) && (~refid.indexOf(' ') || refid.toLowerCase() !== refid)) {
366
381
  if ((refid = doc.$resolve_id(refid))['$nil?']()) return m
367
382
  }
368
- return `<<${idPrefix}${refid}${text ? ',' + text : ''}>>`
383
+ const alphaPrefix = !(refid in scannedInlineAnchors) || /^[\p{Alpha}_:]/u.test(idPrefix) ? '' : 'iid-'
384
+ return `<<${alphaPrefix}${idPrefix}${refid}${text ? ',' + text : ''}>>`
369
385
  })
370
386
  }
371
387
  // NOTE: the next check takes care of inline and block anchors
372
388
  if (~line.indexOf('[[')) {
373
- line = line.replace(/\[\[([\p{Alpha}_:][\p{Alpha}0-9_\-:.]*)(|, *.+?)\]\]/gu, `[[${idPrefix}$1$2]]`)
389
+ line = line.replace(/\[\[([\p{Alpha}_:][\p{Alpha}0-9_\-:.]*)(|, *.+?)\]\]/gu, (m, refid, text) => {
390
+ const alphaPrefix = !(refid in scannedInlineAnchors) || /^[\p{Alpha}_:]/u.test(idPrefix) ? '' : 'iid-'
391
+ return `[[${alphaPrefix}${idPrefix}${refid}${text}]]`
392
+ })
374
393
  }
375
394
  if (~line.indexOf('xref:')) {
376
395
  // Q: should we allow : as first character of target?
377
- line = line.replace(/(?<![\\+])xref:((?:\.\/)?[\p{Alpha}0-9_/.{#].*?)\[(|.*?[^\\])\]/gu, (m, target, text) => {
396
+ line = line.replace(/(?<![\\+])xref:((?:\.\/)?[\p{Alpha}0-9_/.{#].*?)\[(|.*?[^\\])\]/gu, (_, target_, text) => {
397
+ let target = target_
398
+ if (~target.indexOf('{')) target = doc.$sub_attributes(target, Opal.hash({ attribute_missing: 'skip' }))
378
399
  let fragment, resource, resourceRef
379
400
  const hashIdx = target.indexOf('#')
380
401
  if (~hashIdx) {
@@ -389,21 +410,23 @@ function mergeAsciiDoc (
389
410
  // Q: should we validate the internal ID here?
390
411
  if (!resourceRef) return `xref:${idPrefix}${fragment}[${text}]`
391
412
  const resourceId = parseResourceRef(resourceRef, page.src, 'page', contentCatalog)
392
- if (resourceId.family !== 'page') {
393
- if (siteRoot && (resource = contentCatalog.getById(resourceId))?.pub) {
394
- text ||= resource.asciidoc?.xreftext || target
395
- return `${resolveLinkTarget(resource, siteRoot, pubRoot, linkRefStyle)}${fragment && '#' + fragment}[${text}]`
396
- }
397
- // TODO: handle unresolved resource better
398
- return m
399
- }
400
- if (!(resource = pagesInOutline.get(createResourceKey(resourceId)))) {
401
- if (siteRoot && (resource = contentCatalog.getById(resourceId))?.pub) {
402
- text ||= resource.asciidoc?.xreftext || target
403
- return `${resolveLinkTarget(resource, siteRoot, pubRoot, linkRefStyle)}${fragment && '#' + fragment}[${text}]`
413
+ if (resourceId.family !== 'page' || !(resource = pagesInOutline.get(createResourceKey(resourceId)))) {
414
+ if ((resource = contentCatalog.getById(resourceId))?.pub) {
415
+ text ||= resource.asciidoc?.xreftext || target_
416
+ if (siteRoot || linkRefStyle === 'relative') {
417
+ return `${resolveLinkTarget(resource, siteRoot, pubRoot, linkRefStyle)}${fragment && '#' + fragment}[${text}]`
418
+ }
419
+ asciidoctorLogger.warn(
420
+ doc.createLogMessage(
421
+ `Cannot create external ${resourceId.family} reference in assembly because site URL is unknown: ${target_}`,
422
+ { source_location: { file: relative, lineno: idx + 1 } }
423
+ )
424
+ )
404
425
  }
405
- // TODO: handle unresolved page better
406
- return m
426
+ const linkAttrlist = text
427
+ ? (~text.indexOf(',') ? `"${text}"` : text) + ',role=unresolved'
428
+ : (~target.indexOf(':') ? `${target},` : '') + 'role=unresolved'
429
+ return `link:${target_}[${linkAttrlist}]`
407
430
  }
408
431
  if (fragment === resource.asciidoc.id) fragment = ''
409
432
  if (
@@ -427,7 +450,7 @@ function mergeAsciiDoc (
427
450
  if (~line.indexOf('link:{attachmentsdir}/')) {
428
451
  line = line.replace(/(?<![\\+])link:\{attachmentsdir\}\/([^\s[]+)\[(|.*?[^\\])\]/g, (m, relative, text) => {
429
452
  const attachment =
430
- siteRoot &&
453
+ (siteRoot || linkRefStyle === 'relative') &&
431
454
  contentCatalog.getById({
432
455
  component: componentVersion.name,
433
456
  version: componentVersion.version,
@@ -441,15 +464,25 @@ function mergeAsciiDoc (
441
464
  }
442
465
  if (~line.indexOf('image:') && !line.startsWith('image::')) {
443
466
  line = line.replace(/(?<![\\+])image:([^:\s[](?:[^[]*[^\s[])?)\[([^\]]*)\]/g, (m, target, attrlist) => {
444
- if (isResourceSpec(target)) {
445
- const image = contentCatalog.resolveResource(target, page.src, 'image', ['image'])
446
- // TODO: handle (or report) unresolved image better
447
- if (image?.out && (filetype !== 'html' || siteRoot)) {
467
+ let image
468
+ if (
469
+ isResourceSpec(target) &&
470
+ (image = contentCatalog.resolveResource(target, page.src, 'image', ['image']))?.out
471
+ ) {
472
+ if (filetype !== 'html') {
473
+ pagesInOutline.assembled.assets.add(image)
474
+ return `image:${resolveEmbedTarget(image, outDirname, embedRefStyle, true)}[${attrlist}]`
475
+ }
476
+ if (siteRoot || linkRefStyle === 'relative') {
448
477
  pagesInOutline.assembled.assets.add(image)
449
- return filetype === 'html'
450
- ? `image:${resolveLinkTarget(image, siteRoot, pubRoot, linkRefStyle)}[${attrlist}]`
451
- : `image:${resolveEmbedTarget(image, outDirname, embedRefStyle, true)}[${attrlist}]`
478
+ return `image:${resolveLinkTarget(image, siteRoot, pubRoot, linkRefStyle)}[${attrlist}]`
452
479
  }
480
+ asciidoctorLogger.warn(
481
+ doc.createLogMessage(
482
+ `Cannot create external image reference in assembly because site URL is unknown: ${target}`,
483
+ { source_location: { file: relative, lineno: idx + 1 } }
484
+ )
485
+ )
453
486
  }
454
487
  return m
455
488
  })
@@ -21,6 +21,7 @@ function produceAssemblyFiles (loadAsciiDoc, contentCatalog, assemblerConfig, re
21
21
  embedReferenceStyle: assemblyConfig.embedReferenceStyle,
22
22
  linkReferenceStyle: assemblyConfig.linkReferenceStyle,
23
23
  dropExplicitXrefText: assemblyConfig.dropExplicitXrefText,
24
+ logger: assemblyConfig.logger, // for tests
24
25
  })
25
26
  const assemblerAsciiDocAttributes = Object.assign({}, assemblerAsciiDocConfig.attributes)
26
27
  const { revdate, 'source-highlighter': sourceHighlighter } = assemblerAsciiDocAttributes
@@ -64,7 +65,7 @@ function produceAssemblyFiles (loadAsciiDoc, contentCatalog, assemblerConfig, re
64
65
  if (linkRefStyle === 'absolute' && siteRoot?.url == null) linkRefStyle = 'root-relative'
65
66
  if (linkRefStyle === 'root-relative' && siteRoot?.path == null) linkRefStyle = 'relative'
66
67
  assemblyModel.linkReferenceStyle = linkRefStyle
67
- } else if (assemblyModel.filetype !== 'pdf') {
68
+ } else if (!(assemblyModel.filetype === 'pdf' && assemblyModel.linkReferenceStyle === 'relative')) {
68
69
  assemblyModel.linkReferenceStyle = 'absolute'
69
70
  }
70
71
  const auxiliaryImages = new Set()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antora/assembler",
3
- "version": "1.0.0-beta.14",
3
+ "version": "1.0.0-beta.16",
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)",