@antora/content-classifier 3.2.0-alpha.9 → 3.2.0-rc.1

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.
@@ -4,6 +4,7 @@ const ContentCatalog = require('./content-catalog')
4
4
  const collateAsciiDocAttributes = require('@antora/asciidoc-loader/config/collate-asciidoc-attributes')
5
5
  const logger = require('./logger')
6
6
  const summarizeFileLocation = require('./util/summarize-file-location')
7
+ const families = { attachments: true, examples: true, images: true, pages: true, partials: true }
7
8
 
8
9
  /**
9
10
  * Organizes the raw aggregate of virtual files into a {ContentCatalog}.
@@ -45,9 +46,21 @@ function addFilesAndRegisterStartPages (contentCatalog, siteStartPage) {
45
46
  for (const componentVersion of componentVersions) {
46
47
  const { name: component, version, files = [], nav, startPage } = componentVersion
47
48
  const navResolved = nav && (nav.resolved = new Set())
48
- for (let file, i = 0, len = files.length; i < len; i++) {
49
- allocateSrc((file = files[i]), component, version, nav) && contentCatalog.addFile(file, componentVersion)
49
+ const rootFiles = []
50
+ for (let file, i = 0; (file = files[i]); i++) {
50
51
  files[i] = undefined // free memory
52
+ const outcome = allocateSrc(file, component, version, componentVersion, nav)
53
+ if (outcome) {
54
+ contentCatalog.addFile(file)
55
+ } else if (outcome == null) {
56
+ rootFiles.push(file)
57
+ }
58
+ }
59
+ if (rootFiles.length) {
60
+ for (let file, i = 0; (file = rootFiles[i]); i++) {
61
+ if (file.src.origin.hasModulesDir) continue
62
+ allocateSrc(file, component, version, componentVersion, null, true) && contentCatalog.addFile(file)
63
+ }
51
64
  }
52
65
  if (navResolved && nav.length > navResolved.size && new Set(nav).size > navResolved.size) {
53
66
  const loc = summarizeFileLocation({ path: 'antora.yml', src: { origin: nav.origin } })
@@ -63,21 +76,24 @@ function addFilesAndRegisterStartPages (contentCatalog, siteStartPage) {
63
76
  return contentCatalog
64
77
  }
65
78
 
66
- function allocateSrc (file, component, version, nav) {
67
- const { extname, family } = file.src
79
+ function allocateSrc (file, component, version, componentVersion, nav, implicitRoot) {
80
+ const { extname, family, origin } = file.src
68
81
  if (family && family !== 'nav') {
69
- Object.assign(file.src, { component, version })
82
+ Object.assign(file.src, { component, version, componentVersion })
83
+ if (!('private' in file) && ~('/' + file.src.relative).indexOf('/_')) file.private = true
70
84
  file.src.moduleRootPath ??= calculateRootPath(file.src.relative.split('/').length)
71
85
  return true
72
86
  }
73
87
  const filepath = file.path
74
- const pathSegments = filepath.split('/')
88
+ const pathSegments = implicitRoot ? ['modules', 'ROOT'].concat(filepath.split('/')) : filepath.split('/')
89
+ const inModules = pathSegments[0] === 'modules'
90
+ if (!implicitRoot && origin) origin.hasModulesDir ||= inModules
75
91
  let navInfo
76
92
  if (nav && (navInfo = getNavInfo(filepath, nav))) {
77
- if (extname !== '.adoc') return // ignore file
93
+ if (extname !== '.adoc') return false // ignore file
78
94
  file.nav = navInfo
79
95
  file.src.family = 'nav'
80
- if (pathSegments[0] === 'modules' && pathSegments.length > 2) {
96
+ if (inModules && pathSegments.length > 2) {
81
97
  file.src.module = pathSegments[1]
82
98
  // relative to modules/<module>
83
99
  file.src.relative = pathSegments.slice(2).join('/')
@@ -86,7 +102,7 @@ function allocateSrc (file, component, version, nav) {
86
102
  // relative to content source root
87
103
  file.src.relative = filepath
88
104
  }
89
- } else if (pathSegments[0] === 'modules') {
105
+ } else if (inModules) {
90
106
  let familyFolder = pathSegments[2]
91
107
  switch (familyFolder) {
92
108
  case 'pages':
@@ -100,45 +116,47 @@ function allocateSrc (file, component, version, nav) {
100
116
  // relative to modules/<module>/pages
101
117
  file.src.relative = pathSegments.slice(3).join('/')
102
118
  } else {
103
- return // ignore file
119
+ return false // ignore file
104
120
  }
105
121
  break
106
122
  case 'assets':
107
123
  switch ((familyFolder = pathSegments[3])) {
108
124
  case 'attachments':
109
125
  case 'images':
110
- if (!extname) return // ignore file
111
- file.src.family = familyFolder.substr(0, familyFolder.length - 1)
126
+ if (!extname && familyFolder === 'images') return false // ignore file
127
+ file.src.family = familyFolder.substring(0, familyFolder.length - 1)
112
128
  // relative to modules/<module>/assets/<family>s
113
129
  file.src.relative = pathSegments.slice(4).join('/')
114
130
  break
115
131
  default:
116
- return // ignore file
132
+ return false // ignore file
117
133
  }
118
134
  break
119
- case 'attachments':
120
135
  case 'images':
121
- if (!extname) return
122
- file.src.family = familyFolder.substr(0, familyFolder.length - 1)
136
+ if (!extname) return false
137
+ file.src.family = familyFolder.substring(0, familyFolder.length - 1)
123
138
  // relative to modules/<module>/<family>s
124
139
  file.src.relative = pathSegments.slice(3).join('/')
125
140
  break
141
+ case 'attachments':
126
142
  case 'examples':
127
143
  case 'partials':
128
- file.src.family = familyFolder.substr(0, familyFolder.length - 1)
144
+ file.src.family = familyFolder.substring(0, familyFolder.length - 1)
129
145
  // relative to modules/<module>/<family>s
130
146
  file.src.relative = pathSegments.slice(3).join('/')
131
147
  break
132
148
  default:
133
- return // ignore file
149
+ return false // ignore file
134
150
  }
135
151
  file.src.module = pathSegments[1]
136
152
  file.src.moduleRootPath = calculateRootPath(pathSegments.length - 3)
153
+ if (!('private' in file) && ~('/' + file.src.relative).indexOf('/_')) file.private = true
154
+ } else if (origin && pathSegments[0] in families) {
155
+ return // defer file
137
156
  } else {
138
- return // ignore file
157
+ return false // ignore file
139
158
  }
140
- file.src.component = component
141
- file.src.version = version
159
+ Object.assign(file.src, { component, version, componentVersion })
142
160
  return true
143
161
  }
144
162
 
@@ -152,7 +170,7 @@ function allocateSrc (file, component, version, nav) {
152
170
  * index, if this file is a navigation file, or undefined if it's not.
153
171
  */
154
172
  function getNavInfo (filepath, nav) {
155
- const index = nav.findIndex((candidate) => candidate === filepath)
173
+ const index = nav.indexOf(filepath)
156
174
  if (~index) return nav.resolved.add(filepath) && { index }
157
175
  }
158
176
 
@@ -20,6 +20,7 @@ class ContentCatalog {
20
20
  constructor (playbook = {}) {
21
21
  this[$components] = new Map()
22
22
  this[$files] = new Map()
23
+ this.publishableFamilies = new Set(['page', 'image', 'attachment'])
23
24
  const urls = playbook.urls || {}
24
25
  this.htmlUrlExtensionStyle = urls.htmlExtensionStyle || 'default'
25
26
  this.urlRedirectFacility = urls.redirectFacility || 'static'
@@ -142,11 +143,11 @@ class ContentCatalog {
142
143
  return componentVersion
143
144
  }
144
145
 
145
- addFile (file, componentVersion) {
146
+ addFile (file) {
146
147
  const src = file.src
147
- let { component, version, family } = src
148
- let filesForFamily = this[$files].get(family)
149
- if (!filesForFamily) this[$files].set(family, (filesForFamily = new Map()))
148
+ const family = src.family
149
+ let filesForFamily
150
+ if ((filesForFamily = this[$files].get(family)) == null) this[$files].set(family, (filesForFamily = new Map()))
150
151
  const key = generateKey(src)
151
152
  if (filesForFamily.has(key)) {
152
153
  if (family === 'alias') {
@@ -156,58 +157,73 @@ class ContentCatalog {
156
157
  .map((it, idx) => `${idx + 1}: ${summarizeFileLocation(it)}`)
157
158
  .join(LOG_WRAP)
158
159
  if (family === 'nav') {
159
- throw new Error(`Duplicate nav file: ${file.path} in ${version}@${component}${LOG_WRAP}${details}`)
160
+ throw new Error(`Duplicate nav file: ${file.path} in ${src.version}@${src.component}${LOG_WRAP}${details}`)
160
161
  }
161
162
  throw new Error(`Duplicate ${family}: ${generateResourceSpec(src)}${LOG_WRAP}${details}`)
162
163
  }
164
+ if (!(file.created && File.isVinyl(file))) file = this.createFile(file)
165
+ filesForFamily.set(key, file)
166
+ return file
167
+ }
168
+
169
+ createFile (file) {
170
+ const src = file.src
171
+ let { componentVersion, family } = src
172
+ if (componentVersion) delete src.componentVersion
163
173
  // NOTE: assume that if the file is not a vinyl object, the src likely needs to be prepared
164
174
  // a vinyl object is one indication the file was created and prepared by the content aggregator
165
- // an alternate approach would be to call prepareSrc if the path property is not set
175
+ // an alternate approach would be to call inflateSrc if the path property is not set
166
176
  if (!File.isVinyl(file)) {
167
- prepareSrc(src)
177
+ inflateSrc(src)
168
178
  file = new File(file)
169
179
  }
180
+ Object.defineProperty(file, 'created', { configurable: true, writable: true, value: true })
170
181
  if (family === 'alias') {
171
182
  file.mediaType = 'text/html'
172
- // NOTE: an alias masquerades as the target file
173
- family = file.rel.src.family
174
183
  // NOTE: short circuit in case of splat alias (alias -> alias)
175
- if (family === 'alias' && file.pub?.splat) return filesForFamily.set(key, file) && file
184
+ if (file.rel.src.family === 'alias' && file.pub?.splat) return file
185
+ // NOTE the effective family of an alias is a page, which redirects to the target file
186
+ family = 'page'
176
187
  src.mediaType = 'text/asciidoc'
177
188
  } else if (!(file.mediaType = src.mediaType) && !('mediaType' in src)) {
178
189
  // QUESTION: should we preserve the mediaType property on file if already defined?
179
- file.mediaType = src.mediaType = resolveMimeType(src.extname) || (family === 'page' ? 'text/asciidoc' : undefined)
190
+ file.mediaType = src.mediaType = src.extname
191
+ ? resolveMimeType(src.extname) || (family === 'page' ? 'text/asciidoc' : undefined)
192
+ : 'text/plain'
180
193
  }
181
- let publishable
182
- let activeVersionSegment
194
+ let activeVersionSegment = false
195
+ let publishable, referenceable
183
196
  if (file.out) {
184
197
  publishable = true
185
198
  } else if ('out' in file) {
186
199
  delete file.out
187
- } else if (
188
- !file.private &&
189
- (family === 'page' || family === 'image' || family === 'attachment') &&
190
- (file.private === false || ('/' + src.relative).indexOf('/_') < 0)
191
- ) {
200
+ } else if (!file.private && this.publishableFamilies.has(family)) {
192
201
  publishable = true
193
- if (componentVersion == null) componentVersion = this.getComponentVersion(component, version) || { version }
202
+ componentVersion ??= this.getComponentVersion(src.component, src.version) || { version: src.version }
194
203
  activeVersionSegment =
195
204
  'activeVersionSegment' in componentVersion
196
205
  ? componentVersion.activeVersionSegment
197
206
  : computeVersionSegment.call(this, componentVersion)
198
- file.out = computeOut(src, family, activeVersionSegment, this.htmlUrlExtensionStyle)
207
+ file.out = computeOut.call(this, src, family, activeVersionSegment)
208
+ }
209
+ if (!file.pub) {
210
+ if ('pub' in file) {
211
+ delete file.pub
212
+ } else if (publishable || family === 'nav') {
213
+ referenceable = true
214
+ }
199
215
  }
200
- if (!file.pub && (publishable || family === 'nav')) {
201
- if (activeVersionSegment == null) {
202
- if (componentVersion == null) componentVersion = this.getComponentVersion(component, version) || { version }
216
+ if (referenceable) {
217
+ if (activeVersionSegment === false) {
218
+ componentVersion ??= this.getComponentVersion(src.component, src.version) || { version: src.version }
203
219
  activeVersionSegment =
204
220
  'activeVersionSegment' in componentVersion
205
221
  ? componentVersion.activeVersionSegment
206
222
  : computeVersionSegment.call(this, componentVersion)
207
223
  }
208
- file.pub = computePub(src, file.out, family, activeVersionSegment, this.htmlUrlExtensionStyle)
224
+ file.pub = computePub.call(this, src, file.out, family, activeVersionSegment)
209
225
  }
210
- return filesForFamily.set(key, file) && file
226
+ return file
211
227
  }
212
228
 
213
229
  removeFile (file) {
@@ -263,21 +279,27 @@ class ContentCatalog {
263
279
  return this.getComponents().sort((a, b) => a[property].localeCompare(b[property]))
264
280
  }
265
281
 
266
- getFiles () {
267
- const accum = []
268
- for (const filesForFamily of this[$files].values()) {
269
- for (const file of filesForFamily.values()) accum.push(file)
282
+ getFiles (filter) {
283
+ const files = []
284
+ if (filter) {
285
+ for (const filesForFamily of this[$files].values()) {
286
+ for (const candidate of filesForFamily.values()) filter(candidate) && files.push(candidate)
287
+ }
288
+ } else {
289
+ for (const filesForFamily of this[$files].values()) {
290
+ for (const file of filesForFamily.values()) files.push(file)
291
+ }
270
292
  }
271
- return accum
293
+ return files
272
294
  }
273
295
 
274
296
  getPages (filter) {
275
297
  const candidates = this[$files].get('page')
276
298
  if (!candidates) return []
277
299
  if (filter) {
278
- const accum = []
279
- for (const candidate of candidates.values()) filter(candidate) && accum.push(candidate)
280
- return accum
300
+ const pages = []
301
+ for (const candidate of candidates.values()) filter(candidate) && pages.push(candidate)
302
+ return pages
281
303
  }
282
304
  return [...candidates.values()]
283
305
  }
@@ -295,17 +317,14 @@ class ContentCatalog {
295
317
  if ((file = this.getById(Object.assign({}, ROOT_INDEX_ALIAS_ID, { version })))) return file.rel
296
318
  }
297
319
 
298
- registerComponentVersionStartPage (name, componentVersion, startPageSpec = undefined) {
299
- const component = name
300
- let version = componentVersion.version
301
- if (version == null) {
320
+ registerComponentVersionStartPage (component, componentVersion, startPageSpec = undefined) {
321
+ if (componentVersion.constructor === String) {
302
322
  // QUESTION: should we warn or throw error if component version cannot be found?
303
323
  if (!(componentVersion = this.getComponentVersion(component, componentVersion))) return
304
- version = componentVersion.version
305
324
  }
325
+ const version = componentVersion.version
306
326
  const activeVersionSegment = computeVersionSegment.call(this, componentVersion)
307
- let startPage
308
- let startPageSrc
327
+ let startPage, startPageSrc
309
328
  const indexPageId = Object.assign({}, ROOT_INDEX_PAGE_ID, { component, version })
310
329
  if (startPageSpec) {
311
330
  if (
@@ -314,11 +333,11 @@ class ContentCatalog {
314
333
  startPageSrc.version === version
315
334
  ) {
316
335
  if (!this.getById(indexPageId)) {
317
- const indexAliasId = Object.assign({}, ROOT_INDEX_ALIAS_ID, { component, version })
336
+ const indexAliasId = Object.assign({}, ROOT_INDEX_ALIAS_ID, { component, version, componentVersion })
318
337
  const indexAlias = this.getById(indexAliasId)
319
338
  indexAlias
320
339
  ? indexAlias.synthetic && Object.assign(indexAlias, { rel: startPage })
321
- : this.addFile({ src: indexAliasId, rel: startPage, synthetic: true }, componentVersion)
340
+ : this.addFile({ src: indexAliasId, rel: startPage, synthetic: true })
322
341
  }
323
342
  } else {
324
343
  // TODO pass componentVersion as logObject
@@ -337,20 +356,21 @@ class ContentCatalog {
337
356
  if (startPage) {
338
357
  componentVersion.url = startPage.pub.url
339
358
  } else if (!componentVersion.url) {
359
+ startPageSrc = inflateSrc(Object.assign({}, indexPageId, { family: 'page' }))
340
360
  // QUESTION: should we warn if the default start page cannot be found?
341
- componentVersion.url = computePub(
342
- (startPageSrc = prepareSrc(Object.assign({}, indexPageId, { family: 'page' }))),
343
- computeOut(startPageSrc, startPageSrc.family, activeVersionSegment, this.htmlUrlExtensionStyle),
361
+ componentVersion.url = computePub.call(
362
+ this,
363
+ startPageSrc,
364
+ computeOut.call(this, startPageSrc, startPageSrc.family, activeVersionSegment),
344
365
  startPageSrc.family,
345
- activeVersionSegment,
346
- this.htmlUrlExtensionStyle
366
+ activeVersionSegment
347
367
  ).url
348
368
  }
349
369
  Object.defineProperties(componentVersion, {
350
370
  activeVersionSegment:
351
371
  activeVersionSegment === version
352
- ? { configurable: true, enumerable: false, get: getVersion }
353
- : { configurable: true, enumerable: false, value: activeVersionSegment },
372
+ ? { configurable: true, get: getVersion }
373
+ : { configurable: true, value: activeVersionSegment },
354
374
  files: {
355
375
  configurable: true,
356
376
  enumerable: false,
@@ -375,7 +395,7 @@ class ContentCatalog {
375
395
  const rootIndexAlias = this.getById(ROOT_INDEX_ALIAS_ID)
376
396
  if (rootIndexAlias) return rootIndexAlias.synthetic ? Object.assign(rootIndexAlias, { rel }) : undefined
377
397
  const src = Object.assign({}, ROOT_INDEX_ALIAS_ID)
378
- return this.addFile({ src, rel, synthetic: true }, { version: src.version })
398
+ return this.addFile({ src, rel, synthetic: true })
379
399
  }
380
400
  if (rel === false) {
381
401
  logger.warn('Start page specified for site has invalid syntax: %s', startPageSpec)
@@ -394,14 +414,9 @@ class ContentCatalog {
394
414
  // QUESTION should we throw an error if alias is invalid?
395
415
  if (!src || (inferredSpec && src.relative === '.adoc')) return
396
416
  const component = this.getComponent(src.component)
397
- let componentVersion
398
417
  if (component) {
399
418
  // NOTE version is not set when alias specifies a component, but not a version
400
- if (src.version == null) {
401
- src.version = (componentVersion = component.latest).version
402
- } else {
403
- componentVersion = this.getComponentVersion(component, src.version)
404
- }
419
+ src.version ??= (src.componentVersion = component.latest).version
405
420
  const existingPage = this.getById(src)
406
421
  if (existingPage) {
407
422
  throw new Error(
@@ -426,7 +441,7 @@ class ContentCatalog {
426
441
  )
427
442
  }
428
443
  // NOTE the redirect producer will populate contents when the redirect facility is 'static'
429
- const alias = this.addFile({ src, rel: target }, componentVersion)
444
+ const alias = this.addFile({ src, rel: target })
430
445
  // NOTE record the first alias this target claims as the preferred one
431
446
  if (!target.rel) target.rel = alias
432
447
  return alias
@@ -445,12 +460,18 @@ class ContentCatalog {
445
460
  const basePub = { splat: true }
446
461
  const { component: fromComponent = to.component, versionSegment: fromVersionSegment } = from
447
462
  const fromSrc = Object.assign({ component: fromComponent, version: fromVersionSegment }, baseSrc)
448
- const fromPub = Object.assign(computePub(fromSrc, computeOut(fromSrc, family, fromVersionSegment), family), basePub)
463
+ const fromPub = Object.assign(
464
+ computePub.call(this, fromSrc, computeOut.call(this, fromSrc, family, fromVersionSegment), family),
465
+ basePub
466
+ )
449
467
  const { component: toComponent, version: toVersion } = to
450
468
  const toVersionSegment =
451
469
  to.versionSegment ?? this.getComponentVersion(toComponent, toVersion)?.activeVersionSegment ?? toVersion
452
470
  const toSrc = Object.assign({ component: toComponent, version: toVersion ?? toVersionSegment }, baseSrc)
453
- const toPub = Object.assign(computePub(toSrc, computeOut(toSrc, family, toVersionSegment), family), basePub)
471
+ const toPub = Object.assign(
472
+ computePub.call(this, toSrc, computeOut.call(this, toSrc, family, toVersionSegment), family),
473
+ basePub
474
+ )
454
475
  return this.addFile({ pub: fromPub, src: fromSrc, rel: { pub: toPub, src: toSrc } })
455
476
  }
456
477
 
@@ -536,7 +557,7 @@ function generateResourceSpec ({ component, version, module: module_, family, re
536
557
  )
537
558
  }
538
559
 
539
- function prepareSrc (src) {
560
+ function inflateSrc (src) {
540
561
  let { basename, extname, stem } = src
541
562
  if (basename == null) {
542
563
  basename = src.basename = path.basename(src.relative)
@@ -544,22 +565,22 @@ function prepareSrc (src) {
544
565
  if (stem == null) {
545
566
  if (extname == null) {
546
567
  if (~(extname = basename.lastIndexOf('.'))) {
547
- src.stem = basename.substr(0, extname)
548
- src.extname = basename.substr(extname)
568
+ src.stem = basename.substring(0, extname)
569
+ src.extname = basename.substring(extname)
549
570
  } else {
550
571
  src.stem = basename
551
572
  src.extname = ''
552
573
  }
553
574
  } else {
554
- src.stem = basename.substr(0, basename.length - extname.length)
575
+ src.stem = basename.substring(0, basename.length - extname.length)
555
576
  }
556
577
  } else if (extname == null) {
557
- src.extname = basename.substr(stem.length)
578
+ src.extname = basename.substring(stem.length)
558
579
  }
559
580
  return src
560
581
  }
561
582
 
562
- function computeOut (src, family, versionSegment, htmlUrlExtensionStyle) {
583
+ function computeOut (src, family, versionSegment) {
563
584
  let { component, module: module_, basename, extname, relative, stem } = src
564
585
  if (component === 'ROOT') component = ''
565
586
  if (module_ === 'ROOT') module_ = ''
@@ -567,16 +588,14 @@ function computeOut (src, family, versionSegment, htmlUrlExtensionStyle) {
567
588
  let familyPathSegment = ''
568
589
 
569
590
  if (family === 'page') {
570
- if (stem !== 'index' && htmlUrlExtensionStyle === 'indexify') {
591
+ if (stem !== 'index' && this.htmlUrlExtensionStyle === 'indexify') {
571
592
  basename = 'index.html'
572
593
  indexifyPathSegment = stem
573
594
  } else if (extname === '.adoc') {
574
595
  basename = stem + '.html'
575
596
  }
576
- } else if (family === 'image') {
577
- familyPathSegment = '_images'
578
- } else if (family === 'attachment') {
579
- familyPathSegment = '_attachments'
597
+ } else if (this.publishableFamilies.has(family)) {
598
+ familyPathSegment = '_' + family + 's'
580
599
  }
581
600
 
582
601
  const modulePath = path.join(component, versionSegment, module_)
@@ -588,7 +607,7 @@ function computeOut (src, family, versionSegment, htmlUrlExtensionStyle) {
588
607
  return { dirname, basename, path: path_, moduleRootPath, rootPath }
589
608
  }
590
609
 
591
- function computePub (src, out, family, versionSegment, htmlUrlExtensionStyle) {
610
+ function computePub (src, out, family, versionSegment) {
592
611
  const pub = {}
593
612
  let url
594
613
  if (family === 'nav') {
@@ -604,12 +623,12 @@ function computePub (src, out, family, versionSegment, htmlUrlExtensionStyle) {
604
623
  } else if (family === 'page') {
605
624
  const urlSegments = out.path.split('/')
606
625
  const lastUrlSegmentIdx = urlSegments.length - 1
607
- if (htmlUrlExtensionStyle === 'drop') {
626
+ if (this.htmlUrlExtensionStyle === 'drop') {
608
627
  // drop just the .html extension or, if the filename is index.html, the whole segment
609
628
  const lastUrlSegment = urlSegments[lastUrlSegmentIdx]
610
629
  urlSegments[lastUrlSegmentIdx] =
611
- lastUrlSegment === 'index.html' ? '' : lastUrlSegment.substr(0, lastUrlSegment.length - 5)
612
- } else if (htmlUrlExtensionStyle === 'indexify') {
630
+ lastUrlSegment === 'index.html' ? '' : lastUrlSegment.substring(0, lastUrlSegment.length - 5)
631
+ } else if (this.htmlUrlExtensionStyle === 'indexify') {
613
632
  urlSegments[lastUrlSegmentIdx] = ''
614
633
  }
615
634
  url = '/' + urlSegments.join('/')
@@ -59,7 +59,7 @@ function parseResourceId (spec, ctx = {}, defaultFamily = 'page', permittedFamil
59
59
  const relativeSegments = relative.split('/')
60
60
  let from
61
61
  if (relativeSegments[0] === '.' && (from = ctx.relative)) {
62
- relativeSegments[0] = from.substr(0, (from.lastIndexOf('/') + 1 || 1) - 1)
62
+ relativeSegments[0] = from.substring(0, (from.lastIndexOf('/') + 1 || 1) - 1)
63
63
  }
64
64
  relative = relativeSegments
65
65
  .reduce((accum, segment) => {
@@ -26,7 +26,7 @@ const parseResourceId = require('./parse-resource-id')
26
26
  */
27
27
  function resolveResource (spec, catalog, ctx = {}, defaultFamily = undefined, permittedFamilies = undefined) {
28
28
  const id = parseResourceId(spec, ctx, defaultFamily, permittedFamilies)
29
- if (!id || !id.family) return false
29
+ if (!id?.family) return false
30
30
  if (id.version == null) {
31
31
  const component = catalog.getComponent(id.component)
32
32
  if (!component) return
@@ -33,7 +33,7 @@ function versionCompareDesc (a, b) {
33
33
  function resolveSemver (str) {
34
34
  const chr0 = str.charAt()
35
35
  if (chr0 === 'v') {
36
- if (isDigit(str.charAt(1)) && (str = str.substr(1)) && (~str.indexOf('.') || isDigit(str.charAt()))) {
36
+ if (isDigit(str.charAt(1)) && (str = str.substring(1)) && (~str.indexOf('.') || isDigit(str.charAt()))) {
37
37
  return str
38
38
  }
39
39
  } else if (isDigit(chr0) && (~str.indexOf('.') || isInteger(Number(str)))) {
@@ -51,12 +51,12 @@ function semverCompare (a, b) {
51
51
  const preOffsetA = a.indexOf('-')
52
52
  const preOffsetB = b.indexOf('-')
53
53
  if (~preOffsetA) {
54
- preA = a.substr(preOffsetA + 1)
55
- a = a.substr(0, preOffsetA)
54
+ preA = a.substring(preOffsetA + 1)
55
+ a = a.substring(0, preOffsetA)
56
56
  }
57
57
  if (~preOffsetB) {
58
- preB = b.substr(preOffsetB + 1)
59
- b = b.substr(0, preOffsetB)
58
+ preB = b.substring(preOffsetB + 1)
59
+ b = b.substring(0, preOffsetB)
60
60
  }
61
61
  const numsA = a.split('.')
62
62
  const numsB = b.split('.')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antora/content-classifier",
3
- "version": "3.2.0-alpha.9",
3
+ "version": "3.2.0-rc.1",
4
4
  "description": "Organizes aggregated content into a virtual file catalog for use in an Antora documentation pipeline.",
5
5
  "license": "MPL-2.0",
6
6
  "author": "OpenDevise Inc. (https://opendevise.com)",
@@ -31,13 +31,13 @@
31
31
  "#constants": "./lib/constants.js"
32
32
  },
33
33
  "dependencies": {
34
- "@antora/asciidoc-loader": "3.2.0-alpha.9",
35
- "@antora/logger": "3.2.0-alpha.9",
36
- "mime-types": "~2.1",
34
+ "@antora/asciidoc-loader": "3.2.0-rc.1",
35
+ "@antora/logger": "3.2.0-rc.1",
36
+ "mime-types": "~3.0",
37
37
  "vinyl": "~3.0"
38
38
  },
39
39
  "engines": {
40
- "node": ">=18.0.0"
40
+ "node": ">=20.0.0"
41
41
  },
42
42
  "files": [
43
43
  "lib/"
@@ -51,7 +51,7 @@
51
51
  "web publishing"
52
52
  ],
53
53
  "scripts": {
54
- "test": "_mocha",
54
+ "test": "node --test",
55
55
  "prepublishOnly": "npx -y downdoc@latest --prepublish",
56
56
  "postpublish": "npx -y downdoc@latest --postpublish"
57
57
  }