Skip to content

Commit

Permalink
Merge pull request #2 from CloudCannon/feat/move-collections-config
Browse files Browse the repository at this point in the history
Get collections config per SSG
  • Loading branch information
rphillips-cc authored Jul 29, 2024
2 parents 9285d1a + bda0109 commit 45a5399
Show file tree
Hide file tree
Showing 11 changed files with 4,028 additions and 3,955 deletions.
7,634 changes: 3,817 additions & 3,817 deletions package-lock.json

Large diffs are not rendered by default.

104 changes: 52 additions & 52 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
{
"name": "@cloudcannon/gadget",
"type": "module",
"version": "0.0.0",
"description": "Inpects a list of files to create configuration for the CloudCannon CMS.",
"keywords": [
"static site generator",
"cloudcannon"
],
"homepage": "https://github.com/CloudCannon/gadget#readme",
"repository": {
"type": "git",
"url": "https://github.com/CloudCannon/gadget.git"
},
"bugs": {
"url": "https://github.com/CloudCannon/gadget/issues",
"email": "[email protected]"
},
"main": "src/index.js",
"types": "dist/index.d.ts",
"files": [
"src/**/*.js",
"src/**/*.d.ts",
"dist/**/*.d.ts"
],
"scripts": {
"build": "tsc --emitDeclarationOnly",
"test": "ava",
"test:watch": "ava --watch --verbose",
"test:coverage": "c8 --all --src src ava",
"lint": "npm run lint:eslint && npm run lint:tsc && npm run lint:format",
"lint:eslint": "eslint src",
"lint:tsc": "tsc --noEmit",
"lint:format": "npx prettier . -c",
"fix:format": "npx prettier . -w"
},
"author": "CloudCannon <[email protected]>",
"devDependencies": {
"@cloudcannon/configuration-types": "^0.0.4",
"@types/node": "^20.14.8",
"ava": "^6.1.3",
"c8": "^10.1.2",
"eslint": "^9.5.0",
"prettier": "^3.3.2",
"typescript": "^5.4.5"
},
"license": "MIT",
"dependencies": {
"@sindresorhus/slugify": "^2.2.1",
"leven": "^4.0.0",
"titleize": "^4.0.0"
}
}
"name": "@cloudcannon/gadget",
"type": "module",
"version": "0.0.0",
"description": "Inpects a list of files to create configuration for the CloudCannon CMS.",
"keywords": [
"static site generator",
"cloudcannon"
],
"homepage": "https://github.com/CloudCannon/gadget#readme",
"repository": {
"type": "git",
"url": "https://github.com/CloudCannon/gadget.git"
},
"bugs": {
"url": "https://github.com/CloudCannon/gadget/issues",
"email": "[email protected]"
},
"main": "src/index.js",
"types": "dist/index.d.ts",
"files": [
"src/**/*.js",
"src/**/*.d.ts",
"dist/**/*.d.ts"
],
"scripts": {
"build": "tsc --emitDeclarationOnly",
"test": "ava",
"test:watch": "ava --watch --verbose",
"test:coverage": "c8 --all --src src ava",
"lint": "npm run lint:eslint && npm run lint:tsc && npm run lint:format",
"lint:eslint": "eslint src",
"lint:tsc": "tsc --noEmit",
"lint:format": "npx prettier . -c",
"fix:format": "npx prettier . -w"
},
"author": "CloudCannon <[email protected]>",
"devDependencies": {
"@cloudcannon/configuration-types": "^0.0.7",
"@types/node": "^20.14.12",
"ava": "^6.1.3",
"c8": "^10.1.2",
"eslint": "^9.7.0",
"prettier": "^3.3.3",
"typescript": "^5.5.4"
},
"license": "MIT",
"dependencies": {
"@sindresorhus/slugify": "^2.2.1",
"leven": "^4.0.0",
"titleize": "^4.0.0"
}
}
50 changes: 9 additions & 41 deletions src/collections.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { basename, join } from 'path';
import slugify from '@sindresorhus/slugify';
import titleize from 'titleize';
import { findIcon } from './icons.js';
import { join } from 'path';
import { stripTopPath } from './utility.js';

/**
Expand All @@ -23,43 +20,6 @@ export function getCollectionPaths(filePath) {
return paths;
}

/**
* Generates collections config from a set of paths.
*
* @param collectionPaths {{ basePath: string, paths: string[] }}
* @param source {string}
* @returns {import('./types').CollectionsConfig}
*/
export function generateCollectionsConfig(collectionPaths, source) {
/** @type import('./types').CollectionsConfig */
const collectionsConfig = {};
const collectionPath = stripTopPath(collectionPaths.basePath, source);

for (let path of collectionPaths.paths) {
const sourcePath = stripTopPath(path, source);
const key = slugify(sourcePath, { separator: '_' }) || 'pages';
const name = titleize(
basename(sourcePath || key)
.replace(/[_-]/g, ' ')
.trim(),
);

collectionsConfig[key] = {
path: sourcePath,
name,
icon: findIcon(name.toLowerCase()),
};

if (sourcePath === collectionPath) {
collectionsConfig[key].filter = {
base: 'strict',
};
}
}

return collectionsConfig;
}

/**
* Makes collection paths relative to a shared base path, also returns that shared path as source.
*
Expand Down Expand Up @@ -90,6 +50,14 @@ export function processCollectionPaths(collectionPathCounts) {
paths = paths.map((pathKey) => stripTopPath(pathKey, basePath));
}

if (paths.length === 1) {
// If there is one collection, force it to have path.
return {
basePath: '',
paths: [basePath],
};
}

return {
basePath,
paths,
Expand Down
31 changes: 20 additions & 11 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { guessSsg, ssgs } from './ssgs/ssgs.js';
import { last, stripTopPath } from './utility.js';
import {
getCollectionPaths,
generateCollectionsConfig,
processCollectionPaths,
} from './collections.js';
import { getCollectionPaths, processCollectionPaths } from './collections.js';

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

/**
* Provides a summary of a file at this path.
Expand Down Expand Up @@ -63,6 +61,16 @@ function parseFiles(filePaths, ssg) {
return { collectionPathCounts, groups };
}

/**
* Attempts to find the current timezone.
*
* @returns {import('@cloudcannon/configuration-types').Timezone | undefined}
*/
function getTimezone() {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
return /** @type {import('@cloudcannon/configuration-types').Timezone | undefined} */ (timezone);
}

/**
* Generates a baseline CloudCannon configuration based on the file path provided.
*
Expand All @@ -71,26 +79,27 @@ function parseFiles(filePaths, ssg) {
* @returns {Promise<import('@cloudcannon/configuration-types').Configuration>}
*/
export async function generate(filePaths, options) {
const ssgKey = options?.config?.ssg ?? options?.buildConfig?.ssg;
const ssgKey = options?.config?.ssg || options?.buildConfig?.ssg;
const ssg = ssgKey ? ssgs[ssgKey] : guessSsg(filePaths);
const files = parseFiles(filePaths, ssg);
const collectionPaths = processCollectionPaths(files.collectionPathCounts);

const source =
options?.config?.source ??
options?.buildConfig?.source ??
ssg.getSource(files, filePaths, collectionPaths);
options?.config?.source ?? options?.buildConfig?.source ?? ssg.getSource(files, filePaths);

const collectionsConfig =
options?.config?.collections_config ?? generateCollectionsConfig(collectionPaths, source);
options?.config?.collections_config || ssg.generateCollectionsConfig(collectionPaths, source);

return {
ssg: ssg?.key,
source,
collections_config: collectionsConfig,
paths: {
collections: stripTopPath(collectionPaths.basePath, source),
collections: source
? stripTopPath(collectionPaths.basePath, source)
: collectionPaths.basePath,
...options?.config?.paths,
},
timezone: options?.config?.timezone ?? getTimezone(),
};
}
22 changes: 22 additions & 0 deletions src/ssgs/hugo.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,26 @@ export default class Hugo extends Ssg {
'resources/', // cache
]);
}

/**
* Generates a collection config entry.
*
* @param key {string}
* @param path {string}
* @param basePath {string}
* @returns {import('@cloudcannon/configuration-types').CollectionConfig}
*/
generateCollectionConfig(key, path, basePath) {
const collectionConfig = super.generateCollectionConfig(key, path, basePath);

if (path !== basePath) {
collectionConfig.glob =
typeof collectionConfig.glob === 'string'
? [collectionConfig.glob]
: collectionConfig.glob || [];
collectionConfig.glob.push('!_index.md');
}

return collectionConfig;
}
}
23 changes: 19 additions & 4 deletions src/ssgs/jekyll.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class Jekyll extends Ssg {
}

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

ignoredFolders() {
Expand Down Expand Up @@ -62,16 +62,31 @@ export default class Jekyll extends Ssg {
* @param _files {import('../types').ParsedFiles}
* @param filePaths {string[]} List of input file paths.
* @param collectionPaths {{ basePath: string, paths: string[] }}
* @returns {string}
* @returns {string | undefined}
*/
getSource(_files, filePaths, collectionPaths) {
getSource(_files, filePaths) {
const { filePath, conventionPath } = this._findConventionPath(filePaths);

if (filePath && conventionPath) {
const conventionIndex = filePath.indexOf(conventionPath);
return filePath.substring(0, Math.max(0, conventionIndex - 1));
}

return super.getSource(_files, filePaths, collectionPaths);
return super.getSource(_files, filePaths);
}

/**
* Generates a collection config entry.
*
* @param key {string}
* @param path {string}
* @param basePath {string}
* @returns {import('@cloudcannon/configuration-types').CollectionConfig}
*/
generateCollectionConfig(key, path, basePath) {
const collectionConfig = super.generateCollectionConfig(key, path, basePath);
// TODO: read contents of _config.yml to find which collections are output
collectionConfig.output = key !== 'data';
return collectionConfig;
}
}
Loading

0 comments on commit 45a5399

Please sign in to comment.