Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Eleventy detection #14

Merged
merged 5 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 23 additions & 24 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@
},
"author": "CloudCannon <[email protected]>",
"devDependencies": {
"@cloudcannon/configuration-types": "0.0.11",
"@cloudcannon/configuration-types": "0.0.12",
"@types/he": "^1.2.3",
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.5.0",
"@types/node": "^22.5.2",
"ava": "^6.1.3",
"c8": "^10.1.2",
"eslint": "^9.9.0",
"eslint": "^9.9.1",
"prettier": "^3.3.3",
"typescript": "^5.5.4"
},
Expand Down
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',
};
7 changes: 5 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { guessSsg, ssgs } from './ssgs/ssgs.js';
import { findBasePath } from './collections.js';
import { normalisePath } from './utility.js';

export { ssgs } from './ssgs/ssgs.js';

Expand Down Expand Up @@ -70,11 +71,13 @@ export async function generateConfiguration(filePaths, options) {
* @returns {Promise<import('./types').BuildCommands>}
*/
export async function generateBuildCommands(filePaths, options) {
let source = options?.config?.source ? normalisePath(options.config.source) : undefined;

const ssg = options?.buildConfig?.ssg
? ssgs[options.buildConfig.ssg]
: guessSsg(filterPaths(filePaths, options?.config?.source));
: guessSsg(filterPaths(filePaths, source));

const source = options?.config?.source ?? ssg.getSource(filePaths);
source = source ?? ssg.getSource(filePaths);
filePaths = filterPaths(filePaths, source);

const files = ssg.groupFiles(filePaths);
Expand Down
59 changes: 59 additions & 0 deletions src/ssgs/eleventy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { joinPaths, stripBottomPath } from '../utility.js';
import Ssg from './ssg.js';

export default class Eleventy extends Ssg {
Expand Down Expand Up @@ -28,6 +29,64 @@ export default class Eleventy extends Ssg {
return super.contentExtensions().concat(['.html']);
}

partialFolders() {
return super.partialFolders().concat(['_includes/']);
}

ignoredFolders() {
return super.ignoredFolders().concat([
'_site/', // build output
]);
}

conventionalPathsInSource = ['_includes/', '_data/'];

/**
* Attempts to find the most likely source folder.
*
* @param filePaths {string[]} List of input file paths.
* @returns {string | undefined}
*/
getSource(filePaths) {
const source = super.getSource(filePaths);
if (source !== undefined) {
return source;
}

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

/**
* Generates a collection config entry.
*
* @param key {string}
* @param path {string}
* @param options {{ basePath?: string; }=}
* @returns {import('@cloudcannon/configuration-types').CollectionConfig}
*/
generateCollectionConfig(key, path, options) {
const collectionConfig = super.generateCollectionConfig(key, path, options);
collectionConfig.output = !(path === '_data' || path.endsWith('/_data'));
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
73 changes: 24 additions & 49 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,51 +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;
}

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 Expand Up @@ -196,14 +170,15 @@ export default class Hugo extends Ssg {
headingTags.forEach((tag) => {
attribute_elements[tag] = !!parser?.attribute?.title ? 'space right' : 'none';
});

/** @type {(keyof HTMLElementTagNameMap)[]} */
const otherTags = ['blockquote', 'hr', 'ol', 'ul', 'p', 'table'];
otherTags.forEach((tag) => {
attribute_elements[tag] = !!parser?.attribute?.block ? 'below' : 'none';
});

const imgAttrsAllowed = !!parser?.attribute?.block && parser?.wrapStandAloneImageWithinParagraph === false;
const imgAttrsAllowed =
!!parser?.attribute?.block && parser?.wrapStandAloneImageWithinParagraph === false;
attribute_elements.img = imgAttrsAllowed ? 'below' : 'none';

options.attribute_elements = attribute_elements;
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
Loading
Loading