New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@cloudcannon/reader

Package Overview
Dependencies
Maintainers
6
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cloudcannon/reader - npm Package Compare versions

Comparing version 0.0.5 to 0.1.0-0

src/util/logger.js

7

package.json
{
"name": "@cloudcannon/reader",
"type": "module",
"version": "0.0.5",
"version": "0.1.0-0",
"description": "Parses config, files and folder structures to create a JSON file with information about sites made with any static site generator.",

@@ -25,3 +25,4 @@ "keywords": [

"lint": "eslint src",
"release": "npx np"
"release:latest": "npx np",
"release:next": "npx np --tag=next"
},

@@ -47,2 +48,3 @@ "bin": {

"@sindresorhus/slugify": "^2.1.0",
"chalk": "^4.1.2",
"cosmiconfig": "^7.0.1",

@@ -54,2 +56,3 @@ "fdir": "^5.1.0",

"papaparse": "^5.3.1",
"picomatch": "^2.3.0",
"properties": "^1.2.1",

@@ -56,0 +59,0 @@ "toml": "^3.0.0"

@@ -31,2 +31,4 @@ # Reader

To print usage details:
```bash

@@ -39,4 +41,6 @@ $ cloudcannon-reader --help

Options
--version Print the current version
--config, -c Use a specific configuration file
--output, -o Write to a different location than .
--quiet, -q Disable logging

@@ -83,2 +87,5 @@ Examples

// Tells CloudCannon this collection produces output files
output: true
// CloudCannon collection-level configuration

@@ -100,4 +107,21 @@ name: 'Personnel',

return `/posts/${year}/${slug}/`;
}
},
// Tells CloudCannon this collection produces output files
output: true
},
pages: {
// Tells CloudCannon to navigate to this path for this collection
path: '',
// Reads the contents of each file for this pattern (takes priority over path)
glob: ['**/*.md', './src/pages/*.html'],
// Tells CloudCannon to only show successfully parsed files for this collection
// Useful for excluding other collections when using '' as path
filter: 'strict',
// Tells CloudCannon this collection produces output files
output: true
},
data: {

@@ -212,2 +236,23 @@ // Reads the contents of each file in this directory

<details>
<summary><code>glob</code> (optional)</summary>
> The `glob` is a string or array of strings containing patterns to filter the files parsed into this collection. Globs are **not** relative to `source`. Patterns are matched with [picomatch](https://github.com/micromatch/picomatch#basic-globbing). If set as an array, files only have to match one glob pattern to be parsed.
>
> ```javascript
> glob: ['**/*.md', '**/*.html'] // All .md and .html files
> ```
>
> ```javascript
> glob: './src/**/*.liquid' // All .liquid files inside the src folder and subfolders
> ```
>
> This is used to find files instead of `path`, but path is still required as a base path for the collection.
>
> - `'./src/*.md'` matches `.md` files in the `src` folder.
> - `'**/*.html'` matches `.html` files in any folder or subfolder.
> - `['**/*.md', './pages/*.html']` matches `.md` files in any folder, or `.html` files in the `pages` folder.
</details>
<details>
<summary><code>url</code> (optional)</summary>

@@ -217,6 +262,22 @@

>
> Functions are are supported with `.js` or `.cjs` files. Given file path, parsed file content and an object with filters as arguments. The return value should be the slash-prefixed URL string.
> Functions are are supported with `.js` or `.cjs` files. Given file path, parsed file content and an object with filters and the `buildUrl` function as arguments. The return value should be the slash-prefixed URL string.
>
> ```javascript
> url: (filePath, content, { filters, buildUrl }) => {
> if (content.permalink) {
> // Returns a lower case permalink front matter field
> return filters.lowercase(content.permalink);
> }
>
> // Falls back to processing a url string
> return buildUrl(filePath, content, '/[slug]/');
> }
> ```
>
> Strings are used as a template to build the URL. There are two types of placeholders available, file and data. Placeholders resulting in empty values are supported. Sequential slashes in URLs are condensed to one.
>
> ```javascript
> url: '/blog/{date|year}/[slug]/'
> ```
>
> File placeholders are always available, and provided by `cloudcannon-reader`:

@@ -235,2 +296,5 @@ >

> - `{tag|slugify|uppercase}` is `tag` from inside the file, slugified, then upper cased.
> - `{date|year}` is `date` from inside the file, with the 4-digit year extracted.
> - `{date|month}` is `date` from inside the file, with the 2-digit month extracted.
> - `{date|day}` is `date` from inside the file, with the 2-digit day extracted.

@@ -243,2 +307,6 @@ </details>

> The `parser` field should state which [Parser](#parsers) you want to use to read the files in this collection.
>
> ```javascript
> parser: 'front-matter'
> ```

@@ -245,0 +313,0 @@ </details>

@@ -0,4 +1,6 @@

import chalk from 'chalk';
import { fdir } from 'fdir';
import { join } from 'path';
import { buildUrl } from '../util/url-builder.js';
import log from '../util/logger.js';
import { parseFile } from '../parsers/parser.js';

@@ -16,25 +18,42 @@

async function readCollectionItem(filePath, collectionConfig, key, source) {
const data = await parseFile(filePath, collectionConfig.parser);
const itemPath = source && filePath.startsWith(source)
? filePath.slice(source.length + 1) // +1 for slash after source
: filePath;
try {
const data = await parseFile(filePath, collectionConfig.parser);
const itemPath = source && filePath.startsWith(source)
? filePath.slice(source.length + 1) // +1 for slash after source
: filePath;
return {
...data,
path: itemPath,
collection: key,
url: buildUrl(itemPath, data, collectionConfig.url)
};
return {
...data,
path: itemPath,
collection: key,
url: buildUrl(itemPath, data, collectionConfig.url)
};
} catch (e) {
log(` ${chalk.bold(filePath)} skipped due to ${chalk.red(e.message)}`);
}
}
async function readCollection(collectionConfig, key, source) {
const filePaths = await new fdir()
const crawler = new fdir()
.withBasePath()
.filter((filePath, isDirectory) => !isDirectory && !filePath.includes('/_defaults.'))
.filter((filePath, isDirectory) => !isDirectory && !filePath.includes('/_defaults.'));
const glob = typeof collectionConfig.glob === 'string'
? [collectionConfig.glob]
: collectionConfig.glob;
if (collectionConfig.glob) {
crawler.glob(glob);
}
const filePaths = await crawler
.crawl(join(source, collectionConfig.path))
.withPromise();
return await Promise.all(filePaths.map(async (filePath) => {
return await readCollectionItem(filePath, collectionConfig, key, source);
}));
return await filePaths.reduce(async (memo, filePath) => {
const collectionItem = await readCollectionItem(filePath, collectionConfig, key, source);
return collectionItem
? [...(await memo), collectionItem]
: await memo;
}, []);
}

@@ -5,2 +5,3 @@ #!/usr/bin/env node

import runner from './runner.js';
import { toggleLogging } from './util/logger.js';

@@ -15,2 +16,3 @@ const cli = meow(`

--output, -o Write to a different location than .
--quiet, -q Disable logging

@@ -30,2 +32,6 @@ Examples

alias: 'o'
},
quiet: {
quiet: 'string',
alias: 'q'
}

@@ -35,3 +41,6 @@ }

runner.run(cli.flags, cli.pkg)
.then(() => console.log('Generated info.json successfully.'));
if (cli.flags.quiet) {
toggleLogging(false);
}
runner.run(cli.flags, cli.pkg);

@@ -45,3 +45,3 @@ import { readFile } from 'fs/promises';

if (!parse) {
throw new Error(`Unsupported parser: ${parser}`);
throw new Error(parser ? `unsupported parser ${parser}` : 'unknown parser');
}

@@ -48,0 +48,0 @@

import { mkdir, writeFile } from 'fs/promises';
import { join } from 'path';
import { join, relative } from 'path';
import { cosmiconfig } from 'cosmiconfig';
import { generateInfo } from './generators/info.js';
import log from './util/logger.js';
import report from './util/reporter.js';
import chalk from 'chalk';

@@ -26,11 +29,18 @@ export default {

if (config) {
console.log(`Using config file: ${config.filepath}`);
const relativeConfigPath = relative(process.cwd(), config.filepath);
log(`⚙️ Using config file at ${chalk.bold(relativeConfigPath)}`);
return config.config || {};
}
} catch (e) {
console.error(e);
if (e.code === 'ENOENT') {
log(`⚠️ ${chalk.red('No config file found at')} ${chalk.red.bold(configPath)}`);
return false;
} else {
log(`⚠️ ${chalk.red('Error reading config file')}`, 'error');
throw e;
}
}
console.log('No config file found.');
return {};
log('⚙️ No config file found, see the instructions at https://github.com/CloudCannon/reader');
return false;
},

@@ -42,11 +52,19 @@

write: async function (info, outputDir) {
write: async function (info, outputDir, outputPath) {
await mkdir(outputDir, { recursive: true });
await writeFile(join(outputDir, 'info.json'), JSON.stringify(info, null, '\t'));
await writeFile(outputPath, JSON.stringify(info, null, '\t'));
},
run: async function (flags, pkg) {
const config = await this.readConfig(flags?.config) || {};
log(`⭐️ Starting ${chalk.blue('cloudcannon-reader')}`);
const config = await this.readConfig(flags?.config);
if (config === false) {
return;
}
config.output = flags?.output || config.output;
const outputDir = join('.', config.output || '', '_cloudcannon');
const outputPath = join(outputDir, 'info.json');
let info;

@@ -57,3 +75,3 @@

} catch (e) {
e.message = `Failed to generate info: ${e.message}`;
log(`⚠️ ${chalk.red('Failed to generate')} ${chalk.red.bold(outputPath)}`, 'error');
throw e;

@@ -63,6 +81,7 @@ }

try {
const outputDir = join('.', config.output || '', '_cloudcannon');
await this.write(info, outputDir);
await this.write(info, outputDir, outputPath);
report(info);
log(`🏁 Generated ${chalk.bold(outputPath)} ${chalk.green('successfully')}`);
} catch (e) {
e.message = `Failed to write info: ${e.message}`;
log(`⚠️ ${chalk.red('Failed to write')} ${chalk.red.bold(outputPath)}`, 'error');
throw e;

@@ -69,0 +88,0 @@ }

@@ -7,3 +7,12 @@ import { parse } from 'path';

lowercase: (value) => value?.toLowerCase?.(),
slugify
slugify,
year: (value) => value?.getFullYear?.(),
month: (value) => {
const month = value?.getMonth?.();
return month === undefined ? month : ('0' + (month + 1)).slice(-2);
},
day: (value) => {
const day = value?.getDate?.();
return day === undefined ? day : ('0' + day).slice(-2);
}
};

@@ -40,3 +49,3 @@

if (typeof urlTemplate === 'function') {
return urlTemplate(filePath, data, { filters });
return urlTemplate(filePath, data, { filters, buildUrl });
}

@@ -43,0 +52,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc