Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@antora/content-classifier

Package Overview
Dependencies
Maintainers
2
Versions
86
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@antora/content-classifier - npm Package Compare versions

Comparing version 2.3.4 to 3.0.0-alpha.1

lib/mime-types-with-asciidoc.js

37

lib/classify-content.js

@@ -16,16 +16,27 @@ 'use strict'

* @param {Object} aggregate - The raw aggregate of virtual file objects to be classified.
* @param {Object} [siteAsciiDocConfig=undefined] - Site-wide AsciiDoc processor configuration options.
* @param {Object} [siteAsciiDocConfig={}] - Site-wide AsciiDoc processor configuration options.
* @returns {ContentCatalog} A structured catalog of content components and virtual content files.
*/
function classifyContent (playbook, aggregate, siteAsciiDocConfig = undefined) {
// deprecated; remove fallback in Antora 3.x
if (!siteAsciiDocConfig) siteAsciiDocConfig = require('@antora/asciidoc-loader').resolveConfig(playbook)
const contentCatalog = aggregate.reduce((catalog, descriptor) => {
const { name, version, nav, files } = descriptor
delete descriptor.files
descriptor.asciidoc = resolveAsciiDocConfig(siteAsciiDocConfig, descriptor)
files.forEach((file) => allocateSrc(file, name, version, nav) && catalog.addFile(file))
catalog.registerComponentVersion(name, version, descriptor)
return catalog
}, new ContentCatalog(playbook))
function classifyContent (playbook, aggregate, siteAsciiDocConfig = {}) {
const contentCatalog = new ContentCatalog(playbook)
aggregate
.reduce((accum, componentVersionData) => {
const { name, version } = componentVersionData
// drop startPage to defer registration of start page
// drop files since they aren't needed to register component version
const { files, startPage, ...descriptor } = Object.assign({}, componentVersionData, {
asciidoc: resolveAsciiDocConfig(siteAsciiDocConfig, componentVersionData),
})
return new Map(accum).set(
contentCatalog.registerComponentVersion(name, version, descriptor),
componentVersionData
)
}, new Map())
.forEach((componentVersionData, componentVersion) => {
const { name, version } = componentVersion
const { files, nav, startPage } = componentVersionData
delete componentVersionData.files // clean up memory
files.forEach((file) => allocateSrc(file, name, version, nav) && contentCatalog.addFile(file))
contentCatalog.registerComponentVersionStartPage(name, componentVersion, startPage)
})
contentCatalog.registerSiteStartPage(playbook.site.startPage)

@@ -60,3 +71,3 @@ return contentCatalog

file.src.relative = pathSegments.slice(4).join('/')
} else if (file.src.mediaType === 'text/asciidoc') {
} else if (file.src.extname === '.adoc') {
file.src.family = 'page'

@@ -63,0 +74,0 @@ // relative to modules/<module>/pages

'use strict'
const File = require('./file')
const { lookup: resolveMimeType } = require('./mime-types-with-asciidoc')
const parseResourceId = require('./util/parse-resource-id')

@@ -19,43 +20,41 @@ const { posix: path } = require('path')

this[$files] = new Map()
this.htmlUrlExtensionStyle = (playbook.urls || {}).htmlExtensionStyle || 'default'
this.urlRedirectFacility = (playbook.urls || {}).redirectFacility || 'static'
const urls = playbook.urls || {}
this.htmlUrlExtensionStyle = urls.htmlExtensionStyle || 'default'
this.urlRedirectFacility = urls.redirectFacility || 'static'
this.latestVersionUrlSegment = urls.latestVersionSegment
this.latestPrereleaseVersionUrlSegment = urls.latestPrereleaseVersionSegment
if (this.latestVersionUrlSegment == null && this.latestPrereleaseVersionUrlSegment == null) {
this.latestVersionUrlSegmentStrategy = undefined
} else {
this.latestVersionUrlSegmentStrategy = urls.latestVersionSegmentStrategy || 'replace'
if (this.latestVersionUrlSegmentStrategy === 'redirect:from') {
if (!this.latestVersionUrlSegment) this.latestVersionUrlSegment = undefined
if (!this.latestPrereleaseVersionUrlSegment) {
this.latestPrereleaseVersionUrlSegment = undefined
if (!this.latestVersionUrlSegment) this.latestVersionUrlSegmentStrategy = undefined
}
}
}
}
/**
* Registers a new component version with the content catalog. Also registers the component if it does not yet exist.
*
* @param {String} name - The name of the component to which this component version belongs.
* @param {String} version - The version of the component to register.
* @param {Object} [descriptor={}] - The configuration data for the component version.
* @param {Object} [descriptor.asciidoc=undefined] - The AsciiDoc configuration for this component version.
* @param {String} [descriptor.displayVersion=version] - The display version for this component version.
* @param {Boolean|String} [descriptor.prerelease=undefined] - The prerelease flag for this version. If the value
* is a String, it implies true and is appended to the display version, separated if necessary by a space.
* @param {Boolean|String} [descriptor.startPage=undefined] - The page specifier for the start page. The start page
* is only registered if this property is truthy. A String value will be used to resolve a start page within this
* component version. A true value is a special case to tell this method to register the default start page and is
* intended for testing.
* @param {String} [descriptor.title=name] - The title for this component version.
*/
registerComponentVersion (name, version, descriptor = {}) {
const { asciidoc, displayVersion, prerelease, title, startPage: startPageSpec } = descriptor
const { asciidoc, displayVersion, prerelease, startPage: startPageSpec, title } = descriptor
const componentVersion = { displayVersion: displayVersion || version, title: title || name, version }
Object.defineProperty(componentVersion, 'name', { value: name, enumerable: true })
let startPage
let startPageSrc
const indexPageId = { component: name, version, module: 'ROOT', family: 'page', relative: 'index.adoc' }
if (startPageSpec) {
if (
(startPage = this.resolvePage(startPageSpec, indexPageId)) &&
(startPageSrc = startPage.src).component === name &&
startPageSrc.version === version
) {
if ((startPageSrc.module !== 'ROOT' || startPageSrc.relative !== 'index.adoc') && !this.getById(indexPageId)) {
this.addFile({ mediaType: 'text/html', src: inflateSrc(indexPageId, 'alias'), rel: startPage })
}
} else {
console.warn(
`Start page specified for ${version}@${name} ${startPage === false ? 'has invalid syntax' : 'not found'}: ` +
startPageSpec
)
startPage = this.getById(indexPageId)
}
} else {
startPage = this.getById(indexPageId)
}
if (startPage) {
componentVersion.url = startPage.pub.url
} else {
// QUESTION: should we warn if the default start page cannot be found?
componentVersion.url = computePub(
(startPageSrc = inflateSrc(indexPageId)),
computeOut(startPageSrc, startPageSrc.family, this.htmlUrlExtensionStyle),
startPageSrc.family,
this.htmlUrlExtensionStyle
).url
}
if (prerelease) {

@@ -82,3 +81,7 @@ componentVersion.prerelease = prerelease

}
component.latest = componentVersions.find((candidate) => !candidate.prerelease) || componentVersions[0]
if ((component.latest = componentVersions.find((candidate) => !candidate.prerelease))) {
if (componentVersions[0] !== component.latest) component.latestPrerelease = componentVersions[0]
} else {
component.latest = componentVersions[0]
}
} else {

@@ -95,8 +98,2 @@ this[$components].set(

},
// NOTE deprecated; alias latestVersion to latest for backwards compatibility; remove in Antora 3
latestVersion: {
get () {
return this.latest
},
},
title: {

@@ -116,2 +113,5 @@ get () {

}
if (startPageSpec) {
this.registerComponentVersionStartPage(name, componentVersion, startPageSpec === true ? undefined : startPageSpec)
}
return componentVersion

@@ -122,5 +122,5 @@ }

const src = file.src
let family = src.family
const key = generateKey(src)
if (this[$files].has(key)) {
const family = src.family
if (family === 'alias') {

@@ -137,5 +137,22 @@ throw new Error(`Duplicate alias: ${generateResourceSpec(src)}`)

}
if (!File.isVinyl(file)) file = new File(file)
const actingFamily = src.family === 'alias' ? file.rel.src.family : src.family
// NOTE: if the path property is not set, assume the src likely needs to be prepared
// another option is to assume that if the file is not a vinyl object, the src likely needs to be prepared
// a vinyl object is one indication the file was created and prepared by the content aggregator
//if (!src.path) prepareSrc(src)
//if (!File.isVinyl(file)) file = new File(file)
if (!File.isVinyl(file)) {
prepareSrc(src)
file = new File(file)
}
if (family === 'alias') {
src.mediaType = 'text/asciidoc'
file.mediaType = 'text/html'
// NOTE: an alias masquerades as the target file
family = file.rel.src.family
// QUESTION: should we preserve the mediaType property on file if already defined?
} else if (!(file.mediaType = src.mediaType) && !('mediaType' in src)) {
file.mediaType = src.mediaType = resolveMimeType(src.extname) || (family === 'page' ? 'text/asciidoc' : undefined)
}
let publishable
let versionSegment
if (file.out) {

@@ -146,10 +163,12 @@ publishable = true

} else if (
(actingFamily === 'page' || actingFamily === 'image' || actingFamily === 'attachment') &&
!~('/' + src.relative).indexOf('/_')
(family === 'page' || family === 'image' || family === 'attachment') &&
('/' + src.relative).indexOf('/_') < 0
) {
publishable = true
file.out = computeOut(src, actingFamily, this.htmlUrlExtensionStyle)
versionSegment = computeVersionSegment.bind(this)(src.component, src.version)
file.out = computeOut(src, family, versionSegment, this.htmlUrlExtensionStyle)
}
if (!file.pub && (publishable || actingFamily === 'nav')) {
file.pub = computePub(src, file.out, actingFamily, this.htmlUrlExtensionStyle)
if (!file.pub && (publishable || family === 'nav')) {
if (versionSegment == null) versionSegment = computeVersionSegment.bind(this)(src.component, src.version)
file.pub = computePub(src, file.out, family, versionSegment, this.htmlUrlExtensionStyle)
}

@@ -192,24 +211,2 @@ this[$files].set(key, file)

/**
* @deprecated scheduled to be removed in Antora 3
*/
getComponentMap () {
const accum = {}
for (const [name, component] of this[$components]) {
accum[name] = component
}
return accum
}
/**
* @deprecated scheduled to be removed in Antora 3
*/
getComponentMapSortedBy (property) {
const accum = {}
for (const component of this.getComponentsSortedBy(property)) {
accum[component.name] = component
}
return accum
}
getComponents () {

@@ -223,3 +220,3 @@ return [...this[$components].values()]

getAll () {
getFiles () {
return [...this[$files].values()]

@@ -247,2 +244,54 @@ }

registerComponentVersionStartPage (name, componentVersion, startPageSpec = undefined) {
let version = componentVersion.version
if (version == null) {
// QUESTION: should we warn or throw error if component version cannot be found?
if (!(componentVersion = this.getComponentVersion(name, componentVersion))) return
version = componentVersion.version
}
let startPage
let startPageSrc
const indexPageId = { component: name, version, module: 'ROOT', family: 'page', relative: 'index.adoc' }
if (startPageSpec) {
if (
(startPage = this.resolvePage(startPageSpec, indexPageId)) &&
(startPageSrc = startPage.src).component === name &&
startPageSrc.version === version
) {
if ((startPageSrc.module !== 'ROOT' || startPageSrc.relative !== 'index.adoc') && !this.getById(indexPageId)) {
this.addFile({ src: Object.assign({}, indexPageId, { family: 'alias' }), rel: startPage })
}
} else {
console.warn(
`Start page specified for ${version}@${name} ${startPage === false ? 'has invalid syntax' : 'not found'}: ` +
startPageSpec
)
startPage = this.getById(indexPageId)
}
} else {
startPage = this.getById(indexPageId)
}
if (startPage) {
componentVersion.url = startPage.pub.url
} else {
// QUESTION: should we warn if the default start page cannot be found?
const versionSegment = computeVersionSegment.bind(this)(name, version)
componentVersion.url = computePub(
(startPageSrc = prepareSrc(Object.assign({}, indexPageId, { family: 'page' }))),
computeOut(startPageSrc, startPageSrc.family, versionSegment, this.htmlUrlExtensionStyle),
startPageSrc.family,
versionSegment,
this.htmlUrlExtensionStyle
).url
}
const symbolicVersionAlias = createSymbolicVersionAlias(
name,
version,
computeVersionSegment.bind(this)(name, version, 'alias'),
this.latestVersionUrlSegmentStrategy
)
if (symbolicVersionAlias) this.addFile(symbolicVersionAlias)
}
registerSiteStartPage (startPageSpec) {

@@ -252,3 +301,3 @@ if (!startPageSpec) return

if (rel) {
return this.addFile({ mediaType: 'text/html', src: inflateSrc(Object.assign({}, START_ALIAS_ID), 'alias'), rel })
return this.addFile({ src: Object.assign({}, START_ALIAS_ID), rel })
} else if (rel === false) {

@@ -265,5 +314,7 @@ console.warn(`Start page specified for site has invalid syntax: ${startPageSpec}`)

registerPageAlias (spec, target) {
const src = parseResourceId(spec, target.src, 'page', ['page'])
// .adoc file extension will be required on ID spec for page alias starting in Antora 4 (possibly in Antora 3)
const inferredSpec = spec.endsWith('.adoc') ? undefined : spec + '.adoc'
const src = parseResourceId(inferredSpec || spec, target.src, 'page', ['page'])
// QUESTION should we throw an error if alias is invalid?
if (!src) return
if (!src || (inferredSpec && src.relative === '.adoc')) return
const component = this.getComponent(src.component)

@@ -295,7 +346,8 @@ if (component) {

}
// QUESTION should we use src.origin instead of rel with type='link'?
//src.origin = { type: 'link', target }
src.family = 'alias'
// NOTE the redirect producer will populate contents when the redirect facility is 'static'
//const path_ = path.join(targetPage.path.slice(0, -targetPage.src.relative.length), src.relative)
return this.addFile({ mediaType: 'text/html', src: inflateSrc(src, 'alias'), rel: target })
const alias = this.addFile({ src, rel: target })
// NOTE record the first alias this target claims as the preferred one
if (!target.rel) target.rel = alias
return alias
}

@@ -328,18 +380,16 @@

exportToModel () {
return Object.assign(
new (class ContentCatalogProxy {})(),
[
this.findBy,
this.getAll,
this.getById,
this.getComponent,
this.getComponentVersion,
this.getComponents,
this.getComponentsSortedBy,
this.getPages,
this.getSiteStartPage,
this.resolvePage,
this.resolveResource,
].reduce((accum, method) => (accum[method.name] = method.bind(this)) && accum, {})
)
return [
this.findBy,
{ name: 'getAll', bind: (to) => this.getAll.bind(to) },
this.getById,
this.getComponent,
this.getComponentVersion,
this.getComponents,
this.getComponentsSortedBy,
this.getFiles,
this.getPages,
this.getSiteStartPage,
this.resolvePage,
this.resolveResource,
].reduce((proxy, method) => (proxy[method.name] = method.bind(this)) && proxy, new (class ContentCatalogProxy {})())
}

@@ -349,5 +399,5 @@ }

/**
* @deprecated superceded by getAll()
* @deprecated superceded by getFiles(); scheduled to be removed in Antora 4
*/
ContentCatalog.prototype.getFiles = ContentCatalog.prototype.getAll
ContentCatalog.prototype.getAll = ContentCatalog.prototype.getFiles

@@ -359,3 +409,2 @@ function generateKey ({ component, version, module: module_, family, relative }) {

function generateResourceSpec ({ component, version, module: module_, family, relative }, shorthand = true) {
//if (module_ == null && family === 'nav') return `${version}@${component}:nav$${relative}`
return (

@@ -368,24 +417,32 @@ `${version}@${component}:${shorthand && module_ === 'ROOT' ? '' : module_}:` +

function inflateSrc (src, family = 'page', mediaType = 'text/asciidoc') {
const basename = (src.basename = path.basename(src.relative))
const extIdx = basename.lastIndexOf('.')
if (~extIdx) {
src.stem = basename.substr(0, extIdx)
src.extname = basename.substr(extIdx)
} else {
src.stem = basename
src.extname = ''
function prepareSrc (src) {
let { basename, extname, stem } = src
let update
if (basename == null) {
update = true
basename = path.basename(src.relative)
}
src.family = family
src.mediaType = mediaType
return src
if (stem == null) {
update = true
if (extname == null) {
if (~(extname = basename.lastIndexOf('.'))) {
stem = basename.substr(0, extname)
extname = basename.substr(extname)
} else {
stem = basename
extname = ''
}
} else {
stem = basename.substr(0, basename.length - extname.length)
}
} else if (extname == null) {
update = true
extname = basename.substr(stem.length)
}
return update ? Object.assign(src, { basename, extname, stem }) : src
}
function computeOut (src, family, htmlUrlExtensionStyle) {
const component = src.component
const version = src.version === 'master' ? '' : src.version
const module_ = src.module === 'ROOT' ? '' : src.module
let basename = src.basename || path.basename(src.relative)
const stem = src.stem || basename.substr(0, (basename.lastIndexOf('.') + 1 || basename.length + 1) - 1)
function computeOut (src, family, version, htmlUrlExtensionStyle) {
let { component, module: module_, basename, extname, relative, stem } = src
if (module_ === 'ROOT') module_ = ''
let indexifyPathSegment = ''

@@ -398,3 +455,3 @@ let familyPathSegment = ''

indexifyPathSegment = stem
} else if (src.mediaType === 'text/asciidoc') {
} else if (extname === '.adoc') {
basename = stem + '.html'

@@ -409,3 +466,3 @@ }

const modulePath = path.join(component, version, module_)
const dirname = path.join(modulePath, familyPathSegment, path.dirname(src.relative), indexifyPathSegment)
const dirname = path.join(modulePath, familyPathSegment, path.dirname(relative), indexifyPathSegment)
const path_ = path.join(dirname, basename)

@@ -418,8 +475,7 @@ const moduleRootPath = path.relative(dirname, modulePath) || '.'

function computePub (src, out, family, htmlUrlExtensionStyle) {
function computePub (src, out, family, version, htmlUrlExtensionStyle) {
const pub = {}
let url
if (family === 'nav') {
const urlSegments = [src.component]
if (src.version !== 'master') urlSegments.push(src.version)
const urlSegments = version ? [src.component, version] : [src.component]
if (src.module && src.module !== 'ROOT') urlSegments.push(src.module)

@@ -443,2 +499,3 @@ // an artificial URL used for resolving page references in navigation model

url = '/' + out.path
if (family === 'alias' && !src.relative.length) pub.splat = true
}

@@ -456,2 +513,60 @@

function computeVersionSegment (name, version, mode) {
if (mode === 'original') return version === 'master' ? '' : version
const strategy = this.latestVersionUrlSegmentStrategy
// NOTE: special exception; revisit in Antora 3
if (version === 'master') {
if (mode !== 'alias') return ''
if (strategy === 'redirect:to') return
}
if (strategy === 'redirect:to' || strategy === (mode === 'alias' ? 'redirect:from' : 'replace')) {
const component = this.getComponent(name)
const componentVersion = component && this.getComponentVersion(component, version)
if (componentVersion) {
const segment =
componentVersion === component.latest
? this.latestVersionUrlSegment
: componentVersion === component.latestPrerelease
? this.latestPrereleaseVersionUrlSegment
: undefined
return segment == null ? version : segment
}
}
return version
}
function createSymbolicVersionAlias (component, version, symbolicVersionSegment, strategy) {
if (symbolicVersionSegment == null || symbolicVersionSegment === version) return
const family = 'alias'
const baseVersionAliasSrc = { component, module: 'ROOT', family, relative: '', basename: '', stem: '', extname: '' }
const symbolicVersionAliasSrc = Object.assign({}, baseVersionAliasSrc, { version: symbolicVersionSegment })
const symbolicVersionAlias = {
src: symbolicVersionAliasSrc,
pub: computePub(
symbolicVersionAliasSrc,
computeOut(symbolicVersionAliasSrc, family, symbolicVersionSegment),
family
),
}
const originalVersionAliasSrc = Object.assign({}, baseVersionAliasSrc, { version })
const originalVersionSegment = computeVersionSegment(component, version, 'original')
const originalVersionAlias = {
src: originalVersionAliasSrc,
pub: computePub(
originalVersionAliasSrc,
computeOut(originalVersionAliasSrc, family, originalVersionSegment),
family
),
}
if (strategy === 'redirect:to') {
originalVersionAlias.out = undefined
originalVersionAlias.rel = symbolicVersionAlias
return originalVersionAlias
} else {
symbolicVersionAlias.out = undefined
symbolicVersionAlias.rel = originalVersionAlias
return symbolicVersionAlias
}
}
function getFileLocation ({ path: path_, src: { abspath, origin } }) {

@@ -458,0 +573,0 @@ return (

@@ -56,4 +56,2 @@ 'use strict'

if (family === 'page' && relative.indexOf('.') < 0) relative += '.adoc'
if (~relative.indexOf('/')) {

@@ -60,0 +58,0 @@ relative = relative

{
"name": "@antora/content-classifier",
"version": "2.3.4",
"version": "3.0.0-alpha.1",
"description": "Organizes aggregated content into a virtual file catalog for use in an Antora documentation pipeline.",

@@ -19,10 +19,7 @@ "license": "MPL-2.0",

"dependencies": {
"@antora/asciidoc-loader": "2.3.4",
"mime-types": "~2.1",
"vinyl": "~2.2"
},
"devDependencies": {
"@antora/content-aggregator": "2.3.4"
},
"engines": {
"node": ">=8.11.0"
"node": ">=10.17.0"
},

@@ -40,3 +37,3 @@ "files": [

],
"gitHead": "5a40191c970ece6baecbd1a3a7a599d7161351a9"
"gitHead": "337ff6d2ed11e1f4d0a8ef993ddc8eaac7a73e9f"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc