diff --git a/README.md b/README.md
index 4a3d0f2..f6f53de 100644
--- a/README.md
+++ b/README.md
@@ -286,6 +286,12 @@ const default_options = {
count: 20,
+ // optional sorting function for the entries.
+ // Gets the array entries as the input, expects the sorted array
+ // as its output.
+ // e.g.: sort: entries => _.reverse( _.sortBy( entries, 'date' ) ),
+ sort: entries => entries,
+
// ---------------------------------------------------------------------------
// supported - use in config as needed
diff --git a/index.js b/index.js
index 99d1845..aa16b14 100644
--- a/index.js
+++ b/index.js
@@ -36,26 +36,26 @@ const PLUGIN = {
*/
PLUGIN.get_options_defaults = ( context ) =>
{
-
+
const {
title,
description
} = context.getSiteData ? context.getSiteData() : context;
// ---------------------------------------------------------------------------
-
+
// Feed class options
// @see: https://github.com/jpmonette/feed#example
-
+
const feed_options = {
-
+
title,
description,
generator: PLUGIN.homepage,
// -------------------------------------------------------------------------
-
- // the following are auto populated in PLUGIN.get_options()
+
+ // the following are auto populated in PLUGIN.get_options()
// if they are not set as options
/*
id,
@@ -64,7 +64,7 @@ PLUGIN.get_options_defaults = ( context ) =>
*/
// -------------------------------------------------------------------------
-
+
// ref:
/*
title: "Feed Title",
@@ -86,30 +86,30 @@ PLUGIN.get_options_defaults = ( context ) =>
link: "https://example.com/johndoe"
}
*/
-
+
};
// ---------------------------------------------------------------------------
-
+
const out = {
-
+
// required; it can also be used as enable/disable
-
+
canonical_base: '',
// -------------------------------------------------------------------------
-
+
// Feed class options
-
+
feed_options,
// -------------------------------------------------------------------------
-
+
// @notes:
// property name is also the name of the FEED package function
-
+
feeds: {
-
+
rss2: {
enable : true,
file_name : 'rss.xml',
@@ -121,7 +121,7 @@ PLUGIN.get_options_defaults = ( context ) =>
},
// -----------------------------------------------------------------------
-
+
atom1: {
enable : true,
file_name : 'feed.atom',
@@ -133,7 +133,7 @@ PLUGIN.get_options_defaults = ( context ) =>
},
// -----------------------------------------------------------------------
-
+
json1: {
enable : true,
file_name : 'feed.json',
@@ -143,23 +143,23 @@ PLUGIN.get_options_defaults = ( context ) =>
title : '%%site_title%% JSON Feed',
}
},
-
+
},
// -------------------------------------------------------------------------
-
+
// order of what gets the highest priority:
//
// 1. frontmatter
// 2. page excerpt
// 3. content markdown paragraph
// 4. content regular html
-
+
description_sources: [
-
+
'frontmatter',
'excerpt',
-
+
// markdown paragraph regex
// @todo: needs work
//
@@ -167,78 +167,84 @@ PLUGIN.get_options_defaults = ( context ) =>
//
// this excludes blockquotes using `(?!^>)`
///^((?:(?!^#)(?!^\-|\+)(?!^[0-9]+\.)(?!^!\[.*?\]\((.*?)\))(?!^>)(?!^\[\[.*?\]\])(?!^\{\{.*?\}\})[^\n]|\n(?! *\n))+)(?:\n *)+\n/gim,
-
+
// html paragraph regex
/
(.*?)<\/p>/i,
// -----------------------------------------------------------------------
-
+
// @notes: setting as array require escaping `\`
-
+
//['^((?:(?!^#)(?!^\-|\+)(?!^[0-9]+\.)(?!^\[\[.*?\]\])(?!^\{\{.*?\}\})[^\n]|\n(?! *\n))+)(?:\n *)+\n', 'gim'],
//['
(.*?)<\/p>', 'i'],
-
+
],
// -------------------------------------------------------------------------
-
+
// @consider description max words/char
// -------------------------------------------------------------------------
-
+
// order of what gets the highest priority:
//
// 1. frontmatter
// 2. content markdown image such as ``
// 3. content regular html img
-
+
image_sources: [
-
+
'frontmatter',
-
+
/!\[.*?\]\((.*?)\)/i, // markdown image regex
/ _.reverse( _.sortBy( entries, 'date' ) ),
+ sort: entries => entries, // defaults to just returning it as it is
+
// -------------------------------------------------------------------------
-
+
// supported - use in config as needed
-
+
// category
// contributor
-
+
};
// ---------------------------------------------------------------------------
-
+
return out;
-
+
};
// PLUGIN.get_options_defaults()
@@ -249,7 +255,7 @@ PLUGIN.get_options_defaults = ( context ) =>
*/
PLUGIN.get_options = ( plugin_options, context ) =>
{
-
+
if ( _.isEmpty( PLUGIN.options ) )
{
PLUGIN.options = _.defaultsDeep(
@@ -258,30 +264,30 @@ PLUGIN.get_options = ( plugin_options, context ) =>
);
// -------------------------------------------------------------------------
-
+
// default link and id
-
+
if ( ! PLUGIN.options.feed_options.hasOwnProperty('link') )
{
PLUGIN.options.feed_options.link = plugin_options.canonical_base;
}
-
+
if ( ! PLUGIN.options.feed_options.hasOwnProperty('id') )
{
PLUGIN.options.feed_options.id = plugin_options.canonical_base;
}
// -------------------------------------------------------------------------
-
+
// default feedLinks
-
+
if ( ! PLUGIN.options.feed_options.hasOwnProperty('feedLinks')
&& ! _.isEmpty( PLUGIN.options.feeds ) )
{
PLUGIN.options.feed_options.feedLinks = {};
-
+
const feeds = PLUGIN.options.feeds || {};
-
+
for ( let key of Object.keys( feeds ) )
{
if ( ! PLUGIN.allowed_feed_types.includes( key ) )
@@ -290,39 +296,39 @@ PLUGIN.get_options = ( plugin_options, context ) =>
}
// ---------------------------------------------------------------------
-
+
const url = PLUGIN.get_feed_url( feeds[ key ] );
-
+
if ( ! url )
{
continue;
}
// ---------------------------------------------------------------------
-
+
key = key.replace(/[0-9]/g, ''); // remove numbers from key;
-
+
PLUGIN.options.feed_options.feedLinks[ key ] = url;
}
}
// -------------------------------------------------------------------------
-
+
// internal - used in other files/classes
-
+
PLUGIN.options._internal = {
name : PLUGIN.name,
homepage : PLUGIN.homepage,
key : PLUGIN.key,
allowed_feed_types: PLUGIN.allowed_feed_types,
};
-
+
}
// ---------------------------------------------------------------------------
-
+
return PLUGIN.options;
-
+
};
// PLUGIN.get_options()
@@ -333,15 +339,15 @@ PLUGIN.get_options = ( plugin_options, context ) =>
*/
PLUGIN.good_to_go = ( plugin_options, context ) =>
{
-
+
const options = PLUGIN.get_options( plugin_options, context );
// ---------------------------------------------------------------------------
-
+
return ( options.canonical_base
&& ! _.isEmpty( options.feeds )
&& ! _.isEmpty( PLUGIN.pages ) );
-
+
};
// PLUGIN.good_to_go()
@@ -352,12 +358,12 @@ PLUGIN.good_to_go = ( plugin_options, context ) =>
*/
PLUGIN.get_feed_url = feed =>
{
-
+
if ( feed.enable && feed.file_name )
{
return URL.resolve( PLUGIN.options.canonical_base, feed.file_name );
}
-
+
};
// PLUGIN.get_feed_url()
@@ -389,18 +395,18 @@ PLUGIN.is_page_type_post = frontmatter => ( 'post' === PLUGIN.get_page_type( fro
*/
PLUGIN.is_feed_page = ( page ) =>
{
-
+
const { frontmatter, path } = page;
// ---------------------------------------------------------------------------
-
+
if ( ! _.isEmpty( frontmatter ) )
{
// use `frontmatter.feed.enable` to exclude a particular page/post
// bailout if it is set to false
-
+
const page_feed_settings = PLUGIN.get_page_feed_settings( frontmatter );
-
+
/*
if ( page_feed_settings.hasOwnProperty('enable')
&& ! page_feed_settings.enable )
@@ -408,19 +414,19 @@ PLUGIN.is_feed_page = ( page ) =>
return false;
}
*/
-
+
// @notes:
- // as opposed to the above way of bailing out if set to false
- // the following means that any page that has `frontmatter.feed.enable`
+ // as opposed to the above way of bailing out if set to false
+ // the following means that any page that has `frontmatter.feed.enable`
// set to true will be added
-
+
if ( page_feed_settings.hasOwnProperty('enable') )
{
return ( page_feed_settings.enable );
}
// -------------------------------------------------------------------------
-
+
if ( PLUGIN.is_page_type_post( frontmatter ) )
{
return true;
@@ -428,9 +434,9 @@ PLUGIN.is_feed_page = ( page ) =>
}
// ---------------------------------------------------------------------------
-
+
const directories = PLUGIN.options.posts_directories || [];
-
+
if ( ! _.isEmpty( directories ) )
{
for ( const dir of directories )
@@ -443,9 +449,9 @@ PLUGIN.is_feed_page = ( page ) =>
}
// ---------------------------------------------------------------------------
-
+
return false;
-
+
};
// PLUGIN.is_feed_page()
@@ -456,68 +462,68 @@ module.exports = ( plugin_options, context ) => ({
/**
* used for collecting pages that would be used in feed;
* the reason i'm using this, is that `getSiteData` only gets `page.toJson()`,
- * which only assigns preperties that don't start with '_'
+ * which only assigns preperties that don't start with '_'
* and what i need is the $page._strippedContent to get content for the feed
*/
extendPageData ( $page ) {
-
+
try {
-
+
if ( PLUGIN.get_options( plugin_options, context ).is_feed_page( $page ) )
{
PLUGIN.pages.push( $page );
}
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
},
// ---------------------------------------------------------------------------
-
+
/**
* used for adding head links
*/
async ready() {
-
+
try {
-
+
if ( PLUGIN.good_to_go( plugin_options, context ) )
{
await new LIB.Head( PLUGIN.options, context ).add_links();
}
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
},
// ---------------------------------------------------------------------------
-
+
/**
* used for generating the feed files
*/
async generated ( pagePaths ) {
-
+
try {
-
+
if ( PLUGIN.good_to_go( plugin_options, context ) )
{
await new LIB.Generator( PLUGIN.pages, PLUGIN.options, context ).generate();
}
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
}
-
+
});
diff --git a/lib/Generator.js b/lib/Generator.js
index 35df5ac..1ffd436 100644
--- a/lib/Generator.js
+++ b/lib/Generator.js
@@ -31,180 +31,180 @@ const FEED = require('feed').Feed;
*/
class Generator
{
-
+
/**
* constructor
- *
+ *
* @param {array} pages
* @param {object} options
* @param {object} context
*/
constructor( pages, options = {}, context )
{
-
+
if ( _.isEmpty( pages ) )
{
throw new Error('pages required');
}
-
+
if ( ! options.canonical_base )
{
throw new Error('canonical_base required');
}
// -------------------------------------------------------------------------
-
+
this.pages = pages;
// -------------------------------------------------------------------------
-
+
this.options = options;
this.canonical_base = this.options.canonical_base;
this.feed_options = this.options.feed_options || {};
this.feeds = this.options.feeds || {};
this._internal = this.options._internal || {};
-
+
// -------------------------------------------------------------------------
-
+
this.context = context || {};
-
+
// -------------------------------------------------------------------------
-
+
this.feed_generator = new FEED( this.feed_options );
-
+
}
// constructor()
-
-
-
+
+
+
/**
* @return null
*/
async add_items()
{
-
+
try {
-
- const pages = this.pages.slice( 0, this.options.count );
-
+
+ const pages = this.options.sort(this.pages).slice( 0, this.options.count );
+
LIB.LOG.wait('Adding pages/posts as feed items...');
-
+
const out = [];
-
+
for ( const page of pages )
{
const item = await new LIB.Page( page, this.options, this.context ).get_feed_item();
-
+
if ( ! _.isEmpty( item ) )
{
this.feed_generator.addItem( item );
-
+
out.push( item );
}
}
-
+
// -----------------------------------------------------------------------
-
+
if ( ! _.isEmpty( out ) )
{
LIB.LOG.success(`added ${CHALK.cyan( out.length + ' page(s)' )} as feed item(s)`);
}
-
+
// -----------------------------------------------------------------------
-
+
return out;
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
}
// add_items()
-
-
-
+
+
+
/**
* @return null
*/
add_categories()
{
-
+
try {
-
+
const { category } = this.options;
-
+
if ( category )
{
const categories = Array.isArray( category ) ? category : [ category ];
-
+
categories.map( e => this.feed_generator.addCategory( e ) );
}
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
}
// add_categories()
-
-
-
+
+
+
/**
* @return null
*/
add_contributors()
{
-
+
try {
-
+
const { contributor } = this.options;
-
+
if ( contributor )
{
const contributors = Array.isArray( contributor ) ? contributor : [ contributor ];
-
+
contributors.map( e => this.feed_generator.addContributor( e ) );
}
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
}
// add_contributors()
-
-
-
+
+
+
/**
* @return {array}
*/
async generate_files()
{
-
+
try {
-
+
LIB.LOG.wait('Checking feeds that need to be generated...');
-
+
if ( _.isEmpty( this.feeds ) )
{
LIB.LOG.warn('no feeds set - aborting');
-
+
return;
}
-
+
// -----------------------------------------------------------------------
-
+
const { outDir, cwd } = this.context;
-
+
const feeds = this.feeds;
const out = [];
-
+
for ( const key of Object.keys( feeds ) )
{
if ( ! this._internal.allowed_feed_types.includes( key ) )
@@ -213,71 +213,71 @@ class Generator
}
// ---------------------------------------------------------------------
-
+
const feed = feeds[ key ];
-
+
if ( ! feed.enable || ! feed.file_name )
{
continue;
}
// ---------------------------------------------------------------------
-
+
const content = this.feed_generator[ key ]();
const file = PATH.resolve( outDir, feed.file_name );
const relative = PATH.relative( cwd, file );
-
+
await FSE.outputFile( file, content );
-
+
LIB.LOG.success(`${key} feed file generated and saved to ${CHALK.cyan( relative )}`);
// ---------------------------------------------------------------------
-
+
out.push( file );
}
-
+
// -----------------------------------------------------------------------
-
+
return out;
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
}
// generate_files()
-
-
-
+
+
+
/**
* @return {array}
*/
async generate()
{
-
+
try {
-
+
await this.add_items();
-
+
this.add_categories();
-
+
this.add_contributors();
-
+
const files = await this.generate_files();
-
+
return files;
-
+
} catch ( err ) {
-
+
LIB.LOG.error( err.message );
-
+
}
-
+
}
// generate()
-
+
}
// class Generator