Skip to content

Commit

Permalink
BREAKING: Make metadata accessible from Collection array instead of '…
Browse files Browse the repository at this point in the history
….metadata' property
  • Loading branch information
webketje committed Nov 25, 2024
1 parent 5ff031e commit 3462bff
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 25 deletions.
45 changes: 27 additions & 18 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ function sortBy(key, order) {
}
}

/**
* @param {import('metalsmith').File[]} items
* @param {CollectionConfig} config
*/
function Collection(items, { metadata, ...config }) {
const collection = [...items]
Object.assign(collection, metadata)
collection.config = config
collection.constructor = Collection
Object.seal(collection)
return collection
}

const defaultSort = sortBy('path', 'asc')
const defaultFilter = () => true

Expand Down Expand Up @@ -140,11 +153,11 @@ function collections(options) {

debug('Identified %s collections: %s', mappedCollections.length, collectionNames.join())

mappedCollections.forEach((collection) => {
const { pattern, filter, sort, refer, limit } = collection
const name = collection.name
mappedCollections.forEach((collectionConfig) => {
const { pattern, filter, sort, refer, limit } = collectionConfig
const name = collectionConfig.name
const matches = []
debug('Processing collection %s with options %s:', name, collection)
debug('Processing collection %s with options %s:', name, collectionConfig)

// first match by pattern if provided
if (pattern) {
Expand All @@ -159,8 +172,8 @@ function collections(options) {
} else if (typeof data.collection === 'string') {
data.collection = [data.collection]
}
if (!data.collection.includes(collection.name)) {
data.collection = [...data.collection, collection.name]
if (!data.collection.includes(collectionConfig.name)) {
data.collection = [...data.collection, collectionConfig.name]
}
return data
})
Expand All @@ -173,27 +186,24 @@ function collections(options) {
Object.values(files).filter((file) => {
const patternMatched = matches.includes(file)
const isInCollection = Array.isArray(file.collection)
? file.collection.includes(collection.name)
: file.collection === collection.name
? file.collection.includes(collectionConfig.name)
: file.collection === collectionConfig.name
return !patternMatched && isInCollection
})
)

if (Object.prototype.hasOwnProperty.call(metadata, name)) {
debug('Warning: overwriting previously set metadata property %s', name)
}
// apply sort, filter, limit options in this order

let currentCollection = (metadata.collections[name] = matches)

let currentCollection = matches
// safely add to and remove from the sorting context 'path' property
const originalPaths = []
currentCollection.forEach((item) => {
if (item.path) originalPaths.push([item, item.path])
item.path = metalsmith.path(Object.entries(files).find((entry) => entry[1] === item)[0])
})
currentCollection = currentCollection.sort(sort)
currentCollection = metadata.collections[name] = currentCollection.filter(filter).slice(0, limit)

currentCollection = currentCollection.sort(sort).filter(filter).slice(0, limit)

currentCollection.forEach((item) => {
const original = originalPaths.find(([file]) => file === item)
if (original) {
Expand All @@ -203,9 +213,8 @@ function collections(options) {
}
})

if (collection.metadata) {
currentCollection.metadata = collection.metadata
}
metadata.collections[name] = Collection(currentCollection, collectionConfig)

if (refer) {
const lastIndex = currentCollection.length - 1
currentCollection.forEach((file, i) => {
Expand Down
43 changes: 36 additions & 7 deletions test/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -292,38 +292,67 @@ describe('@metalsmith/collections', function () {
})
})

it('should add metadata objects to collections', function (done) {
it('should add metadata objects to collections', function () {
const metalsmith = Metalsmith('test/fixtures/basic')
return metalsmith
.use(
collections({
articles: {
metadata: { name: 'Batman', test: 'Batman' }
}
})
)
.build()
.then(() => {
const m = metalsmith.metadata()
assert.strictEqual(m.collections.articles.test, 'Batman')
})
})

it('should provide access to collection config via collection metadata', function () {
const metalsmith = Metalsmith('test/fixtures/basic')
return metalsmith
.use(collections({ articles: { refer: false }}))
.build()
.then(() => {
const m = metalsmith.metadata()
assert.strictEqual(m.collections.articles.config.limit, Infinity)
assert.strictEqual(m.collections.articles.config.refer, false)
})
})

it('should load collection metadata from a JSON file', function (done) {
const metalsmith = Metalsmith('test/fixtures/metadata')
metalsmith
.use(
collections({
articles: {
metadata: { name: 'Batman' }
metadata: 'metadata.json'
}
})
)
.build(function (err) {
if (err) return done(err)
const m = metalsmith.metadata()
assert.strictEqual('Batman', m.collections.articles.metadata.name)
assert.strictEqual('Batman', m.collections.articles.name)
done()
})
})

it('should load collection metadata from a JSON file', function (done) {
it('should load collection metadata from a YAML file', function (done) {
const metalsmith = Metalsmith('test/fixtures/metadata')
metalsmith
.use(
collections({
articles: {
metadata: 'metadata.json'
metadata: 'metadata.yaml'
}
})
)
.build(function (err) {
if (err) return done(err)
const m = metalsmith.metadata()
assert.strictEqual('Batman', m.collections.articles.metadata.name)
assert.strictEqual('Batman', m.collections.articles.name)
done()
})
})
Expand All @@ -341,7 +370,7 @@ describe('@metalsmith/collections', function () {
.build(function (err) {
if (err) return done(err)
const m = metalsmith.metadata()
assert.strictEqual('Batman', m.collections.articles.metadata.name)
assert.strictEqual('Batman', m.collections.articles.name)
done()
})
})
Expand Down

0 comments on commit 3462bff

Please sign in to comment.