@antora/content-aggregator 3.0.0-alpha.6 → 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 +1 -1
- package/lib/aggregate-content.js +314 -287
- package/lib/constants.js +6 -5
- package/lib/decode-uint8-array.js +6 -0
- package/lib/filter-refs.js +60 -0
- package/lib/git-credential-manager-store.js +7 -12
- package/lib/git-plugin-http.js +49 -25
- package/lib/git.js +3 -0
- package/lib/index.js +1 -1
- package/lib/promise-all-settled-polyfill.js +11 -0
- package/lib/resolve-path-globs.js +36 -35
- package/package.json +8 -8
package/lib/constants.js
CHANGED
|
@@ -2,24 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
module.exports = Object.freeze({
|
|
4
4
|
COMPONENT_DESC_FILENAME: 'antora.yml',
|
|
5
|
-
CONTENT_CACHE_FOLDER: 'content
|
|
6
|
-
|
|
5
|
+
CONTENT_CACHE_FOLDER: 'content',
|
|
6
|
+
CONTENT_SRC_GLOB: '**/*[!~]',
|
|
7
|
+
CONTENT_SRC_OPTS: { follow: true, nomount: true, nosort: true, nounique: true, removeBOM: false, uniqueBy: (m) => m },
|
|
7
8
|
FILE_MODES: { 100644: 0o100666 & ~process.umask(), 100755: 0o100777 & ~process.umask() },
|
|
8
9
|
GIT_CORE: 'antora',
|
|
9
10
|
GIT_OPERATION_LABEL_LENGTH: 8,
|
|
10
11
|
GIT_PROGRESS_PHASES: ['Counting objects', 'Compressing objects', 'Receiving objects', 'Resolving deltas'],
|
|
11
12
|
PICOMATCH_VERSION_OPTS: {
|
|
12
13
|
bash: true,
|
|
13
|
-
debug: false,
|
|
14
14
|
dot: true,
|
|
15
15
|
fastpaths: false,
|
|
16
|
-
|
|
17
|
-
noextglob: true,
|
|
16
|
+
nobracket: true,
|
|
18
17
|
noglobstar: true,
|
|
19
18
|
nonegate: true,
|
|
20
19
|
noquantifiers: true,
|
|
20
|
+
regex: false,
|
|
21
21
|
strictSlashes: true,
|
|
22
22
|
},
|
|
23
|
+
REF_PATTERN_CACHE_KEY: Symbol('RefPatternCache'),
|
|
23
24
|
SYMLINK_FILE_MODE: '120000',
|
|
24
25
|
VALID_STATE_FILENAME: 'valid',
|
|
25
26
|
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { compile: bracesToGroup } = require('braces')
|
|
4
|
+
const { makeRe: makePicomatchRx } = require('picomatch')
|
|
5
|
+
|
|
6
|
+
function getPicomatchOpts (cache) {
|
|
7
|
+
return {
|
|
8
|
+
bash: true,
|
|
9
|
+
dot: true,
|
|
10
|
+
expandRange: (begin, end, step, opts) => {
|
|
11
|
+
const pattern = opts ? `{${begin}..${end}..${step}}` : `{${begin}..${end}}`
|
|
12
|
+
return cache.braces.get(pattern) || cache.braces.set(pattern, bracesToGroup(pattern)).get(pattern)
|
|
13
|
+
},
|
|
14
|
+
fastpaths: false,
|
|
15
|
+
nobracket: true,
|
|
16
|
+
noglobstar: true,
|
|
17
|
+
noquantifiers: true,
|
|
18
|
+
regex: false,
|
|
19
|
+
strictSlashes: true,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function compileRx (pattern, opts) {
|
|
24
|
+
if (pattern === '*' || pattern === '**') return { test: () => true }
|
|
25
|
+
return pattern.charAt() === '!' // do our own negate
|
|
26
|
+
? Object.defineProperty(makePicomatchRx(pattern.substr(1), opts), 'negated', { value: true })
|
|
27
|
+
: makePicomatchRx(pattern, opts)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function createMatcher (patterns, cache) {
|
|
31
|
+
let opts
|
|
32
|
+
const rxs = patterns.map(
|
|
33
|
+
(pattern) =>
|
|
34
|
+
cache.get(pattern) ||
|
|
35
|
+
cache.set(pattern, compileRx(pattern, opts || (opts = getPicomatchOpts(cache)))).get(pattern)
|
|
36
|
+
)
|
|
37
|
+
return (candidate) => {
|
|
38
|
+
let first = true
|
|
39
|
+
let matched
|
|
40
|
+
for (const rx of rxs) {
|
|
41
|
+
if (matched) {
|
|
42
|
+
if (rx.negated && rx.test(candidate)) return
|
|
43
|
+
} else if (first || !rx.negated) {
|
|
44
|
+
matched = rx.test(candidate)
|
|
45
|
+
}
|
|
46
|
+
first = false
|
|
47
|
+
}
|
|
48
|
+
return matched
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function filterRefs (candidates, patterns, cache = Object.assign(new Map(), { braces: new Map() })) {
|
|
53
|
+
const isMatch = createMatcher(patterns, cache)
|
|
54
|
+
return candidates.reduce((accum, candidate) => {
|
|
55
|
+
if (isMatch(candidate)) accum.push(candidate)
|
|
56
|
+
return accum
|
|
57
|
+
}, [])
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = filterRefs
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { homedir } = require('os')
|
|
4
4
|
const expandPath = require('@antora/expand-path-helper')
|
|
5
|
+
const invariably = { void: () => undefined }
|
|
5
6
|
const { promises: fsp } = require('fs')
|
|
6
7
|
const ospath = require('path')
|
|
7
8
|
|
|
@@ -9,12 +10,10 @@ class GitCredentialManagerStore {
|
|
|
9
10
|
configure ({ config, startDir }) {
|
|
10
11
|
this.entries = undefined
|
|
11
12
|
this.urls = {}
|
|
12
|
-
if ((this.contents = (config = config || {}).contents)) {
|
|
13
|
+
if ((this.contents = (config = config || {}).contents) || !config.path) {
|
|
13
14
|
this.path = undefined
|
|
14
|
-
} else if (config.path) {
|
|
15
|
-
this.path = expandPath(config.path, '~+', startDir)
|
|
16
15
|
} else {
|
|
17
|
-
this.path =
|
|
16
|
+
this.path = expandPath(config.path, { dot: startDir })
|
|
18
17
|
}
|
|
19
18
|
return this
|
|
20
19
|
}
|
|
@@ -28,10 +27,7 @@ class GitCredentialManagerStore {
|
|
|
28
27
|
contentsPromise = Promise.resolve(this.contents)
|
|
29
28
|
delimiter = /[,\n]/
|
|
30
29
|
} else if (this.path) {
|
|
31
|
-
contentsPromise = fsp
|
|
32
|
-
.access(this.path)
|
|
33
|
-
.then(() => fsp.readFile(this.path, 'utf8'))
|
|
34
|
-
.catch(() => undefined)
|
|
30
|
+
contentsPromise = fsp.access(this.path).then(() => fsp.readFile(this.path, 'utf8'), invariably.void)
|
|
35
31
|
} else {
|
|
36
32
|
const homeGitCredentialsPath = ospath.join(homedir(), '.git-credentials')
|
|
37
33
|
const xdgConfigGitCredentialsPath = ospath.join(
|
|
@@ -45,8 +41,7 @@ class GitCredentialManagerStore {
|
|
|
45
41
|
.catch(() =>
|
|
46
42
|
fsp
|
|
47
43
|
.access(xdgConfigGitCredentialsPath)
|
|
48
|
-
.then(() => fsp.readFile(xdgConfigGitCredentialsPath, 'utf8'))
|
|
49
|
-
.catch(() => undefined)
|
|
44
|
+
.then(() => fsp.readFile(xdgConfigGitCredentialsPath, 'utf8'), invariably.void)
|
|
50
45
|
)
|
|
51
46
|
}
|
|
52
47
|
contentsPromise.then((contents) => {
|
|
@@ -62,7 +57,7 @@ class GitCredentialManagerStore {
|
|
|
62
57
|
if (password) {
|
|
63
58
|
credentials = { username: decodeURIComponent(username), password: decodeURIComponent(password) }
|
|
64
59
|
} else if (username) {
|
|
65
|
-
credentials = {
|
|
60
|
+
credentials = { username: decodeURIComponent(username), password: '' }
|
|
66
61
|
} else {
|
|
67
62
|
return accum
|
|
68
63
|
}
|
|
@@ -101,7 +96,7 @@ class GitCredentialManagerStore {
|
|
|
101
96
|
const statusCode = 401
|
|
102
97
|
const statusMessage = 'HTTP Basic: Access Denied'
|
|
103
98
|
const err = new Error(`HTTP Error: ${statusCode} ${statusMessage}`)
|
|
104
|
-
err.name = err.code = '
|
|
99
|
+
err.name = err.code = 'HttpError'
|
|
105
100
|
err.data = { statusCode, statusMessage }
|
|
106
101
|
if (auth) err.rejected = true
|
|
107
102
|
throw err
|
package/lib/git-plugin-http.js
CHANGED
|
@@ -1,32 +1,56 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const get = require('simple-get')
|
|
4
|
-
const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent')
|
|
5
|
-
const shouldProxy = require('should-proxy')
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
5
|
+
function distillResponse (res) {
|
|
6
|
+
const { url, method, statusCode, statusMessage, headers } = res
|
|
7
|
+
return { url, method, statusCode, statusMessage, headers, body: res }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function mergeBuffers (data) {
|
|
11
|
+
if (!Array.isArray(data)) return data
|
|
12
|
+
if (data.length === 1 && data[0] instanceof Buffer) return data[0]
|
|
13
|
+
const buffers = []
|
|
14
|
+
let offset = 0
|
|
15
|
+
let size = 0
|
|
16
|
+
for await (const chunk of data) {
|
|
17
|
+
buffers.push(chunk)
|
|
18
|
+
size += chunk.byteLength
|
|
19
|
+
}
|
|
20
|
+
data = new Uint8Array(size)
|
|
21
|
+
for (const buffer of buffers) {
|
|
22
|
+
data.set(buffer, offset)
|
|
23
|
+
offset += buffer.byteLength
|
|
24
|
+
}
|
|
25
|
+
return Buffer.from(data.buffer)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = ({ httpProxy, httpsProxy, noProxy }, userAgent) => {
|
|
29
|
+
if ((httpsProxy || httpProxy) && noProxy !== '*') {
|
|
30
|
+
const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent')
|
|
31
|
+
const shouldProxy = require('should-proxy')
|
|
32
|
+
return {
|
|
33
|
+
async request ({ url, method, headers, body }) {
|
|
34
|
+
headers['user-agent'] = userAgent
|
|
35
|
+
body = await mergeBuffers(body)
|
|
36
|
+
const proxy = url.startsWith('https:')
|
|
37
|
+
? { Agent: HttpsProxyAgent, url: httpsProxy }
|
|
38
|
+
: { Agent: HttpProxyAgent, url: httpProxy }
|
|
39
|
+
const agent =
|
|
40
|
+
proxy.url && shouldProxy(url, { no_proxy: noProxy }) ? new proxy.Agent({ proxy: proxy.url }) : undefined
|
|
41
|
+
return new Promise((resolve, reject) =>
|
|
42
|
+
get({ url, method, agent, headers, body }, (err, res) => (err ? reject(err) : resolve(distillResponse(res))))
|
|
43
|
+
)
|
|
44
|
+
},
|
|
23
45
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
async request ({ url, method, headers, body }) {
|
|
49
|
+
headers['user-agent'] = userAgent
|
|
50
|
+
body = await mergeBuffers(body)
|
|
51
|
+
return new Promise((resolve, reject) =>
|
|
52
|
+
get({ url, method, headers, body }, (err, res) => (err ? reject(err) : resolve(distillResponse(res))))
|
|
53
|
+
)
|
|
54
|
+
},
|
|
31
55
|
}
|
|
32
56
|
}
|
package/lib/git.js
ADDED
package/lib/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Responsible for aggregating the content from multiple repositories and
|
|
7
7
|
* references into a raw aggregate of virtual files that can be organized by a
|
|
8
|
-
* subsequent step in the
|
|
8
|
+
* subsequent step in the generator.
|
|
9
9
|
*
|
|
10
10
|
* @namespace content-aggregator
|
|
11
11
|
*/
|
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { expand: expandBraces } = require('braces')
|
|
3
|
+
const { expand: expandBraces, compile: bracesToGroup } = require('braces')
|
|
4
4
|
const flattenDeep = require('./flatten-deep')
|
|
5
5
|
const { promises: fsp } = require('fs')
|
|
6
|
-
const git = require('
|
|
7
|
-
const invariably = { true: () => true, false: () => false, void: () =>
|
|
6
|
+
const git = require('./git')
|
|
7
|
+
const invariably = { true: () => true, false: () => false, void: () => undefined, emptyArray: () => [] }
|
|
8
8
|
const { makeRe: makePicomatchRx } = require('picomatch')
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
const RX_MAGIC_DETECTOR = /[*{]/
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const NON_GLOB_SPECIAL_CHARS_RX = /[.+?^${}()|[\]\\]/g
|
|
11
|
+
const RX_MAGIC_DETECTOR = /[*{(]/
|
|
12
|
+
const PICOMATCH_OPTS = {
|
|
13
|
+
bash: true,
|
|
14
|
+
expandRange: (begin, end, step, opts) => bracesToGroup(opts ? `{${begin}..${end}..${step}}` : `{${begin}..${end}}`),
|
|
15
|
+
fastpaths: false,
|
|
16
|
+
nobracket: true,
|
|
17
|
+
noglobstar: true,
|
|
18
|
+
nonegate: true,
|
|
19
|
+
noquantifiers: true,
|
|
20
|
+
regex: false,
|
|
21
|
+
strictSlashes: true,
|
|
22
|
+
}
|
|
15
23
|
|
|
16
24
|
function resolvePathGlobs (base, patterns, listDirents, retrievePath, tree = { path: '' }) {
|
|
17
25
|
return patterns.reduce((paths, pattern) => {
|
|
18
26
|
if (pattern.charAt() === '!') {
|
|
19
27
|
return paths.then((resolvedPaths) => {
|
|
20
28
|
if (resolvedPaths.length) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return resolvedPaths.filter(rx.test.bind(rx))
|
|
29
|
+
const rx = makePicomatchRx(pattern.substr(1), PICOMATCH_OPTS)
|
|
30
|
+
return resolvedPaths.filter((it) => !rx.test(it))
|
|
24
31
|
} else {
|
|
25
32
|
return resolvedPaths
|
|
26
33
|
}
|
|
@@ -38,14 +45,13 @@ async function glob (base, patternSegments, listDirents, retrievePath, { oid, pa
|
|
|
38
45
|
let patternSegment = patternSegments[0]
|
|
39
46
|
patternSegments = patternSegments.slice(1)
|
|
40
47
|
if (RX_MAGIC_DETECTOR.test(patternSegment)) {
|
|
41
|
-
let isMatch
|
|
42
|
-
let explicit
|
|
48
|
+
let isMatch, explicit
|
|
43
49
|
if (patternSegment === '*') {
|
|
44
50
|
isMatch = (it) => it.charAt() !== '.'
|
|
51
|
+
} else if (~patternSegment.indexOf('(')) {
|
|
52
|
+
isMatch = (isMatch = makePicomatchRx(patternSegment, PICOMATCH_OPTS)).test.bind(isMatch)
|
|
45
53
|
} else if (~patternSegment.indexOf('{')) {
|
|
46
54
|
if (globbed) {
|
|
47
|
-
if (patternSegment.charAt() === '!') patternSegment = '\\' + patternSegment
|
|
48
|
-
if (~patternSegment.indexOf('?')) patternSegment = patternSegment.replace(RX_QUESTION_MARK, '\\?')
|
|
49
55
|
isMatch = (isMatch = makePicomatchRx(patternSegment, PICOMATCH_OPTS)).test.bind(isMatch)
|
|
50
56
|
} else if (~patternSegment.indexOf('*')) {
|
|
51
57
|
const [wildPatterns, literals] = expandBraces(patternSegment).reduce(
|
|
@@ -90,22 +96,15 @@ async function glob (base, patternSegments, listDirents, retrievePath, { oid, pa
|
|
|
90
96
|
})
|
|
91
97
|
} else if ((patternSegment += '/' + patternSegments.join('/')).indexOf('{')) {
|
|
92
98
|
return expandBraces(patternSegment).map((it) => joinPath(path, it))
|
|
93
|
-
} else {
|
|
94
|
-
return [joinPath(path, patternSegment)]
|
|
95
99
|
}
|
|
100
|
+
return [joinPath(path, patternSegment)]
|
|
96
101
|
} else if (globbed) {
|
|
97
102
|
return (await retrievePath(base, { oid, path }, patternSegment)) ? [joinPath(path, patternSegment)] : []
|
|
98
|
-
} else {
|
|
99
|
-
return [joinPath(path, patternSegment)]
|
|
100
103
|
}
|
|
104
|
+
return [joinPath(path, patternSegment)]
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
function regexpEscapeWithGlob (str) {
|
|
105
|
-
// we don't escape "-" since it's meaningless in a literal
|
|
106
|
-
return str.replace(RX_ESCAPE_EXCEPT_GLOB, '\\$&').replace('*', '.*')
|
|
107
|
-
}
|
|
108
|
-
|
|
109
108
|
function extractMagicBase (patternSegments, base) {
|
|
110
109
|
let nextSegment
|
|
111
110
|
if (patternSegments.length) {
|
|
@@ -123,12 +122,11 @@ function listDirentsFs (base, path) {
|
|
|
123
122
|
|
|
124
123
|
function listDirentsGit (repo, treeOid) {
|
|
125
124
|
return git
|
|
126
|
-
.
|
|
127
|
-
.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
: []
|
|
125
|
+
.readTree(Object.assign({ oid: treeOid, filepath: '' }, repo))
|
|
126
|
+
.then(
|
|
127
|
+
({ tree: entries }) =>
|
|
128
|
+
entries.map(({ type, oid, path: name }) => ({ name, oid, isDirectory: invariably[type === 'tree'] })),
|
|
129
|
+
invariably.emptyArray
|
|
132
130
|
)
|
|
133
131
|
}
|
|
134
132
|
|
|
@@ -141,7 +139,13 @@ function makeMatcherRx (pattern) {
|
|
|
141
139
|
}
|
|
142
140
|
|
|
143
141
|
function patternToRx (pattern) {
|
|
144
|
-
return (
|
|
142
|
+
return (
|
|
143
|
+
(pattern.charAt() === '.' ? '' : '(?!\\.)') +
|
|
144
|
+
pattern
|
|
145
|
+
.replace(NON_GLOB_SPECIAL_CHARS_RX, '\\$&')
|
|
146
|
+
.replace('\\\\*', '\\x2a')
|
|
147
|
+
.replace('*', '.*?')
|
|
148
|
+
)
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
function readdirWithFileTypes (dir) {
|
|
@@ -149,10 +153,7 @@ function readdirWithFileTypes (dir) {
|
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
function retrievePathFs (base, { path }, subpath) {
|
|
152
|
-
return fsp
|
|
153
|
-
.access(base + '/' + joinPath(path, subpath))
|
|
154
|
-
.then(invariably.true)
|
|
155
|
-
.catch(invariably.false)
|
|
156
|
+
return fsp.access(base + '/' + joinPath(path, subpath)).then(invariably.true, invariably.false)
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
function retrievePathGit (repo, { oid }, filepath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antora/content-aggregator",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-beta.1",
|
|
4
4
|
"description": "Fetches and aggregates content from distributed sources for use in an Antora documentation pipeline.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": "OpenDevise Inc. (https://opendevise.com)",
|
|
@@ -17,16 +17,16 @@
|
|
|
17
17
|
},
|
|
18
18
|
"main": "lib/index.js",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@antora/expand-path-helper": "~
|
|
20
|
+
"@antora/expand-path-helper": "~2.0",
|
|
21
|
+
"@antora/user-require-helper": "~2.0",
|
|
21
22
|
"braces": "~3.0",
|
|
22
23
|
"cache-directory": "~2.0",
|
|
23
|
-
"camelcase-keys": "~
|
|
24
|
+
"camelcase-keys": "~7.0",
|
|
24
25
|
"hpagent": "~0.1.0",
|
|
25
|
-
"isomorphic-git": "
|
|
26
|
+
"isomorphic-git": "~1.10",
|
|
26
27
|
"js-yaml": "~4.1",
|
|
27
|
-
"matcher": "~4.0",
|
|
28
28
|
"multi-progress": "~4.0",
|
|
29
|
-
"picomatch": "~2.
|
|
29
|
+
"picomatch": "~2.3",
|
|
30
30
|
"progress": "~2.0",
|
|
31
31
|
"should-proxy": "~1.0",
|
|
32
32
|
"simple-get": "~4.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"vinyl-fs": "~3.0"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
|
-
"node": ">=
|
|
37
|
+
"node": ">=12.21.0"
|
|
38
38
|
},
|
|
39
39
|
"files": [
|
|
40
40
|
"lib/"
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"static site",
|
|
50
50
|
"web publishing"
|
|
51
51
|
],
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "7c5ef1ea93dd489af533c80a936c736013c41769"
|
|
53
53
|
}
|