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

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, create = true) {
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))) 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,64 +157,77 @@ 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
  }
163
- // NOTE: assume that if the file is not a vinyl object, the src likely needs to be prepared
164
+ filesForFamily.set(key, create ? (file = this.createFile(file)) : file)
165
+ return file
166
+ }
167
+
168
+ createFile (file) {
169
+ const src = file.src
170
+ let { componentVersion, family } = src
171
+ if (componentVersion) delete src.componentVersion
172
+ // NOTE: assume that if the file is not a vinyl object, the src likely needs to be inflated
164
173
  // 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
166
174
  if (!File.isVinyl(file)) {
167
- prepareSrc(src)
175
+ if (typeof file.contents === 'string') file.contents = Buffer.from(file.contents)
176
+ inflateSrc(src)
168
177
  file = new File(file)
169
178
  }
179
+ Object.defineProperty(file, 'created', { configurable: true, writable: true, value: true })
170
180
  if (family === 'alias') {
171
181
  file.mediaType = 'text/html'
172
- // NOTE: an alias masquerades as the target file
173
- family = file.rel.src.family
174
182
  // NOTE: short circuit in case of splat alias (alias -> alias)
175
- if (family === 'alias' && file.pub?.splat) return filesForFamily.set(key, file) && file
183
+ if (file.rel.src.family === 'alias' && file.pub?.splat) return file
184
+ // NOTE the effective family of an alias is a page, which redirects to the target file
185
+ family = 'page'
176
186
  src.mediaType = 'text/asciidoc'
177
187
  } else if (!(file.mediaType = src.mediaType) && !('mediaType' in src)) {
178
188
  // 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)
189
+ file.mediaType = src.mediaType = src.extname
190
+ ? resolveMimeType(src.extname) || (family === 'page' ? 'text/asciidoc' : undefined)
191
+ : 'text/plain'
180
192
  }
181
- let publishable
182
- let activeVersionSegment
193
+ let activeVersionSegment = false
194
+ let publishable, referenceable
183
195
  if (file.out) {
184
196
  publishable = true
185
197
  } else if ('out' in file) {
186
198
  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
- ) {
199
+ } else if (!file.private && this.publishableFamilies.has(family)) {
192
200
  publishable = true
193
- if (componentVersion == null) componentVersion = this.getComponentVersion(component, version) || { version }
201
+ componentVersion ??= this.getComponentVersion(src.component, src.version) || { version: src.version }
194
202
  activeVersionSegment =
195
203
  'activeVersionSegment' in componentVersion
196
204
  ? componentVersion.activeVersionSegment
197
205
  : computeVersionSegment.call(this, componentVersion)
198
- file.out = computeOut(src, family, activeVersionSegment, this.htmlUrlExtensionStyle)
206
+ file.out = computeOut.call(this, src, family, activeVersionSegment)
207
+ }
208
+ if (!file.pub) {
209
+ if ('pub' in file) {
210
+ delete file.pub
211
+ } else if (publishable || family === 'nav') {
212
+ referenceable = true
213
+ }
199
214
  }
200
- if (!file.pub && (publishable || family === 'nav')) {
201
- if (activeVersionSegment == null) {
202
- if (componentVersion == null) componentVersion = this.getComponentVersion(component, version) || { version }
215
+ if (referenceable) {
216
+ if (activeVersionSegment === false) {
217
+ componentVersion ??= this.getComponentVersion(src.component, src.version) || { version: src.version }
203
218
  activeVersionSegment =
204
219
  'activeVersionSegment' in componentVersion
205
220
  ? componentVersion.activeVersionSegment
206
221
  : computeVersionSegment.call(this, componentVersion)
207
222
  }
208
- file.pub = computePub(src, file.out, family, activeVersionSegment, this.htmlUrlExtensionStyle)
223
+ file.pub = computePub.call(this, src, file.out, family, activeVersionSegment)
209
224
  }
210
- return filesForFamily.set(key, file) && file
225
+ return file
211
226
  }
212
227
 
213
228
  removeFile (file) {
214
229
  const src = file.src
215
- const filesForFamily = this[$files].get(src.family)
216
- return filesForFamily ? filesForFamily.delete(generateKey(src)) : false
230
+ return this[$files].get(src.family)?.delete(generateKey(src)) || false
217
231
  }
218
232
 
219
233
  findBy (criteria) {
@@ -263,21 +277,27 @@ class ContentCatalog {
263
277
  return this.getComponents().sort((a, b) => a[property].localeCompare(b[property]))
264
278
  }
265
279
 
266
- getFiles () {
267
- const accum = []
268
- for (const filesForFamily of this[$files].values()) {
269
- for (const file of filesForFamily.values()) accum.push(file)
280
+ getFiles (filter) {
281
+ const files = []
282
+ if (filter) {
283
+ for (const filesForFamily of this[$files].values()) {
284
+ for (const candidate of filesForFamily.values()) filter(candidate) && files.push(candidate)
285
+ }
286
+ } else {
287
+ for (const filesForFamily of this[$files].values()) {
288
+ for (const file of filesForFamily.values()) files.push(file)
289
+ }
270
290
  }
271
- return accum
291
+ return files
272
292
  }
273
293
 
274
294
  getPages (filter) {
275
295
  const candidates = this[$files].get('page')
276
296
  if (!candidates) return []
277
297
  if (filter) {
278
- const accum = []
279
- for (const candidate of candidates.values()) filter(candidate) && accum.push(candidate)
280
- return accum
298
+ const pages = []
299
+ for (const candidate of candidates.values()) filter(candidate) && pages.push(candidate)
300
+ return pages
281
301
  }
282
302
  return [...candidates.values()]
283
303
  }
@@ -295,17 +315,14 @@ class ContentCatalog {
295
315
  if ((file = this.getById(Object.assign({}, ROOT_INDEX_ALIAS_ID, { version })))) return file.rel
296
316
  }
297
317
 
298
- registerComponentVersionStartPage (name, componentVersion, startPageSpec = undefined) {
299
- const component = name
300
- let version = componentVersion.version
301
- if (version == null) {
318
+ registerComponentVersionStartPage (component, componentVersion, startPageSpec = undefined) {
319
+ if (componentVersion.constructor === String) {
302
320
  // QUESTION: should we warn or throw error if component version cannot be found?
303
321
  if (!(componentVersion = this.getComponentVersion(component, componentVersion))) return
304
- version = componentVersion.version
305
322
  }
323
+ const version = componentVersion.version
306
324
  const activeVersionSegment = computeVersionSegment.call(this, componentVersion)
307
- let startPage
308
- let startPageSrc
325
+ let startPage, startPageSrc
309
326
  const indexPageId = Object.assign({}, ROOT_INDEX_PAGE_ID, { component, version })
310
327
  if (startPageSpec) {
311
328
  if (
@@ -314,11 +331,11 @@ class ContentCatalog {
314
331
  startPageSrc.version === version
315
332
  ) {
316
333
  if (!this.getById(indexPageId)) {
317
- const indexAliasId = Object.assign({}, ROOT_INDEX_ALIAS_ID, { component, version })
334
+ const indexAliasId = Object.assign({}, ROOT_INDEX_ALIAS_ID, { component, version, componentVersion })
318
335
  const indexAlias = this.getById(indexAliasId)
319
336
  indexAlias
320
337
  ? indexAlias.synthetic && Object.assign(indexAlias, { rel: startPage })
321
- : this.addFile({ src: indexAliasId, rel: startPage, synthetic: true }, componentVersion)
338
+ : this.addFile({ src: indexAliasId, rel: startPage, synthetic: true })
322
339
  }
323
340
  } else {
324
341
  // TODO pass componentVersion as logObject
@@ -337,20 +354,21 @@ class ContentCatalog {
337
354
  if (startPage) {
338
355
  componentVersion.url = startPage.pub.url
339
356
  } else if (!componentVersion.url) {
357
+ startPageSrc = inflateSrc(Object.assign({}, indexPageId, { family: 'page' }))
340
358
  // 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),
359
+ componentVersion.url = computePub.call(
360
+ this,
361
+ startPageSrc,
362
+ computeOut.call(this, startPageSrc, startPageSrc.family, activeVersionSegment),
344
363
  startPageSrc.family,
345
- activeVersionSegment,
346
- this.htmlUrlExtensionStyle
364
+ activeVersionSegment
347
365
  ).url
348
366
  }
349
367
  Object.defineProperties(componentVersion, {
350
368
  activeVersionSegment:
351
369
  activeVersionSegment === version
352
- ? { configurable: true, enumerable: false, get: getVersion }
353
- : { configurable: true, enumerable: false, value: activeVersionSegment },
370
+ ? { configurable: true, get: getVersion }
371
+ : { configurable: true, value: activeVersionSegment },
354
372
  files: {
355
373
  configurable: true,
356
374
  enumerable: false,
@@ -375,7 +393,7 @@ class ContentCatalog {
375
393
  const rootIndexAlias = this.getById(ROOT_INDEX_ALIAS_ID)
376
394
  if (rootIndexAlias) return rootIndexAlias.synthetic ? Object.assign(rootIndexAlias, { rel }) : undefined
377
395
  const src = Object.assign({}, ROOT_INDEX_ALIAS_ID)
378
- return this.addFile({ src, rel, synthetic: true }, { version: src.version })
396
+ return this.addFile({ src, rel, synthetic: true })
379
397
  }
380
398
  if (rel === false) {
381
399
  logger.warn('Start page specified for site has invalid syntax: %s', startPageSpec)
@@ -394,14 +412,9 @@ class ContentCatalog {
394
412
  // QUESTION should we throw an error if alias is invalid?
395
413
  if (!src || (inferredSpec && src.relative === '.adoc')) return
396
414
  const component = this.getComponent(src.component)
397
- let componentVersion
398
415
  if (component) {
399
416
  // 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
- }
417
+ src.version ??= (src.componentVersion = component.latest).version
405
418
  const existingPage = this.getById(src)
406
419
  if (existingPage) {
407
420
  throw new Error(
@@ -426,7 +439,7 @@ class ContentCatalog {
426
439
  )
427
440
  }
428
441
  // NOTE the redirect producer will populate contents when the redirect facility is 'static'
429
- const alias = this.addFile({ src, rel: target }, componentVersion)
442
+ const alias = this.addFile({ src, rel: target })
430
443
  // NOTE record the first alias this target claims as the preferred one
431
444
  if (!target.rel) target.rel = alias
432
445
  return alias
@@ -445,12 +458,18 @@ class ContentCatalog {
445
458
  const basePub = { splat: true }
446
459
  const { component: fromComponent = to.component, versionSegment: fromVersionSegment } = from
447
460
  const fromSrc = Object.assign({ component: fromComponent, version: fromVersionSegment }, baseSrc)
448
- const fromPub = Object.assign(computePub(fromSrc, computeOut(fromSrc, family, fromVersionSegment), family), basePub)
461
+ const fromPub = Object.assign(
462
+ computePub.call(this, fromSrc, computeOut.call(this, fromSrc, family, fromVersionSegment), family),
463
+ basePub
464
+ )
449
465
  const { component: toComponent, version: toVersion } = to
450
466
  const toVersionSegment =
451
467
  to.versionSegment ?? this.getComponentVersion(toComponent, toVersion)?.activeVersionSegment ?? toVersion
452
468
  const toSrc = Object.assign({ component: toComponent, version: toVersion ?? toVersionSegment }, baseSrc)
453
- const toPub = Object.assign(computePub(toSrc, computeOut(toSrc, family, toVersionSegment), family), basePub)
469
+ const toPub = Object.assign(
470
+ computePub.call(this, toSrc, computeOut.call(this, toSrc, family, toVersionSegment), family),
471
+ basePub
472
+ )
454
473
  return this.addFile({ pub: fromPub, src: fromSrc, rel: { pub: toPub, src: toSrc } })
455
474
  }
456
475
 
@@ -536,7 +555,7 @@ function generateResourceSpec ({ component, version, module: module_, family, re
536
555
  )
537
556
  }
538
557
 
539
- function prepareSrc (src) {
558
+ function inflateSrc (src) {
540
559
  let { basename, extname, stem } = src
541
560
  if (basename == null) {
542
561
  basename = src.basename = path.basename(src.relative)
@@ -544,22 +563,22 @@ function prepareSrc (src) {
544
563
  if (stem == null) {
545
564
  if (extname == null) {
546
565
  if (~(extname = basename.lastIndexOf('.'))) {
547
- src.stem = basename.substr(0, extname)
548
- src.extname = basename.substr(extname)
566
+ src.stem = basename.substring(0, extname)
567
+ src.extname = basename.substring(extname)
549
568
  } else {
550
569
  src.stem = basename
551
570
  src.extname = ''
552
571
  }
553
572
  } else {
554
- src.stem = basename.substr(0, basename.length - extname.length)
573
+ src.stem = basename.substring(0, basename.length - extname.length)
555
574
  }
556
575
  } else if (extname == null) {
557
- src.extname = basename.substr(stem.length)
576
+ src.extname = basename.substring(stem.length)
558
577
  }
559
578
  return src
560
579
  }
561
580
 
562
- function computeOut (src, family, versionSegment, htmlUrlExtensionStyle) {
581
+ function computeOut (src, family, versionSegment) {
563
582
  let { component, module: module_, basename, extname, relative, stem } = src
564
583
  if (component === 'ROOT') component = ''
565
584
  if (module_ === 'ROOT') module_ = ''
@@ -567,16 +586,14 @@ function computeOut (src, family, versionSegment, htmlUrlExtensionStyle) {
567
586
  let familyPathSegment = ''
568
587
 
569
588
  if (family === 'page') {
570
- if (stem !== 'index' && htmlUrlExtensionStyle === 'indexify') {
589
+ if (stem !== 'index' && this.htmlUrlExtensionStyle === 'indexify') {
571
590
  basename = 'index.html'
572
591
  indexifyPathSegment = stem
573
592
  } else if (extname === '.adoc') {
574
593
  basename = stem + '.html'
575
594
  }
576
- } else if (family === 'image') {
577
- familyPathSegment = '_images'
578
- } else if (family === 'attachment') {
579
- familyPathSegment = '_attachments'
595
+ } else if (this.publishableFamilies.has(family)) {
596
+ familyPathSegment = '_' + family + 's'
580
597
  }
581
598
 
582
599
  const modulePath = path.join(component, versionSegment, module_)
@@ -588,7 +605,7 @@ function computeOut (src, family, versionSegment, htmlUrlExtensionStyle) {
588
605
  return { dirname, basename, path: path_, moduleRootPath, rootPath }
589
606
  }
590
607
 
591
- function computePub (src, out, family, versionSegment, htmlUrlExtensionStyle) {
608
+ function computePub (src, out, family, versionSegment) {
592
609
  const pub = {}
593
610
  let url
594
611
  if (family === 'nav') {
@@ -604,12 +621,12 @@ function computePub (src, out, family, versionSegment, htmlUrlExtensionStyle) {
604
621
  } else if (family === 'page') {
605
622
  const urlSegments = out.path.split('/')
606
623
  const lastUrlSegmentIdx = urlSegments.length - 1
607
- if (htmlUrlExtensionStyle === 'drop') {
624
+ if (this.htmlUrlExtensionStyle === 'drop') {
608
625
  // drop just the .html extension or, if the filename is index.html, the whole segment
609
626
  const lastUrlSegment = urlSegments[lastUrlSegmentIdx]
610
627
  urlSegments[lastUrlSegmentIdx] =
611
- lastUrlSegment === 'index.html' ? '' : lastUrlSegment.substr(0, lastUrlSegment.length - 5)
612
- } else if (htmlUrlExtensionStyle === 'indexify') {
628
+ lastUrlSegment === 'index.html' ? '' : lastUrlSegment.substring(0, lastUrlSegment.length - 5)
629
+ } else if (this.htmlUrlExtensionStyle === 'indexify') {
613
630
  urlSegments[lastUrlSegmentIdx] = ''
614
631
  }
615
632
  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.2",
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.2",
35
+ "@antora/logger": "3.2.0-rc.2",
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
  }