@antora/site-generator-default 3.0.0-alpha.9 → 3.0.0-beta.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.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Antora Default Site Generator
2
2
 
3
- This is the default site generator pipeline for Antora.
4
- This pipeline is invoked by the `generate` command of Antora's CLI to produce and publish static documentation sites.
3
+ This is the default site generator for Antora.
4
+ This generator is invoked by the `generate` command of Antora's CLI to produce and publish static documentation sites.
5
5
 
6
6
  [Antora](https://antora.org) is a modular static site generator designed for creating documentation sites from AsciiDoc documents.
7
- Its site generator pipeline aggregates documents from versioned content repositories and processes them using [Asciidoctor](https://asciidoctor.org).
7
+ Its site generator aggregates documents from versioned content repositories and processes them using [Asciidoctor](https://asciidoctor.org).
8
8
 
9
9
  ## Copyright and License
10
10
 
@@ -1,74 +1,61 @@
1
1
  'use strict'
2
2
 
3
- const Pipeline = require('./pipeline')
3
+ const GeneratorContext = require('./generator-context')
4
4
  const SiteCatalog = require('./site-catalog')
5
5
 
6
- const aggregateContent = require('@antora/content-aggregator')
7
- const buildNavigation = require('@antora/navigation-builder')
8
- const buildPlaybook = require('@antora/playbook-builder')
9
- const classifyContent = require('@antora/content-classifier')
10
- const convertDocuments = require('@antora/document-converter')
11
- const createPageComposer = require('@antora/page-composer')
12
- const loadUi = require('@antora/ui-loader')
13
- const mapSite = require('@antora/site-mapper')
14
- const produceRedirects = require('@antora/redirect-producer')
15
- const publishSite = require('@antora/site-publisher')
16
- const { resolveAsciiDocConfig } = require('@antora/asciidoc-loader')
17
-
18
- async function generateSite (args, env) {
19
- let playbook = buildPlaybook(args, env)
6
+ async function generateSite (playbook) {
20
7
  try {
21
- const pipeline = new Pipeline(playbook, module)
22
- const vars = pipeline.vars
23
- await pipeline.notify('playbookBuilt')
8
+ const context = new GeneratorContext(playbook, module)
9
+ const { fxns, vars } = context
10
+ await context.notify('playbookBuilt')
24
11
  playbook = vars.lock('playbook')
25
- vars.asciidocConfig = resolveAsciiDocConfig(playbook)
12
+ vars.asciidocConfig = fxns.resolveAsciiDocConfig(playbook)
26
13
  vars.siteCatalog = new SiteCatalog()
27
- await pipeline.notify('beforeProcess')
14
+ await context.notify('beforeProcess')
28
15
  const asciidocConfig = vars.lock('asciidocConfig')
29
16
  await Promise.all([
30
- aggregateContent(playbook).then((contentAggregate) =>
31
- pipeline.notify('contentAggregated', Object.assign(vars, { contentAggregate })).then(() => {
32
- vars.contentCatalog = classifyContent(playbook, vars.remove('contentAggregate'), asciidocConfig)
17
+ fxns.aggregateContent(playbook).then((contentAggregate) =>
18
+ context.notify('contentAggregated', Object.assign(vars, { contentAggregate })).then(() => {
19
+ vars.contentCatalog = fxns.classifyContent(playbook, vars.remove('contentAggregate'), asciidocConfig)
33
20
  })
34
21
  ),
35
- loadUi(playbook).then((uiCatalog) => pipeline.notify('uiLoaded', Object.assign(vars, { uiCatalog }))),
22
+ fxns.loadUi(playbook).then((uiCatalog) => context.notify('uiLoaded', Object.assign(vars, { uiCatalog }))),
36
23
  ])
37
- await pipeline.notify('contentClassified')
24
+ await context.notify('contentClassified')
38
25
  const contentCatalog = vars.lock('contentCatalog')
39
26
  const uiCatalog = vars.lock('uiCatalog')
40
- convertDocuments(contentCatalog, asciidocConfig)
41
- await pipeline.notify('documentsConverted')
42
- vars.navigationCatalog = buildNavigation(contentCatalog, asciidocConfig)
43
- await pipeline.notify('navigationBuilt')
27
+ fxns.convertDocuments(contentCatalog, asciidocConfig)
28
+ await context.notify('documentsConverted')
29
+ vars.navigationCatalog = fxns.buildNavigation(contentCatalog, asciidocConfig)
30
+ await context.notify('navigationBuilt')
44
31
  ;(() => {
45
32
  const navigationCatalog = vars.remove('navigationCatalog')
46
- const composePage = createPageComposer(playbook, contentCatalog, uiCatalog, playbook.env)
33
+ const composePage = fxns.createPageComposer(playbook, contentCatalog, uiCatalog, playbook.env)
47
34
  contentCatalog.getPages((page) => page.out && composePage(page, contentCatalog, navigationCatalog))
48
35
  if (playbook.site.url) vars.siteCatalog.addFile(composePage(create404Page()))
49
36
  })()
50
- await pipeline.notify('pagesComposed')
51
- vars.siteCatalog.addFiles(produceRedirects(playbook, contentCatalog))
52
- await pipeline.notify('redirectsProduced')
37
+ await context.notify('pagesComposed')
38
+ vars.siteCatalog.addFiles(fxns.produceRedirects(playbook, contentCatalog))
39
+ await context.notify('redirectsProduced')
53
40
  if (playbook.site.url) {
54
41
  const publishablePages = contentCatalog.getPages((page) => page.out)
55
- vars.siteCatalog.addFiles(mapSite(playbook, publishablePages))
56
- await pipeline.notify('siteMapped')
42
+ vars.siteCatalog.addFiles(fxns.mapSite(playbook, publishablePages))
43
+ await context.notify('siteMapped')
57
44
  }
58
- await pipeline.notify('beforePublish')
59
- return publishSite(playbook, [contentCatalog, uiCatalog, vars.lock('siteCatalog')]).then((publications) => {
45
+ await context.notify('beforePublish')
46
+ return fxns.publishSite(playbook, [contentCatalog, uiCatalog, vars.lock('siteCatalog')]).then((publications) => {
60
47
  if (!playbook.runtime.quiet && process.stdout.isTTY) {
61
48
  process.stdout.write('Site generation complete!\n')
62
49
  publications.forEach(
63
50
  ({ fileUri }) => fileUri && process.stdout.write(`View the site by visiting ${fileUri} in a browser.\n`)
64
51
  )
65
52
  }
66
- return pipeline
53
+ return context
67
54
  .notify('sitePublished', Object.assign(vars, { publications }))
68
55
  .then(() => vars.remove('publications'))
69
56
  })
70
57
  } catch (err) {
71
- if (!Pipeline.isHaltSignal(err)) throw err
58
+ if (!GeneratorContext.isHaltSignal(err)) throw err
72
59
  }
73
60
  }
74
61
 
@@ -0,0 +1,160 @@
1
+ 'use strict'
2
+
3
+ const EventEmitter = require('events')
4
+ const getLogger = require('@antora/logger')
5
+ const userRequire = require('@antora/user-require-helper')
6
+
7
+ const FUNCTION_PROVIDERS = {
8
+ aggregateContent: 'content-aggregator',
9
+ buildNavigation: 'navigation-builder',
10
+ classifyContent: 'content-classifier',
11
+ convertDocument: 'document-converter',
12
+ convertDocuments: 'document-converter',
13
+ createPageComposer: 'page-composer',
14
+ extractAsciiDocMetadata: 'asciidoc-loader',
15
+ loadAsciiDoc: 'asciidoc-loader',
16
+ loadUi: 'ui-loader',
17
+ mapSite: 'site-mapper',
18
+ produceRedirects: 'redirect-producer',
19
+ publishSite: 'site-publisher',
20
+ resolveAsciiDocConfig: 'asciidoc-loader',
21
+ }
22
+
23
+ class HaltSignal extends Error {}
24
+
25
+ class GeneratorContext extends EventEmitter {
26
+ #fxns
27
+ #vars
28
+
29
+ constructor (playbook, module_) {
30
+ super()
31
+ if (!('path' in (this.module = module_))) module_.path = require('path').dirname(module_.filename)
32
+ this._registerFunctions(module_)
33
+ this._registerExtensions(playbook, this._initVariables(playbook), module_)
34
+ Object.defineProperties(this, { _initVariables: {}, _registerExtensions: {}, _registerFunctions: {} })
35
+ }
36
+
37
+ getFunctions () {
38
+ return arguments.length ? this.#fxns : Object.assign({}, this.#fxns)
39
+ }
40
+
41
+ getLogger (name = 'antora') {
42
+ return getLogger(name)
43
+ }
44
+
45
+ getVariables () {
46
+ return Object.assign({}, this.#vars)
47
+ }
48
+
49
+ halt () {
50
+ throw new HaltSignal()
51
+ }
52
+
53
+ async notify (eventName) {
54
+ if (!this.listenerCount(eventName)) return
55
+ for (const listener of this.rawListeners(eventName)) {
56
+ const outcome = listener.length === 1 ? listener.call(this, this.getVariables()) : listener.call(this)
57
+ if (outcome instanceof Promise) await outcome
58
+ }
59
+ }
60
+
61
+ replaceFunctions (updates) {
62
+ const fxns = this.#fxns
63
+ Object.entries(updates).map(([name, fxn]) => {
64
+ if (name in fxns) fxns[name] = fxn.bind(this)
65
+ })
66
+ }
67
+
68
+ require (request) {
69
+ return this.module.require(request)
70
+ }
71
+
72
+ updateVariables (updates) {
73
+ try {
74
+ Object.assign(this.#vars, updates)
75
+ } catch (err) {
76
+ if (err instanceof TypeError) {
77
+ err.message = err.message.replace(/ assign to read.only property '(.+)' .*/, " update read-only var '$1'")
78
+ }
79
+ throw err
80
+ }
81
+ }
82
+
83
+ // TODO remove updateVars before Antora 3.0.0
84
+ updateVars (updates) {
85
+ return this.updateVariables(updates)
86
+ }
87
+
88
+ static isHaltSignal (err) {
89
+ return err instanceof HaltSignal
90
+ }
91
+
92
+ _initVariables (playbook) {
93
+ Object.defineProperty(this, 'vars', {
94
+ configurable: true,
95
+ get: () => {
96
+ delete this.vars
97
+ return Object.setPrototypeOf(this.#vars, {
98
+ lock (name) {
99
+ return Object.defineProperty(this, name, { configurable: false, writable: false })[name]
100
+ },
101
+ remove (name) {
102
+ const currentValue = this[name]
103
+ delete this[name]
104
+ return currentValue
105
+ },
106
+ })
107
+ },
108
+ })
109
+ return (this.#vars = { playbook })
110
+ }
111
+
112
+ _registerExtensions (playbook, vars, module_) {
113
+ const extensions = (playbook.antora || {}).extensions || []
114
+ if (extensions.length) {
115
+ const requireContext = { dot: playbook.dir, paths: [playbook.dir || '', module_.path] }
116
+ extensions.forEach((ext) => {
117
+ const { enabled = true, id, require: request, ...config } = ext.constructor === String ? { require: ext } : ext
118
+ if (!enabled) return
119
+ const { register } = userRequire(request, requireContext)
120
+ if (typeof register !== 'function') return
121
+ if (register.length) {
122
+ if (/^(?:function *)?(?:\w+ *)?\( *\w|^\w+(?: *, *\w+)* *=>/.test(register.toString().replace(/\r?\n/g, ' '))) {
123
+ register.length === 1 ? register(this) : register(this, Object.assign({ config }, vars))
124
+ } else {
125
+ register.call(this, Object.assign({ config }, vars))
126
+ }
127
+ } else {
128
+ register.call(this)
129
+ }
130
+ })
131
+ }
132
+ this.notify = this.eventNames().length ? this.notify.bind(this) : async () => undefined
133
+ }
134
+
135
+ _registerFunctions (module_) {
136
+ this.#fxns = Object.entries(
137
+ Object.entries(FUNCTION_PROVIDERS).reduce((accum, [fxnName, moduleKey]) => {
138
+ accum[moduleKey] = (accum[moduleKey] || []).concat(fxnName)
139
+ return accum
140
+ }, {})
141
+ ).reduce((accum, [moduleKey, fxnNames]) => {
142
+ const defaultExport = module_.require('@antora/' + moduleKey)
143
+ const defaultExportName = defaultExport.name
144
+ fxnNames.forEach((fxnName) => {
145
+ const fxn = fxnName === defaultExportName ? defaultExport : defaultExport[fxnName]
146
+ accum[fxnName] = fxn.bind(this)
147
+ })
148
+ return accum
149
+ }, {})
150
+ Object.defineProperty(this, 'fxns', {
151
+ configurable: true,
152
+ get: () => {
153
+ delete this.fxns
154
+ return this.#fxns
155
+ },
156
+ })
157
+ }
158
+ }
159
+
160
+ module.exports = GeneratorContext
package/lib/index.js CHANGED
@@ -3,10 +3,9 @@
3
3
  /**
4
4
  * Default Site Generator component for Antora
5
5
  *
6
- * Runs an Antora pipeline using the default set of components with a focus on
7
- * producing and publishing a documentation site. This component represents
8
- * just one way the Antora components can be organized into a site generation
9
- * pipeline.
6
+ * Coordinates a default set of software components to produce and publish a
7
+ * documentation site. This component represents just one way the Antora
8
+ * components can be organized to make a documentation generator.
10
9
  *
11
10
  * @namespace site-generator-default
12
11
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@antora/site-generator-default",
3
- "version": "3.0.0-alpha.9",
4
- "description": "The default site generator pipeline for producing and publishing static documentation sites with Antora.",
3
+ "version": "3.0.0-beta.1",
4
+ "description": "The default site generator for producing and publishing static documentation sites with Antora.",
5
5
  "license": "MPL-2.0",
6
6
  "author": "OpenDevise Inc. (https://opendevise.com)",
7
7
  "contributors": [
@@ -15,21 +15,24 @@
15
15
  },
16
16
  "main": "lib/index.js",
17
17
  "dependencies": {
18
- "@antora/asciidoc-loader": "3.0.0-alpha.9",
19
- "@antora/content-aggregator": "3.0.0-alpha.9",
20
- "@antora/content-classifier": "3.0.0-alpha.9",
21
- "@antora/document-converter": "3.0.0-alpha.9",
22
- "@antora/navigation-builder": "3.0.0-alpha.9",
23
- "@antora/page-composer": "3.0.0-alpha.9",
24
- "@antora/playbook-builder": "3.0.0-alpha.9",
25
- "@antora/redirect-producer": "3.0.0-alpha.9",
26
- "@antora/site-mapper": "3.0.0-alpha.9",
27
- "@antora/site-publisher": "3.0.0-alpha.9",
28
- "@antora/ui-loader": "3.0.0-alpha.9",
18
+ "@antora/asciidoc-loader": "3.0.0-beta.1",
19
+ "@antora/content-aggregator": "3.0.0-beta.1",
20
+ "@antora/content-classifier": "3.0.0-beta.1",
21
+ "@antora/document-converter": "3.0.0-beta.1",
22
+ "@antora/logger": "3.0.0-beta.1",
23
+ "@antora/navigation-builder": "3.0.0-beta.1",
24
+ "@antora/page-composer": "3.0.0-beta.1",
25
+ "@antora/redirect-producer": "3.0.0-beta.1",
26
+ "@antora/site-mapper": "3.0.0-beta.1",
27
+ "@antora/site-publisher": "3.0.0-beta.1",
28
+ "@antora/ui-loader": "3.0.0-beta.1",
29
29
  "@antora/user-require-helper": "~2.0"
30
30
  },
31
+ "devDependencies": {
32
+ "@antora/playbook-builder": "3.0.0-beta.1"
33
+ },
31
34
  "engines": {
32
- "node": ">=10.17.0"
35
+ "node": ">=12.21.0"
33
36
  },
34
37
  "files": [
35
38
  "lib/"
@@ -43,5 +46,5 @@
43
46
  "static site",
44
47
  "web publishing"
45
48
  ],
46
- "gitHead": "a504d6889819b548e8a5416a7194cbb6f9a93e93"
49
+ "gitHead": "7c5ef1ea93dd489af533c80a936c736013c41769"
47
50
  }
package/lib/pipeline.js DELETED
@@ -1,90 +0,0 @@
1
- 'use strict'
2
-
3
- const EventEmitter = require('events')
4
- const userRequire = require('@antora/user-require-helper')
5
-
6
- class HaltPipelineSignal extends Error {}
7
-
8
- class Pipeline extends EventEmitter {
9
- constructor (playbook, module_) {
10
- super()
11
- if (!('path' in (this.module = module_))) module_.path = require('path').dirname(module_.filename)
12
- _registerExtensions.bind(this)(playbook, module_, _initVars.bind(this)(playbook))
13
- }
14
-
15
- halt () {
16
- throw new HaltPipelineSignal()
17
- }
18
-
19
- async notify (vars, eventName) {
20
- if (this.listenerCount(eventName)) {
21
- for (const listener of this.rawListeners(eventName)) {
22
- const outcome = listener.call(this, Object.assign({}, vars))
23
- if (outcome instanceof Promise) await outcome
24
- }
25
- }
26
- }
27
-
28
- require (request) {
29
- return this.module.require(request)
30
- }
31
-
32
- updateVars (vars, updates) {
33
- try {
34
- Object.assign(vars, updates)
35
- } catch (err) {
36
- if (err instanceof TypeError) {
37
- err.message = err.message.replace(/ assign to read.only property '(.+)' .*/, " update read-only var '$1'")
38
- }
39
- throw err
40
- }
41
- }
42
-
43
- static isHaltSignal (err) {
44
- return err instanceof HaltPipelineSignal
45
- }
46
- }
47
-
48
- function _initVars (playbook) {
49
- const vars = Object.setPrototypeOf(
50
- { playbook },
51
- {
52
- lock (name) {
53
- return Object.defineProperty(this, name, { configurable: false, writable: false })[name]
54
- },
55
- remove (name) {
56
- const currentValue = this[name]
57
- delete this[name]
58
- return currentValue
59
- },
60
- }
61
- )
62
- Object.defineProperty(this, 'vars', {
63
- configurable: true,
64
- get: () => {
65
- delete this.vars
66
- return vars
67
- },
68
- })
69
- this.updateVars = this.updateVars.bind(this, vars)
70
- return vars
71
- }
72
-
73
- function _registerExtensions (playbook, module_, vars) {
74
- const extensions = (playbook.pipeline || {}).extensions
75
- if (extensions.length) {
76
- const requireContext = { dot: playbook.dir, paths: [playbook.dir || '', module_.path] }
77
- extensions.forEach((ext) => {
78
- const { enabled = true, id, require: request, ...config } = ext.constructor === String ? { require: ext } : ext
79
- if (enabled) {
80
- const { register } = userRequire(request, requireContext)
81
- if (typeof register === 'function') {
82
- register.length === 1 ? register(this) : register(this, Object.assign({ config }, vars))
83
- }
84
- }
85
- })
86
- }
87
- this.notify = this.eventNames().length ? this.notify.bind(this, vars) : async () => undefined
88
- }
89
-
90
- module.exports = Pipeline