Skip to content

Commit

Permalink
Exclude data/non-content folder when choosing top level content folders
Browse files Browse the repository at this point in the history
  • Loading branch information
rphillips-cc committed Sep 3, 2024
1 parent fe9a770 commit 132f140
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 224 deletions.
30 changes: 15 additions & 15 deletions src/defaults.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
/** @type {import('@cloudcannon/configuration-types').MarkdownAttributeElementOptions} */
export const commonmarkAttributeElementOptions = {
inline: 'none',
block: 'space right',
img: 'right',
ul: 'below',
ol: 'below',
li: 'space right',
table: 'newline below',
blockquote: 'below',
}
inline: 'none',
block: 'space right',
img: 'right',
ul: 'below',
ol: 'below',
li: 'space right',
table: 'newline below',
blockquote: 'below',
};

/** @type {import('@cloudcannon/configuration-types').MarkdownAttributeElementOptions} */
export const kramdownAttributeElementOptions = {
inline: 'right',
block: 'below',
tr: 'none',
td: 'none',
li: 'right-of-prefix',
}
inline: 'right',
block: 'below',
tr: 'none',
td: 'none',
li: 'right-of-prefix',
};
18 changes: 16 additions & 2 deletions src/ssgs/eleventy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { normalisePath, popPathSection } from '../utility.js';
import { joinPaths, stripBottomPath } from '../utility.js';
import Ssg from './ssg.js';

export default class Eleventy extends Ssg {
Expand Down Expand Up @@ -55,7 +55,7 @@ export default class Eleventy extends Ssg {

const configFilePath = filePaths.find(this.isConfigPath.bind(this));
if (configFilePath) {
return normalisePath(popPathSection(configFilePath)) || undefined;
return stripBottomPath(configFilePath) || undefined;
}
}

Expand All @@ -73,6 +73,20 @@ export default class Eleventy extends Ssg {
return collectionConfig;
}

/**
* Filters out collection paths that are collections, but exist in isolated locations.
* Used when a data folder (or similar) is causing all collections to group under one
* `collections_config` entry.
*
* @param collectionPaths {string[]}
* @param basePath {string}
* @returns {string[]}
*/
filterContentCollectionPaths(collectionPaths, basePath) {
const dataPath = joinPaths([basePath, '_data']);
return collectionPaths.filter((path) => path !== dataPath && !path.startsWith(`${dataPath}/`));
}

/**
* @param _config {Record<string, any>}
* @returns {import('@cloudcannon/configuration-types').MarkdownSettings}
Expand Down
66 changes: 21 additions & 45 deletions src/ssgs/hugo.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { findBasePath } from '../collections.js';
import { decodeEntity, joinPaths, stripTopPath } from '../utility.js';
import { decodeEntity, joinPaths } from '../utility.js';
import Ssg from './ssg.js';

export default class Hugo extends Ssg {
Expand Down Expand Up @@ -83,6 +83,20 @@ export default class Hugo extends Ssg {
return collectionConfig;
}

/**
* Filters out collection paths that are collections, but exist in isolated locations.
* Used when a data folder (or similar) is causing all collections to group under one
* `collections_config` entry.
*
* @param collectionPaths {string[]}
* @param basePath {string}
* @returns {string[]}
*/
filterContentCollectionPaths(collectionPaths, basePath) {
const dataPath = joinPaths([basePath, 'data']);
return collectionPaths.filter((path) => path !== dataPath && !path.startsWith(`${dataPath}/`));
}

/**
* Generates collections config from a set of paths.
*
Expand All @@ -91,10 +105,6 @@ export default class Hugo extends Ssg {
* @returns {import('../types').CollectionsConfig}
*/
generateCollectionsConfig(collectionPaths, options) {
/** @type {import('../types').CollectionsConfig} */
const collectionsConfig = {};
let basePath = options.basePath;

const collectionPathsOutsideExampleSite = collectionPaths.filter(
(path) => !path.includes('exampleSite/'),
);
Expand All @@ -103,49 +113,15 @@ export default class Hugo extends Ssg {
collectionPathsOutsideExampleSite.length &&
collectionPathsOutsideExampleSite.length !== collectionPaths.length;

// Exclude collections found inside the exampleSite folder, unless they are the only collections
if (hasNonExampleSiteCollections) {
basePath = findBasePath(collectionPathsOutsideExampleSite);
collectionPaths = collectionPathsOutsideExampleSite;
}

const dataPath = joinPaths([basePath, 'data']);
const collectionPathsOutsideData = collectionPaths.filter((path) => !path.startsWith(dataPath));
const hasDataCollection =
collectionPathsOutsideData.length &&
collectionPathsOutsideData.length !== collectionPaths.length;

// Reprocess basePath to exclude the data folder
if (hasDataCollection) {
basePath = findBasePath(collectionPathsOutsideData);
}

basePath = stripTopPath(basePath, options.source);

const sortedPaths = collectionPaths.sort((a, b) => a.length - b.length);
/** @type {string[]} */
const seenPaths = [];

for (const fullPath of sortedPaths) {
const path = stripTopPath(fullPath, options.source);
const pathInBasePath = stripTopPath(path, basePath);

if (
!path.startsWith(dataPath) &&
seenPaths.some((seenPath) => pathInBasePath.startsWith(seenPath))
) {
// Skip collection if not data, or a top-level content collection (i.e. seen before)
continue;
} else if (pathInBasePath) {
seenPaths.push(pathInBasePath + '/');
}

const key = this.generateCollectionsConfigKey(pathInBasePath, collectionsConfig);

collectionsConfig[key] = this.generateCollectionConfig(key, path, { basePath });
// Exclude collections found inside the exampleSite folder, unless they are the only collections
return super.generateCollectionsConfig(collectionPathsOutsideExampleSite, {
...options,
basePath: findBasePath(collectionPathsOutsideExampleSite),
});
}

return collectionsConfig;
return super.generateCollectionsConfig(collectionPaths, options);
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/ssgs/jekyll.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ export default class Jekyll extends Ssg {

options.attributes = true;
options.attribute_elements = kramdownAttributeElementOptions;

} else if (config) {
const commonmarkConfig = config?.['commonmark'] || {};

Expand Down
48 changes: 34 additions & 14 deletions src/ssgs/ssg.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import slugify from '@sindresorhus/slugify';
import titleize from 'titleize';
import { findIcon } from '../icons.js';
import { joinPaths, last, parseDataFile, stripTopPath } from '../utility.js';
import { getCollectionPaths } from '../collections.js';
import { findBasePath, getCollectionPaths } from '../collections.js';

export default class Ssg {
/** @type {import('@cloudcannon/configuration-types').SsgKey} */
Expand Down Expand Up @@ -380,6 +380,19 @@ export default class Ssg {
return key;
}

/**
* Filters out collection paths that are collections, but exist in isolated locations.
* Used when a data folder (or similar) is causing all collections to group under one
* `collections_config` entry.
*
* @param collectionPaths {string[]}
* @param _basePath {string}
* @returns {string[]}
*/
filterContentCollectionPaths(collectionPaths, _basePath) {
return collectionPaths;
}

/**
* Generates collections config from a set of paths.
*
Expand All @@ -388,28 +401,35 @@ export default class Ssg {
* @returns {import('../types').CollectionsConfig}
*/
generateCollectionsConfig(collectionPaths, options) {
/** @type {import('../types').CollectionsConfig} */
const collectionsConfig = {};
const basePath = options.source
? stripTopPath(options.basePath, options.source)
: options.basePath;
const contentCollectionPaths = this.filterContentCollectionPaths(
collectionPaths,
options.basePath,
);

const hasNonContentCollection =
collectionPaths.length && collectionPaths.length !== contentCollectionPaths.length;

const basePath = stripTopPath(
hasNonContentCollection ? findBasePath(contentCollectionPaths) : options.basePath,
options.source,
);

const sortedPaths = collectionPaths.sort((a, b) => a.length - b.length);
/** @type {string[]} */
const seenPaths = [];
const seenPaths = /** @type {string[]} */ ([]);
const collectionsConfig = /** @type {import('../types').CollectionsConfig} */ ({});

for (const fullPath of sortedPaths) {
const path = stripTopPath(fullPath, options.source);
const pathInBasePath = stripTopPath(path, basePath);

if (seenPaths.some((seenPath) => path.startsWith(seenPath))) {
// Skip collection if parent path seen before
if (seenPaths.some((seenPath) => pathInBasePath.startsWith(seenPath))) {
// Skip collection if higher level path seen before
continue;
} else if (path) {
// add to seen paths if not the root folder
seenPaths.push(path + '/');
} else if (pathInBasePath) {
seenPaths.push(pathInBasePath + '/');
}

const key = this.generateCollectionsConfigKey(path, collectionsConfig);
const key = this.generateCollectionsConfigKey(pathInBasePath, collectionsConfig);
collectionsConfig[key] = this.generateCollectionConfig(key, path, { basePath });
}

Expand Down
4 changes: 2 additions & 2 deletions src/utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ export function stripTopPath(path, stripPath) {
* @param path {string}
* @returns {string}
*/
export function popPathSection(path) {
export function stripBottomPath(path) {
const index = path.lastIndexOf('/');
return index > 0 ? path.substring(path.lastIndexOf('/')) : '';
return index > 0 ? path.substring(0, path.lastIndexOf('/')) : '';
}

/**
Expand Down
Loading

0 comments on commit 132f140

Please sign in to comment.