@antora/content-classifier 3.2.0-alpha.1 → 3.2.0-alpha.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.
package/README.md CHANGED
@@ -9,4 +9,4 @@ Its site generator aggregates documents from versioned content repositories and
9
9
 
10
10
  Copyright (C) 2017-present [OpenDevise Inc.](https://opendevise.com) and the [Antora Project](https://antora.org).
11
11
 
12
- Use of this software is granted under the terms of the [Mozilla Public License Version 2.0](https://www.mozilla.org/en-US/MPL/2.0/) (MPL-2.0).
12
+ Use of this software is granted under the terms of the [Mozilla Public License Version 2.0](https://www.mozilla.org/en-US/MPL/2.0/) (MPL-2.0).
@@ -8,42 +8,58 @@ const collateAsciiDocAttributes = require('@antora/asciidoc-loader/config/collat
8
8
  *
9
9
  * @memberof content-classifier
10
10
  *
11
- * @param {Object} playbook - The configuration object for Antora.
11
+ * @param {Object} playbook - The configuration object for Antora. See ContentCatalog constructor for relevant keys.
12
12
  * @param {Object} playbook.site - Site-related configuration data.
13
13
  * @param {String} playbook.site.startPage - The start page for the site; redirects from base URL.
14
- * @param {Object} playbook.urls - URL settings for the site.
15
- * @param {String} playbook.urls.htmlExtensionStyle - The style to use when computing page URLs.
16
14
  * @param {Object} aggregate - The raw aggregate of virtual file objects to be classified.
17
15
  * @param {Object} [siteAsciiDocConfig={}] - Site-wide AsciiDoc processor configuration options.
18
- * @returns {ContentCatalog} A structured catalog of content components and virtual content files.
16
+ * @param {Function} [onComponentsRegistered] - A function (optionally async) to invoke after components are
17
+ * registered. Must return an instance of ContentCatalog. If async, this function will also return a Promise.
18
+ *
19
+ * @returns {ContentCatalog} A structured catalog of content components, versions, and virtual content files.
19
20
  */
20
- function classifyContent (playbook, aggregate, siteAsciiDocConfig = {}) {
21
- const contentCatalog = new ContentCatalog(playbook)
22
- aggregate
23
- .reduce((accum, componentVersionData) => {
24
- // drop files since they aren't needed to register component version
25
- // drop startPage to defer registration of start page
26
- const { name, version, files, startPage, ...descriptor } = Object.assign({}, componentVersionData, {
27
- asciidoc: resolveAsciiDocConfig(siteAsciiDocConfig, componentVersionData),
28
- })
29
- return new Map(accum).set(
30
- contentCatalog.registerComponentVersion(name, version, descriptor),
31
- componentVersionData
32
- )
33
- }, new Map())
34
- .forEach((componentVersionData, componentVersion) => {
35
- const { name, version } = componentVersion
36
- const { files, nav, startPage } = componentVersionData
37
- componentVersionData.files = undefined // clean up memory
38
- files.forEach((file) => allocateSrc(file, name, version, nav) && contentCatalog.addFile(file, componentVersion))
39
- contentCatalog.registerComponentVersionStartPage(name, componentVersion, startPage)
21
+ function classifyContent (playbook, aggregate, siteAsciiDocConfig = {}, onComponentsRegistered) {
22
+ const siteStartPage = playbook.site.startPage
23
+ let contentCatalog = registerComponentVersions(new ContentCatalog(playbook), aggregate, siteAsciiDocConfig)
24
+ return typeof onComponentsRegistered === 'function' &&
25
+ (contentCatalog = onComponentsRegistered(contentCatalog)) instanceof Promise
26
+ ? contentCatalog.then((contentCatalogValue) => addFilesAndRegisterStartPages(contentCatalogValue, siteStartPage))
27
+ : addFilesAndRegisterStartPages(contentCatalog, siteStartPage)
28
+ }
29
+
30
+ function registerComponentVersions (contentCatalog, aggregate, siteAsciiDocConfig) {
31
+ for (const componentVersionBucket of aggregate) {
32
+ // advance files, nav, and startPage to component version to be used in later phase
33
+ const { name, version, files, nav, startPage, ...data } = Object.assign(componentVersionBucket, {
34
+ asciidoc: resolveAsciiDocConfig(siteAsciiDocConfig, componentVersionBucket),
40
35
  })
41
- contentCatalog.registerSiteStartPage(playbook.site.startPage)
36
+ Object.assign(contentCatalog.registerComponentVersion(name, version, data), { files, nav, startPage })
37
+ }
38
+ return contentCatalog
39
+ }
40
+
41
+ function addFilesAndRegisterStartPages (contentCatalog, siteStartPage) {
42
+ for (const { versions: componentVersions } of contentCatalog.getComponents()) {
43
+ for (const componentVersion of componentVersions) {
44
+ const { name: component, version, files = [], nav, startPage } = componentVersion
45
+ for (let file, i = 0, len = files.length; i < len; i++) {
46
+ allocateSrc((file = files[i]), component, version, nav) && contentCatalog.addFile(file, componentVersion)
47
+ files[i] = undefined // free memory
48
+ }
49
+ contentCatalog.registerComponentVersionStartPage(component, componentVersion, startPage)
50
+ }
51
+ }
52
+ contentCatalog.registerSiteStartPage(siteStartPage)
42
53
  return contentCatalog
43
54
  }
44
55
 
45
56
  function allocateSrc (file, component, version, nav) {
46
- const extname = file.src.extname
57
+ const { extname, family } = file.src
58
+ if (family && family !== 'nav') {
59
+ Object.assign(file.src, { component, version })
60
+ file.src.moduleRootPath ??= calculateRootPath(file.src.relative.split('/').length)
61
+ return true
62
+ }
47
63
  const filepath = file.path
48
64
  const navInfo = nav && getNavInfo(filepath, nav)
49
65
  const pathSegments = filepath.split('/')
@@ -42,6 +42,8 @@ class ContentCatalog {
42
42
  /**
43
43
  * Registers a new component version with the content catalog. Also registers the component if it does not yet exist.
44
44
  *
45
+ * Must be followed by a call to registerComponentVersionStartPage to finalize object.
46
+ *
45
47
  * @param {String} name - The name of the component to which this component version belongs.
46
48
  * @param {String} version - The version of the component to register.
47
49
  * @param {Object} [descriptor={}] - The configuration data for the component version.
@@ -274,7 +276,15 @@ class ContentCatalog {
274
276
 
275
277
  // TODO add `follow` argument to control whether alias is followed
276
278
  getSiteStartPage () {
277
- return this.getById(ROOT_INDEX_PAGE_ID) || (this.getById(ROOT_INDEX_ALIAS_ID) || {}).rel
279
+ let file
280
+ if ((file = this.getById(ROOT_INDEX_PAGE_ID))) return file
281
+ if ((file = this.getById(ROOT_INDEX_ALIAS_ID))) return file.rel
282
+ const rootComponent = this.getComponent('ROOT')
283
+ if (!rootComponent) return
284
+ const version = rootComponent.versions.find(({ activeVersionSegment }) => activeVersionSegment === '')?.version
285
+ if (!version) return
286
+ if ((file = this.getById(Object.assign({}, ROOT_INDEX_PAGE_ID, { version })))) return file
287
+ if ((file = this.getById(Object.assign({}, ROOT_INDEX_ALIAS_ID, { version })))) return file.rel
278
288
  }
279
289
 
280
290
  registerComponentVersionStartPage (name, componentVersion, startPageSpec = undefined) {
@@ -318,7 +328,7 @@ class ContentCatalog {
318
328
  }
319
329
  if (startPage) {
320
330
  componentVersion.url = startPage.pub.url
321
- } else {
331
+ } else if (!componentVersion.url) {
322
332
  // QUESTION: should we warn if the default start page cannot be found?
323
333
  componentVersion.url = computePub(
324
334
  (startPageSrc = prepareSrc(Object.assign({}, indexPageId, { family: 'page' }))),
@@ -328,21 +338,24 @@ class ContentCatalog {
328
338
  this.htmlUrlExtensionStyle
329
339
  ).url
330
340
  }
331
-
332
- Object.defineProperty(
333
- componentVersion,
334
- 'activeVersionSegment',
335
- activeVersionSegment === version
336
- ? {
337
- configurable: true,
338
- get () {
339
- return this.version
340
- },
341
- }
342
- : { configurable: true, value: activeVersionSegment }
343
- )
344
-
341
+ Object.defineProperties(componentVersion, {
342
+ activeVersionSegment:
343
+ activeVersionSegment === version
344
+ ? { configurable: true, enumerable: false, get: getVersion }
345
+ : { configurable: true, enumerable: false, value: activeVersionSegment },
346
+ files: {
347
+ configurable: true,
348
+ enumerable: false,
349
+ get: getComponentVersionFiles.bind(this, { component, version }),
350
+ },
351
+ startPage: {
352
+ configurable: true,
353
+ enumerable: false,
354
+ get: getComponentVersionStartPage.bind(this, { component, version }),
355
+ },
356
+ })
345
357
  addSymbolicVersionAlias.call(this, componentVersion)
358
+ return startPage
346
359
  }
347
360
 
348
361
  registerSiteStartPage (startPageSpec) {
@@ -350,8 +363,9 @@ class ContentCatalog {
350
363
  const rel = this.resolvePage(startPageSpec)
351
364
  if (rel) {
352
365
  if (this.getById(ROOT_INDEX_PAGE_ID)) return
353
- const indexAlias = this.getById(ROOT_INDEX_ALIAS_ID)
354
- if (indexAlias) return indexAlias.synthetic ? Object.assign(indexAlias, { rel }) : undefined
366
+ if (rel.pub.url === (this.htmlUrlExtensionStyle === 'default' ? '/index.html' : '/')) return
367
+ const rootIndexAlias = this.getById(ROOT_INDEX_ALIAS_ID)
368
+ if (rootIndexAlias) return rootIndexAlias.synthetic ? Object.assign(rootIndexAlias, { rel }) : undefined
355
369
  const src = Object.assign({}, ROOT_INDEX_ALIAS_ID)
356
370
  return this.addFile({ src, rel, synthetic: true }, { version: src.version })
357
371
  } else if (rel === false) {
@@ -626,4 +640,16 @@ function getFileLocation ({ path: path_, src: { abspath, origin } }) {
626
640
  return `${abspath || path.join(startPath, path_)} in ${'worktree' in origin ? worktree || gitdir : url} (${details})`
627
641
  }
628
642
 
643
+ function getComponentVersionFiles (componentVersionId) {
644
+ return this.findBy(componentVersionId)
645
+ }
646
+
647
+ function getComponentVersionStartPage (componentVersionId) {
648
+ return this.resolvePage('index.adoc', componentVersionId)
649
+ }
650
+
651
+ function getVersion () {
652
+ return this.version
653
+ }
654
+
629
655
  module.exports = ContentCatalog
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antora/content-classifier",
3
- "version": "3.2.0-alpha.1",
3
+ "version": "3.2.0-alpha.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)",
@@ -27,8 +27,8 @@
27
27
  "#constants": "./lib/constants.js"
28
28
  },
29
29
  "dependencies": {
30
- "@antora/asciidoc-loader": "3.2.0-alpha.1",
31
- "@antora/logger": "3.2.0-alpha.1",
30
+ "@antora/asciidoc-loader": "3.2.0-alpha.2",
31
+ "@antora/logger": "3.2.0-alpha.2",
32
32
  "mime-types": "~2.1",
33
33
  "vinyl": "~2.2"
34
34
  },