Create Jekyll collections
This commit is contained in:
parent
7c8138c386
commit
328c56fa19
5 changed files with 162 additions and 26 deletions
|
|
@ -41,7 +41,7 @@ program
|
|||
const files = scan.findFilesSync(source);
|
||||
const taggedFiles = await scan.readTags(files);
|
||||
const organisedFiles = await organise.byAlbum(target, taggedFiles);
|
||||
generate.generateReleaseInfo(organisedFiles);
|
||||
await generate.generateReleaseInfo(target, organisedFiles);
|
||||
});
|
||||
|
||||
debug(process.argv);
|
||||
|
|
|
|||
|
|
@ -20,29 +20,71 @@ const collect = (tracks, callback) => {
|
|||
/**
|
||||
* Creates release information for a single album.
|
||||
*/
|
||||
const getAlbumInfo = tracks => ({
|
||||
const getAlbumInfo = (root, tracks) => ({
|
||||
layout: 'album',
|
||||
slug: path.basename(root),
|
||||
name: tracks[0].common.album || '',
|
||||
artists: collect(tracks, t => t.common.artists || t.common.artist),
|
||||
album: collect(tracks, t => t.common.album),
|
||||
bitrate: collect(tracks, t => t.format.bitrate),
|
||||
trackCount: tracks.length,
|
||||
cover: tracks[0].coverUrl || null,
|
||||
tracks,
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Generates a release YAML with data
|
||||
* Generates Jekyll-compatible release data
|
||||
*/
|
||||
generateReleaseInfo: taggedFiles => {
|
||||
generateReleaseInfo: async (root, taggedFiles) => {
|
||||
// Create collections
|
||||
const trackCollectionRoot = path.resolve(root, '_tracks');
|
||||
await fs.ensureDir(trackCollectionRoot);
|
||||
|
||||
const albums = _.groupBy(taggedFiles, file => path.dirname(file.path));
|
||||
_.forEach(albums, (albumTracks, albumRoot) => {
|
||||
const baseName = path.basename(albumRoot);
|
||||
debug(
|
||||
`generating release info for album '${baseName}' with ${
|
||||
albumTracks.length
|
||||
} track(s)`
|
||||
);
|
||||
const releaseInfo = yaml.safeDump(getAlbumInfo(albumTracks));
|
||||
fs.writeFileSync(path.resolve(albumRoot, `${baseName}.yml`), releaseInfo);
|
||||
});
|
||||
const albumsInfo = await Promise.all(
|
||||
_.map(albums, async (tracks, albumRoot) => {
|
||||
const baseName = path.basename(albumRoot);
|
||||
const albumCollectionRoot = path.resolve(root, '_albums');
|
||||
await fs.ensureDir(albumCollectionRoot);
|
||||
debug(
|
||||
`generating release info for album '${baseName}' with ${
|
||||
tracks.length
|
||||
} track(s)`
|
||||
);
|
||||
const albumInfo = getAlbumInfo(albumRoot, tracks);
|
||||
const releaseInfo = `---\n${yaml.safeDump(albumInfo)}---\n`;
|
||||
await fs.writeFile(
|
||||
path.resolve(albumCollectionRoot, `${baseName}.md`),
|
||||
releaseInfo
|
||||
);
|
||||
|
||||
// Write track collection
|
||||
await Promise.all(
|
||||
tracks.map(async track => {
|
||||
const trackInfoPath = path.resolve(
|
||||
trackCollectionRoot,
|
||||
baseName,
|
||||
`${track.slug}.md`
|
||||
);
|
||||
await fs.ensureFile(trackInfoPath);
|
||||
await fs.writeFile(
|
||||
trackInfoPath,
|
||||
`---\n${yaml.safeDump({
|
||||
layout: 'track',
|
||||
...track,
|
||||
})}---\n`
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
return albumInfo;
|
||||
})
|
||||
);
|
||||
|
||||
// Create album data
|
||||
debug(`generating data for ${albumsInfo.length} album(s)`);
|
||||
const albumsInfoPath = path.resolve(root, '_data', 'albums.yml');
|
||||
await fs.ensureFile(albumsInfoPath);
|
||||
await fs.writeFile(albumsInfoPath, yaml.safeDump(albumsInfo));
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,13 +6,27 @@ const debug = require('debug')('publikator:organise');
|
|||
const mime = require('mime-types');
|
||||
const tags = require('./tags');
|
||||
|
||||
const getFolderName = file => file.common.album.replace(/ /g, '_');
|
||||
/**
|
||||
* Given a track file, return the album name.
|
||||
*/
|
||||
const getAlbumName = file => file.common.album.replace(/ /g, '_');
|
||||
|
||||
/**
|
||||
* Given a track file, return the new file name.
|
||||
*/
|
||||
const getFileName = file =>
|
||||
`${file.common.track.no}-${file.common.title}${path.extname(
|
||||
file.path
|
||||
)}`.replace(/ /g, '_');
|
||||
|
||||
/**
|
||||
* Strips the extension from a file name;
|
||||
*/
|
||||
const stripExtension = fileName => {
|
||||
const i = fileName.lastIndexOf('.');
|
||||
return fileName.substr(0, i);
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts the cover art and saves it to a file with the same name.
|
||||
*/
|
||||
|
|
@ -43,6 +57,7 @@ module.exports = {
|
|||
* Returns `taggedFiles` with the paths changed to the new paths.
|
||||
*/
|
||||
byAlbum: async (root, taggedFiles) => {
|
||||
const assetRoot = path.resolve(root, 'assets', 'albums');
|
||||
const files = taggedFiles.filter(file =>
|
||||
tags.hasTags(file, [
|
||||
'common.artists',
|
||||
|
|
@ -53,36 +68,38 @@ module.exports = {
|
|||
);
|
||||
|
||||
debug(`grouping tracks by album`);
|
||||
const folders = _.uniq(files.map(file => getFolderName(file)));
|
||||
const folders = _.uniq(files.map(file => getAlbumName(file)));
|
||||
debug(`found ${folders.length} album(s)`);
|
||||
debug(folders);
|
||||
|
||||
debug(`creating album directories`);
|
||||
await Promise.all(
|
||||
folders.map(album => fs.ensureDir(path.resolve(root, sanitize(album))))
|
||||
folders.map(album =>
|
||||
fs.ensureDir(path.resolve(assetRoot, sanitize(album)))
|
||||
)
|
||||
);
|
||||
|
||||
debug(`copying tracks & extracting covers`);
|
||||
return Promise.all(
|
||||
files.map(async file => {
|
||||
const folderName = getFolderName(file);
|
||||
const folderName = getAlbumName(file);
|
||||
const fileName = getFileName(file);
|
||||
const newPath = path.resolve(root, folderName, fileName);
|
||||
const newPath = path.resolve(assetRoot, folderName, fileName);
|
||||
await fs.copyFile(file.path, newPath);
|
||||
const coverPath = await extractCoverArt(newPath);
|
||||
return _.assign(
|
||||
{},
|
||||
{
|
||||
path: newPath,
|
||||
relativePath: `${folderName}/${fileName}`,
|
||||
folderName,
|
||||
fileName,
|
||||
url: `/assets/albums/${folderName}/${fileName}`,
|
||||
slug: stripExtension(fileName),
|
||||
},
|
||||
coverPath
|
||||
? {
|
||||
coverPath,
|
||||
relativeCoverPath: `${folderName}/${path.basename(coverPath)}`,
|
||||
coverFileName: path.basename(coverPath),
|
||||
cover: `/assets/albums/${folderName}/${path.basename(
|
||||
coverPath
|
||||
)}`,
|
||||
}
|
||||
: {},
|
||||
_.omit(file, 'path')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue