@baiyibai-antora/extensions 1.14.0 → 1.15.0

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.
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * @baiyibai-antora/extensions - cite-it
4
4
  *
5
- * Resolves `citeit:[key]` citations against BibTeX/BibLaTeX `.bib` files and
5
+ * Resolves `cite:[key]` citations against BibTeX/BibLaTeX `.bib` files and
6
6
  * generates a categorized bibliography partial. Numbering is a PDF/Antora
7
7
  * Assembler-flattened-output concept only; ordinary, non-assembled HTML
8
8
  * citations render a templated author/year fragment instead, carrying no
@@ -17,7 +17,7 @@
17
17
  * autoterm's `mergeTerminology` already establishes.
18
18
  *
19
19
  * Each category generates its OWN partial (`categoryPartialName`,
20
- * `<output_partial>-<ref_section>.adoc`). A component author routes a
20
+ * `<output_partial>-<ref_category>.adoc`). A component author routes a
21
21
  * category to whichever page they choose, simply by including that
22
22
  * category's own partial there; different categories may genuinely live
23
23
  * on different pages, and citations correctly cross-link to whichever
@@ -41,7 +41,7 @@
41
41
  * generated-partial injection are real per-build cost, so a component
42
42
  * shouldn't pay it just because a sibling component happens to use
43
43
  * cite-it). In practice this produced a bad failure mode: a page citing
44
- * a key with `citeit:[key]` in a component-version that forgot the
44
+ * a key with `cite:[key]` in a component-version that forgot the
45
45
  * `ext.cite_it` block either silently rendered an unrelated component's
46
46
  * entry (if the key happened to collide) or a generic "unknown key"
47
47
  * message that read like a typo rather than "this component-version
@@ -58,10 +58,10 @@
58
58
  * for trademark-it/autoterm: declared once, inherited by every
59
59
  * component-version automatically. A component-version's own
60
60
  * `ext.cite_it.categories`, if present at all, is entirely optional and
61
- * purely additive to the scaffold, matched by `ref_section` (see
62
- * mergeCategoriesConfig): naming a section already in the scaffold
61
+ * purely additive to the scaffold, matched by `ref_category` (see
62
+ * mergeCategoriesConfig): naming a category already in the scaffold
63
63
  * extends it (its `ref_files`/`ref_force` append to the scaffold's),
64
- * and naming a new section adds a category local to that component
64
+ * and naming a new category adds one local to that component
65
65
  * alone. A component-version with
66
66
  * genuinely no categories anywhere, no playbook scaffold and no local
67
67
  * `ext.cite_it.categories`, is still skipped: there is nothing to scan
@@ -77,7 +77,7 @@
77
77
  * # Only 'ieee-bracket' is bundled and supported in this version.
78
78
  * style: 'ieee-bracket'
79
79
  * # Base filename for each category's own generated partial
80
- * # (e.g. section "standards" -> generated-bibliography-
80
+ * # (e.g. category "standards" -> generated-bibliography-
81
81
  * # standards.adoc), one per category, injected into each
82
82
  * # participating component-version.
83
83
  * output_partial: 'generated-bibliography.adoc'
@@ -88,12 +88,12 @@
88
88
  * write_to_disk: false
89
89
  * # The global scaffold: every participating component-version
90
90
  * # inherits these categories as-is unless it names the same
91
- * # ref_section itself, in which case its own entry extends this
91
+ * # ref_category itself, in which case its own entry extends this
92
92
  * # one rather than replacing it.
93
93
  * categories:
94
- * - ref_section: standards
94
+ * - ref_category: standards
95
95
  * ref_files: ['cite-it-data:ROOT:partial$standards.bib']
96
- * - ref_section: literature
96
+ * - ref_category: literature
97
97
  * ref_files: ['cite-it-data:ROOT:partial$literature-shared.bib']
98
98
  * ref_force: ['rfc2119']
99
99
  *
@@ -112,19 +112,19 @@
112
112
  * ext:
113
113
  * cite_it: {}
114
114
  *
115
- * A component needing a local-only addition to an existing section, or a
115
+ * A component needing a local-only addition to an existing category, or a
116
116
  * wholly local category the scaffold does not define, adds only that:
117
117
  *
118
118
  * ext:
119
119
  * cite_it:
120
120
  * categories:
121
- * # Extends the scaffold's own "literature" section (above) with one
121
+ * # Extends the scaffold's own "literature" category (above) with one
122
122
  * # more file, appended after the scaffold's own ref_files.
123
- * - ref_section: literature
123
+ * - ref_category: literature
124
124
  * ref_files: ['literature-local.bib']
125
- * # A section the scaffold does not define at all: local to this
125
+ * # A category the scaffold does not define at all: local to this
126
126
  * # component only.
127
- * - ref_section: internal-notes
127
+ * - ref_category: internal-notes
128
128
  * ref_files: ['internal-notes.bib']
129
129
  *
130
130
  * `.bib` files are resolved from the content catalog's `partial` family,
@@ -172,7 +172,7 @@
172
172
  * reading the `.bib` file directly. Bibtex itself carries no native
173
173
  * concept of an outdated reference; this is a cite-it-specific convention,
174
174
  * not a standard `.bib` field any external tool is expected to recognize.
175
- * Deliberately not raised again at each `citeit:[key]` use site in prose,
175
+ * Deliberately not raised again at each `cite:[key]` use site in prose,
176
176
  * one signal per generated partial is enough; managing `.bib` data itself,
177
177
  * including deciding when an entry is superseded, stays outside cite-it's
178
178
  * own scope (see the docs page's own "Scope" section).
@@ -281,12 +281,12 @@ function parseCategoriesConfig(v) {
281
281
  if (!raw || typeof raw !== 'object')
282
282
  continue;
283
283
  const r = raw;
284
- const section = typeof r['ref_section'] === 'string' ? r['ref_section']
285
- : typeof r['refSection'] === 'string' ? r['refSection'] : '';
286
- if (!section)
284
+ const category = typeof r['ref_category'] === 'string' ? r['ref_category']
285
+ : typeof r['refCategory'] === 'string' ? r['refCategory'] : '';
286
+ if (!category)
287
287
  continue;
288
288
  result.push({
289
- ref_section: section,
289
+ ref_category: category,
290
290
  ref_files: toStringArray(r['ref_files'] ?? r['refFiles']),
291
291
  ref_force: toStringArray(r['ref_force'] ?? r['refForce']),
292
292
  });
@@ -294,25 +294,25 @@ function parseCategoriesConfig(v) {
294
294
  return result;
295
295
  }
296
296
  // The playbook-level scaffold and a component's own categories[] merge by
297
- // ref_section, the same shared-then-local-override precedence autoterm's
297
+ // ref_category, the same shared-then-local-override precedence autoterm's
298
298
  // mergeTerminology and a single category's own ref_files list both already
299
- // establish: a section named at both levels extends (ref_files/ref_force
300
- // concatenate, playbook first) rather than replaces, and a section named
301
- // only at the component level is added as a wholly local category.
299
+ // establish: a category named at both levels extends (ref_files/ref_force
300
+ // concatenate, playbook first) rather than replaces, and a category named
301
+ // only at the component level is added as a wholly local one.
302
302
  function mergeCategoriesConfig(scaffold, local) {
303
- const bySection = new Map();
303
+ const byCategory = new Map();
304
304
  for (const cat of scaffold)
305
- bySection.set(cat.ref_section, { ...cat });
305
+ byCategory.set(cat.ref_category, { ...cat });
306
306
  for (const cat of local) {
307
- const existing = bySection.get(cat.ref_section);
308
- bySection.set(cat.ref_section, existing ? {
309
- ref_section: cat.ref_section,
307
+ const existing = byCategory.get(cat.ref_category);
308
+ byCategory.set(cat.ref_category, existing ? {
309
+ ref_category: cat.ref_category,
310
310
  ref_files: [...existing.ref_files, ...cat.ref_files],
311
311
  ref_force: [...existing.ref_force, ...cat.ref_force],
312
312
  } : cat);
313
313
  }
314
- return [...bySection.values()].map((cat) => ({
315
- ref_section: cat.ref_section,
314
+ return [...byCategory.values()].map((cat) => ({
315
+ ref_category: cat.ref_category,
316
316
  ref_files: cat.ref_files,
317
317
  ref_force: cat.ref_force,
318
318
  }));
@@ -371,11 +371,11 @@ function resolveBibFiles(refs, contentCatalog, component, version, module, logge
371
371
  return result;
372
372
  }
373
373
  // ---------------------------------------------------------------------------
374
- // Orphaned citeit:[key] usage: a component-version that is not scanned
374
+ // Orphaned cite:[key] usage: a component-version that is not scanned
375
375
  // ---------------------------------------------------------------------------
376
376
  /**
377
377
  * Checks a SKIPPED (non-participating) component-version's own pages for
378
- * `citeit:[key]` usage that will never resolve, and records any found into
378
+ * `cite:[key]` usage that will never resolve, and records any found into
379
379
  * `orphanedCiteKeys` (macro.ts) for the macro to detect at render time and
380
380
  * report clearly, instead of either silently borrowing an unrelated
381
381
  * component's data through the cross-component fallback (if the key
@@ -399,7 +399,7 @@ function resolveBibFiles(refs, contentCatalog, component, version, module, logge
399
399
  * cite-it.adoc's own siblings) from being misreported.
400
400
  *
401
401
  * A cheap substring pre-check gates the real, Asciidoctor-based scan
402
- * (`scanCiteKeys`): a component-version that never mentions `citeit:[` at
402
+ * (`scanCiteKeys`): a component-version that never mentions `cite:[` at
403
403
  * all pays nothing beyond a plain string search per page.
404
404
  */
405
405
  function checkOrphanedCiteUsage(compKey, reason, contentCatalog, component, version, logger) {
@@ -412,7 +412,7 @@ function checkOrphanedCiteUsage(compKey, reason, contentCatalog, component, vers
412
412
  const found = new Set();
413
413
  for (const f of pages) {
414
414
  const raw = f.contents.toString('utf8');
415
- if (!raw.includes('citeit:['))
415
+ if (!raw.includes('cite:['))
416
416
  continue;
417
417
  const headerAttrs = (0, asciidoc_conditionals_1.pageHeaderAttributes)(raw);
418
418
  const isDefined = (attr) => {
@@ -428,7 +428,7 @@ function checkOrphanedCiteUsage(compKey, reason, contentCatalog, component, vers
428
428
  if (found.size === 0)
429
429
  return;
430
430
  macro_1.orphanedCiteKeys.set(compKey, found);
431
- logger.warn(`cite-it: ${compKey} - ${reason}, but citeit:[${[...found].join('], citeit:[')}] is used directly on its own page(s); ` +
431
+ logger.warn(`cite-it: ${compKey} - ${reason}, but cite:[${[...found].join('], cite:[')}] is used directly on its own page(s); ` +
432
432
  'these citations will not resolve for this component-version, regardless of the playbook-level configuration');
433
433
  }
434
434
  // ---------------------------------------------------------------------------
@@ -444,6 +444,7 @@ function register(context) {
444
444
  output_partial: 'generated-bibliography.adoc',
445
445
  suppress_events: false,
446
446
  write_to_disk: false,
447
+ blanket_pubstate: false,
447
448
  categories: [],
448
449
  };
449
450
  const extByCompVer = new Map();
@@ -480,7 +481,7 @@ function register(context) {
480
481
  // inside ITS OWN navigationBuilt listener instead, as an earlier version
481
482
  // of this code did, whichever extension's navigationBuilt listener runs
482
483
  // first would win: a playbook that lists cite-it after
483
- // `@antora/pdf-extension` would silently get unrewritten citeit:[key]
484
+ // `@antora/pdf-extension` would silently get unrewritten cite:[key]
484
485
  // literal text in PDF output, no error, no warning, since
485
486
  // assembleContent's own loadAsciiDoc reference would already be frozen to
486
487
  // the original, unwrapped function before cite-it's replaceFunctions call
@@ -509,6 +510,7 @@ function register(context) {
509
510
  const [origFile, catalog, asciidocConfig] = args;
510
511
  let file = origFile;
511
512
  const isAssembled = !!(asciidocConfig?.attributes && 'loader-assembler' in asciidocConfig.attributes);
513
+ let restoreForeignPages;
512
514
  if (isAssembled && file?.contents && file.src?.component && file.src?.version) {
513
515
  const compKey = `${file.src.component}@${file.src.version}`;
514
516
  // @antora/assembler resolves the active profile as
@@ -532,11 +534,17 @@ function register(context) {
532
534
  file = Object.assign(Object.create(Object.getPrototypeOf(file)), file, { contents: Buffer.from(after, 'utf8') });
533
535
  }
534
536
  }
537
+ restoreForeignPages = rewriteForeignCitedPages(file.src, profileName);
535
538
  }
536
539
  // realLoadAsciiDoc is always assigned by this point: this closure is
537
540
  // only ever reachable after the synchronous assignment a few lines
538
541
  // above it in this same if-block has already run.
539
- return realLoadAsciiDoc(file, catalog, asciidocConfig ?? {});
542
+ try {
543
+ return realLoadAsciiDoc(file, catalog, asciidocConfig ?? {});
544
+ }
545
+ finally {
546
+ restoreForeignPages?.();
547
+ }
540
548
  };
541
549
  ctx.replaceFunctions({ loadAsciiDoc: loadAsciiDocWrapper });
542
550
  }
@@ -561,6 +569,7 @@ function register(context) {
561
569
  output_partial: String(pick(raw, ['output_partial', 'outputPartial'], cfg.output_partial)),
562
570
  suppress_events: toBool(pick(raw, ['suppress_events', 'suppressEvents'], cfg.suppress_events), cfg.suppress_events),
563
571
  write_to_disk: toBool(pick(raw, ['write_to_disk', 'writeToDisk'], cfg.write_to_disk), cfg.write_to_disk),
572
+ blanket_pubstate: toBool(pick(raw, ['blanket_pubstate', 'blanketPubstate'], cfg.blanket_pubstate), cfg.blanket_pubstate),
564
573
  categories: Array.isArray(raw['categories']) ? parseCategoriesConfig(raw['categories']) : cfg.categories,
565
574
  };
566
575
  quietMode = cfg.quiet;
@@ -595,7 +604,7 @@ function register(context) {
595
604
  }
596
605
  // The playbook-level categories scaffold needs no counterpart here
597
606
  // at all: a component's own categories[] is entirely optional,
598
- // additive to the scaffold by ref_section. See
607
+ // additive to the scaffold by ref_category. See
599
608
  // mergeCategoriesConfig for the actual merge.
600
609
  const categories = mergeCategoriesConfig(cfg.categories, parseCategoriesConfig(compExt['categories']));
601
610
  if (categories.length === 0) {
@@ -622,6 +631,7 @@ function register(context) {
622
631
  const compStyle = typeof compExt['style'] === 'string' ? compExt['style'] : cfg.style;
623
632
  const compOutPartial = typeof compExt['output_partial'] === 'string' ? compExt['output_partial'] : cfg.output_partial;
624
633
  const compWriteToDisk = toBool(compExt['write_to_disk'] ?? compExt['writeToDisk'], cfg.write_to_disk);
634
+ const compBlanketPubstate = toBool(compExt['blanket_pubstate'] ?? compExt['blanketPubstate'], cfg.blanket_pubstate);
625
635
  const module = files.find((f) => f.src.family === 'page')?.src.module ?? 'ROOT';
626
636
  // A page's own include::partial$<category-partial>[] is resolved
627
637
  // as part of the scan below (collectIncludeText walks every
@@ -640,8 +650,8 @@ function register(context) {
640
650
  // component-version turns out to have any real citation usage at
641
651
  // all, which the scan below has not yet determined at this point.
642
652
  const categoryPartials = categories.map((cat) => ({
643
- section: cat.ref_section,
644
- relative: categoryPartialName(compOutPartial, cat.ref_section),
653
+ category: cat.ref_category,
654
+ relative: categoryPartialName(compOutPartial, cat.ref_category),
645
655
  }));
646
656
  for (const cp of categoryPartials) {
647
657
  (0, index_2.injectPartial)(contentCatalog, files, component, version, module, cp.relative, '', false, logger);
@@ -654,7 +664,7 @@ function register(context) {
654
664
  // stale snapshot from before they existed.
655
665
  files = contentCatalog.getFiles().filter((f) => f.src.component === component && f.src.version === version);
656
666
  // ---------------------------------------------------------------
657
- // 1. Scan pages (+ resolved includes) for citeit:[key] usage,
667
+ // 1. Scan pages (+ resolved includes) for cite:[key] usage,
658
668
  // through a real Asciidoctor conversion (macro.ts's
659
669
  // scanCiteKeys), not a hand-rolled regex. Runs BEFORE ever
660
670
  // resolving or reading a single .bib file: the playbook-level
@@ -666,7 +676,7 @@ function register(context) {
666
676
  // unconditionally, warning "not found" for files it never had
667
677
  // any reason to carry. Scanning first and skipping entirely
668
678
  // when nothing was found (see below) means a component-version
669
- // with zero real citeit:[] usage anywhere never even looks for
679
+ // with zero real cite:[] usage anywhere never even looks for
670
680
  // its category files in the first place, rather than looking
671
681
  // and then discovering there was nothing to find. Placeholder
672
682
  // injection above still runs unconditionally either way: it
@@ -721,7 +731,7 @@ function register(context) {
721
731
  const anyForced = categories.some((cat) => cat.ref_force.length > 0);
722
732
  if (citedKeys.size === 0 && !anyForced) {
723
733
  const hasOwnExt = extByCompVer.has(compKey);
724
- const message = `cite-it: ${compKey} - skipped (no citeit:[key] usage anywhere and no ref_force entries in any category)`;
734
+ const message = `cite-it: ${compKey} - skipped (no cite:[key] usage anywhere and no ref_force entries in any category)`;
725
735
  if (hasOwnExt)
726
736
  logger.warn(message);
727
737
  else
@@ -749,14 +759,14 @@ function register(context) {
749
759
  }
750
760
  const keys = new Set();
751
761
  for (const [key, entry] of catEntries) {
752
- if (keyCategory.has(key) && keyCategory.get(key) !== cat.ref_section) {
753
- logger.warn(`cite-it: ${compKey} - citation key "${key}" appears in both category "${keyCategory.get(key)}" and "${cat.ref_section}"; the later category's membership wins`);
762
+ if (keyCategory.has(key) && keyCategory.get(key) !== cat.ref_category) {
763
+ logger.warn(`cite-it: ${compKey} - citation key "${key}" appears in both category "${keyCategory.get(key)}" and "${cat.ref_category}"; the later category's membership wins`);
754
764
  }
755
- keyCategory.set(key, cat.ref_section);
765
+ keyCategory.set(key, cat.ref_category);
756
766
  combinedEntries.set(key, entry);
757
767
  keys.add(key);
758
768
  }
759
- categoryKeys.set(cat.ref_section, keys);
769
+ categoryKeys.set(cat.ref_category, keys);
760
770
  }
761
771
  // A key claimed by more than one category was added to every
762
772
  // claiming category's own Set above, since each category's loop
@@ -786,15 +796,15 @@ function register(context) {
786
796
  for (const cat of categories) {
787
797
  for (const key of cat.ref_force) {
788
798
  if (!combinedEntries.has(key)) {
789
- logger.warn(`cite-it: ${compKey} - ref_force names unknown key "${key}" in category "${cat.ref_section}"; not found in any configured category's data`);
799
+ logger.warn(`cite-it: ${compKey} - ref_force names unknown key "${key}" in category "${cat.ref_category}"; not found in any configured category's data`);
790
800
  continue;
791
801
  }
792
- const previousSection = keyCategory.get(key);
793
- if (previousSection && previousSection !== cat.ref_section) {
794
- categoryKeys.get(previousSection)?.delete(key);
802
+ const previousCategory = keyCategory.get(key);
803
+ if (previousCategory && previousCategory !== cat.ref_category) {
804
+ categoryKeys.get(previousCategory)?.delete(key);
795
805
  }
796
- keyCategory.set(key, cat.ref_section);
797
- categoryKeys.get(cat.ref_section)?.add(key);
806
+ keyCategory.set(key, cat.ref_category);
807
+ categoryKeys.get(cat.ref_category)?.add(key);
798
808
  }
799
809
  }
800
810
  if (!cfg.suppress_events) {
@@ -802,11 +812,11 @@ function register(context) {
802
812
  }
803
813
  for (const key of citedKeys) {
804
814
  if (!combinedEntries.has(key)) {
805
- logger.warn(`cite-it: ${compKey} - citeit:[${key}] cites an unknown key; not found in any configured category`);
815
+ logger.warn(`cite-it: ${compKey} - cite:[${key}] cites an unknown key; not found in any configured category`);
806
816
  }
807
817
  }
808
818
  // ---------------------------------------------------------------
809
- // 3. Populate the shared cache the citeit:[key] macro reads at
819
+ // 3. Populate the shared cache the cite:[key] macro reads at
810
820
  // real conversion time (macro.ts). Formatted only for keys
811
821
  // actually used (cited, or ref_force), same set the
812
822
  // generated partial lists.
@@ -815,10 +825,10 @@ function register(context) {
815
825
  const usedKeysByCategory = new Map();
816
826
  const allUsedKeys = [];
817
827
  for (const cat of categories) {
818
- const keys = [...(categoryKeys.get(cat.ref_section) ?? new Set())]
828
+ const keys = [...(categoryKeys.get(cat.ref_category) ?? new Set())]
819
829
  .filter((k) => citedKeys.has(k) || refForceKeys.has(k))
820
830
  .sort((a, b) => a.localeCompare(b));
821
- usedKeysByCategory.set(cat.ref_section, keys);
831
+ usedKeysByCategory.set(cat.ref_category, keys);
822
832
  allUsedKeys.push(...keys);
823
833
  }
824
834
  // A key's entry carrying a supersededby field (registry.ts) warns
@@ -826,18 +836,18 @@ function register(context) {
826
836
  // partial actually lists (cited or ref_force'd), not every entry
827
837
  // the registry happens to hold: an unused entry going stale is not
828
838
  // this component-version's problem to flag. Deliberately not
829
- // raised again at each citeit:[key] use site (macro.ts): one clear
839
+ // raised again at each cite:[key] use site (macro.ts): one clear
830
840
  // signal per generated partial, not one per occurrence in prose.
831
- for (const [section, keys] of usedKeysByCategory) {
841
+ for (const [category, keys] of usedKeysByCategory) {
832
842
  for (const key of keys) {
833
843
  const supersededBy = combinedEntries.get(key)?.['supersededby'];
834
844
  if (typeof supersededBy === 'string' && supersededBy) {
835
- logger.warn(`cite-it: ${compKey} - citation "${key}" in category "${section}" carries supersededby "${supersededBy}"; a newer revision is available`);
845
+ logger.warn(`cite-it: ${compKey} - citation "${key}" in category "${category}" carries supersededby "${supersededBy}"; a newer revision is available`);
836
846
  }
837
847
  }
838
848
  }
839
- const formattedByKey = (0, csl_1.formatBibliographyEntries)(compStyle, combinedEntries, allUsedKeys);
840
- const cacheData = { entriesByKey: combinedEntries, formattedByKey };
849
+ const formattedByKey = (0, csl_1.formatBibliographyEntries)(compStyle, combinedEntries, allUsedKeys, compBlanketPubstate);
850
+ const cacheData = { entriesByKey: combinedEntries, formattedByKey, blanketPubstate: compBlanketPubstate };
841
851
  macro_1.citeCache.set(compKey, cacheData);
842
852
  assemblyScanContexts.set(compKey, {
843
853
  contentCatalog: contentCatalog,
@@ -855,8 +865,8 @@ function register(context) {
855
865
  // which category's partial.
856
866
  // ---------------------------------------------------------------
857
867
  for (const cp of categoryPartials) {
858
- const cat = categories.find((c) => c.ref_section === cp.section);
859
- const keys = usedKeysByCategory.get(cat.ref_section) ?? [];
868
+ const cat = categories.find((c) => c.ref_category === cp.category);
869
+ const keys = usedKeysByCategory.get(cat.ref_category) ?? [];
860
870
  const content = generateCategoryPartial(keys, formattedByKey);
861
871
  (0, index_2.injectPartial)(contentCatalog, files, component, version, module, cp.relative, content, compWriteToDisk, logger);
862
872
  }
@@ -874,7 +884,7 @@ function register(context) {
874
884
  // of this code did (the earlier version genuinely raced against
875
885
  // `@antora/assembler`'s own navigationBuilt listener and lost against a
876
886
  // real playbook where `@antora/pdf-extension` preceded cite-it in
877
- // `antora.extensions`, leaving every citeit:[key] unrewritten with no
887
+ // `antora.extensions`, leaving every cite:[key] unrewritten with no
878
888
  // error). Computing lazily on first actual use, inside this same wrapper
879
889
  // invocation, sidesteps that race entirely regardless of extension order.
880
890
  //
@@ -1053,7 +1063,7 @@ function register(context) {
1053
1063
  for (const cat of missingScopeCategories) {
1054
1064
  logger.warn(`cite-it: ${compKey} - could not find the page that includes category "${cat}"'s generated partial; its citation links will render as plain numbers, not clickable links`);
1055
1065
  }
1056
- // The generated bibliography partial's own citeit:[key] row labels
1066
+ // The generated bibliography partial's own cite:[key] row labels
1057
1067
  // need rewriting too, and specifically now, before any assembly-time
1058
1068
  // loadAsciiDoc call resolves an include:: of it: Antora's include
1059
1069
  // processor reads an included partial's content directly from the
@@ -1064,6 +1074,89 @@ function register(context) {
1064
1074
  // the wrapper, before that same invocation's real loadAsciiDoc call.
1065
1075
  (0, assembly_numbering_1.rewritePartialForAssembly)(scanCtx, numbers);
1066
1076
  }
1077
+ // Per participating component-version, the pages whose raw source
1078
+ // carries a cite:[ marker at all. Memoized on first use: the set is
1079
+ // fixed by contentClassified time, and rewriteForeignCitedPages below
1080
+ // runs once per assembled page load, site-wide.
1081
+ const citedPagesByComp = new Map();
1082
+ function rawSourceHolder(f) {
1083
+ const src = f.src;
1084
+ return src.contents !== undefined ? src : f;
1085
+ }
1086
+ // ---------------------------------------------------------------------
1087
+ // Cross-component includes in assembled output. The wrapper above
1088
+ // rewrites only the buffer @antora/assembler hands to loadAsciiDoc, the
1089
+ // page's own source. A page whose body is `include::other:ROOT:page$x.adoc[]`
1090
+ // carries no citation of its own, and Antora's include processor then
1091
+ // reads the included page (and, through it, the included bibliography
1092
+ // partial) straight from the catalog, never back through loadAsciiDoc.
1093
+ // Confirmed live: a component's own PDF rendered `[1]` correctly while a
1094
+ // sibling component wrapping the same page in an include:: shipped the
1095
+ // literal `cite:[key]` text, both inline and as the bibliography's own
1096
+ // row label, since Ruby asciidoctor-pdf has no citeit macro.
1097
+ //
1098
+ // For the duration of one real loadAsciiDoc call, every cited page of
1099
+ // every OTHER participating component-version is rewritten in the
1100
+ // catalog with its OWN component's numbers (the same numbering the
1101
+ // included partial, already rewritten by rewritePartialForAssembly, now
1102
+ // carries), then restored in the wrapper's finally block. Computing
1103
+ // every other component's numbers here, rather than only the loaded
1104
+ // page's own, also removes an ordering dependency: a wrapper component
1105
+ // assembled BEFORE the component it includes used to see that partial
1106
+ // still unrewritten, because rewritePartialForAssembly had not yet run
1107
+ // for it.
1108
+ //
1109
+ // A link target exists only when the included page itself hosts the
1110
+ // key's bibliography anchor: the anchor then lands inside the loaded
1111
+ // page's own fragment of the assembly, so the xref names the loaded
1112
+ // page, not the source page (an unqualified `xref:<page>.adoc` resolves
1113
+ // against the including document's component, where the source page's
1114
+ // name need not exist). Any other key is rewritten to a plain, unlinked
1115
+ // number, the same known-correct-but-unlinked fallback rewriteCiteMarkers
1116
+ // already applies to a key with no scope.
1117
+ // ---------------------------------------------------------------------
1118
+ function rewriteForeignCitedPages(loadedSrc, profileName) {
1119
+ const loadedKey = `${loadedSrc.component}@${loadedSrc.version}`;
1120
+ const loadedDocname = (loadedSrc.relative ?? '').replace(/\.[^./]+$/, '');
1121
+ const restores = [];
1122
+ for (const [compKey, scanCtx] of assemblyScanContexts) {
1123
+ if (compKey === loadedKey)
1124
+ continue;
1125
+ ensureAssemblyDataComputed(compKey, profileName);
1126
+ const numbers = citationNumbers.get(compKey);
1127
+ if (!numbers || numbers.size === 0)
1128
+ continue;
1129
+ const hostScopes = keyScopesByComp.get(compKey) ?? new Map();
1130
+ let pages = citedPagesByComp.get(compKey);
1131
+ if (!pages) {
1132
+ pages = scanCtx.contentCatalog.getFiles().filter((f) => f.src.component === scanCtx.component &&
1133
+ f.src.version === scanCtx.version &&
1134
+ f.src.family === 'page' &&
1135
+ Buffer.from(rawSourceHolder(f).contents).toString('utf8').includes('cite:['));
1136
+ citedPagesByComp.set(compKey, pages);
1137
+ }
1138
+ for (const page of pages) {
1139
+ const pageDocname = (page.src.relative ?? '').replace(/\.[^./]+$/, '');
1140
+ const scopes = new Map();
1141
+ for (const [key, host] of hostScopes) {
1142
+ if (host === pageDocname)
1143
+ scopes.set(key, loadedDocname);
1144
+ }
1145
+ const holder = rawSourceHolder(page);
1146
+ const original = holder.contents;
1147
+ const before = Buffer.from(original).toString('utf8');
1148
+ const after = (0, assembly_numbering_1.rewriteCiteMarkers)(before, numbers, true, scopes);
1149
+ if (after === before)
1150
+ continue;
1151
+ holder.contents = Buffer.from(after, 'utf8');
1152
+ restores.push(() => { holder.contents = original; });
1153
+ }
1154
+ }
1155
+ if (restores.length === 0)
1156
+ return undefined;
1157
+ return () => { for (const restore of restores)
1158
+ restore(); };
1159
+ }
1067
1160
  }
1068
1161
  /**
1069
1162
  * One category's own generated partial content: the bibliography list
@@ -1086,11 +1179,11 @@ function generateCategoryPartial(keys, formattedByKey) {
1086
1179
  const lines = ['[horizontal.cite-it-bibliography]'];
1087
1180
  for (const key of keys) {
1088
1181
  const text = formattedByKey.get(key) ?? `(no formatted text for "${key}")`;
1089
- // The [[cite-<key>]] anchor is what an inline citeit:[key] citation
1182
+ // The [[cite-<key>]] anchor is what an inline cite:[key] citation
1090
1183
  // links to for assembled/PDF output (rewriteCiteMarkers, asLink:
1091
1184
  // true), see assembly-numbering.ts. Harmless, invisible in ordinary
1092
1185
  // HTML rendering.
1093
- lines.push(`[[cite-${key}]]citeit:[${key}]:: ${text}`);
1186
+ lines.push(`[[cite-${key}]]cite:[${key}]:: ${text}`);
1094
1187
  }
1095
1188
  lines.push('');
1096
1189
  return lines.join('\n');