Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

contentful-hugo

Package Overview
Dependencies
Maintainers
1
Versions
107
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

contentful-hugo - npm Package Compare versions

Comparing version 1.5.4 to 1.6.0

images/unconfigured-embedded-entry-block.jpg

492

index.js
require('dotenv').config();
const contentful = require('contentful');
const yaml = require('js-yaml');
const fs = require('fs');
const mkdirp = require('mkdirp');
const yargs = require('yargs');
const { loadConfig } = require('./src/config');
const { removeLeadingAndTrailingSlashes } = require('./src/strings');
yargs.options({
preview: { type: 'boolean', default: false, alias: 'P' },
preview: { type: 'boolean', default: false, alias: 'P' },
init: { type: 'boolean', default: false },
wait: { type: 'number', default: 0, alias: 'W' },
config: { type: 'string', default: null, alias: 'C' },
});
const argv = yargs.argv;
const richTextToPlain = require('@contentful/rich-text-plain-text-renderer')
.documentToPlainTextString;
const getAssetFields = require('./src/getAssetFields');
const getEntryFields = require('./src/getEntryFields');
const richTextNodes = require('./src/richTextNodes');
const createFile = require('./src/createFile');
const processEntry = require('./src/processEntry');
const checkIfFinished = require('./src/checkIfFinished');
const initializeDirectory = require('./src/initializeDirectory');

@@ -25,100 +24,105 @@ // counter variables

if (
process.env.CONTENTFUL_SPACE &&
(process.env.CONTENTFUL_TOKEN || process.env.CONTENTFUL_PREVIEW_TOKEN)
if (argv.init) {
initializeDirectory();
} else if (
process.env.CONTENTFUL_SPACE &&
(process.env.CONTENTFUL_TOKEN || process.env.CONTENTFUL_PREVIEW_TOKEN)
) {
initialize();
loadConfig('.', argv.config).then(config => {
initialize(config);
});
} else {
console.log(
`\nERROR: Environment variables not yet set.\n\nThis module requires the following environmental variables to be set before running:\nCONTENTFUL_SPACE, CONTENTFUL_TOKEN, CONTENTFUL_PREVIEW_TOKEN (optional)\n\nYou can set them using the command line or place them in a .env file.\n`
);
console.log(
`\nERROR: Environment variables not yet set.\n\nThis module requires the following environmental variables to be set before running:\nCONTENTFUL_SPACE, CONTENTFUL_TOKEN, CONTENTFUL_PREVIEW_TOKEN (optional)\n\nYou can set them using the command line or place them in a .env file.\n`
);
}
// getting settings from config file
function initialize() {
const configFile = 'contentful-settings.yaml';
// check if configFile exist and throw error if it doesn't
const deliveryMode = argv.preview ? 'Preview Data' : 'Published Data';
if (fs.existsSync(configFile)) {
console.log(
`\n---------------------------------------------\n Pulling ${deliveryMode} from Contentful...\n---------------------------------------------\n`
);
try {
const config = yaml.safeLoad(
fs.readFileSync('contentful-settings.yaml')
);
// loop through repeatable content types
const types = config.repeatableTypes;
if (types) {
totalContentTypes += types.length;
for (let i = 0; i < types.length; i++) {
// object to pass settings into the function
const contentSettings = {
typeId: types[i].id,
directory: types[i].directory,
isHeadless: types[i].isHeadless,
fileExtension: types[i].fileExtension,
titleField: types[i].title,
dateField: types[i].dateField,
mainContent: types[i].mainContent,
type: types[i].type,
};
// check file extension settings
switch (contentSettings.fileExtension) {
case 'md':
case 'yaml':
case 'yml':
case undefined:
case null:
getContentType(1000, 0, contentSettings);
break;
default:
console.log(
` ERROR: extension "${contentSettings.fileExtension}" not supported`
);
break;
}
}
}
// loop through single content types
const singles = config.singleTypes;
if (singles) {
totalContentTypes += singles.length;
for (let i = 0; i < singles.length; i++) {
const single = singles[i];
const contentSettings = {
typeId: single.id,
directory: single.directory,
fileExtension: single.fileExtension,
fileName: single.fileName,
titleField: single.title,
dateField: single.dateField,
mainContent: single.mainContent,
isSingle: true,
type: single.type,
};
switch (contentSettings.fileExtension) {
case 'md':
case 'yaml':
case 'yml':
case null:
case undefined:
getContentType(1, 0, contentSettings);
break;
default:
console.log(
` ERROR: extension "${contentSettings.fileExtension}" not supported`
);
break;
}
}
}
} catch (e) {
console.log(e);
}
} else {
console.log(
`\nConfiguration file not found. Create a file called "contentful-settings.yaml" to get started.\nVisit https://github.com/ModiiMedia/contentful-hugo for configuration instructions\n`
);
}
async function initialize(config = null) {
// check if configFile exist and throw error if it doesn't
const deliveryMode = argv.preview ? 'Preview Data' : 'Published Data';
if (config) {
const waitTime = argv.wait;
if (waitTime && typeof waitTime === 'number') {
console.log(`waiting ${waitTime}ms...`);
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, waitTime);
});
}
console.log(
`\n---------------------------------------------\n Pulling ${deliveryMode} from Contentful...\n---------------------------------------------\n`
);
// loop through repeatable content types
const types = config.repeatableTypes;
if (types) {
totalContentTypes += types.length;
for (let i = 0; i < types.length; i++) {
// object to pass settings into the function
const contentSettings = {
typeId: types[i].id,
directory: types[i].directory,
isHeadless: types[i].isHeadless,
fileExtension: types[i].fileExtension,
titleField: types[i].title,
dateField: types[i].dateField,
mainContent: types[i].mainContent,
type: types[i].type,
};
// check file extension settings
switch (contentSettings.fileExtension) {
case 'md':
case 'yaml':
case 'yml':
case undefined:
case null:
getContentType(1000, 0, contentSettings);
break;
default:
console.log(
` ERROR: extension "${contentSettings.fileExtension}" not supported`
);
break;
}
}
}
// loop through single content types
const singles = config.singleTypes;
if (singles) {
totalContentTypes += singles.length;
for (let i = 0; i < singles.length; i++) {
const single = singles[i];
const contentSettings = {
typeId: single.id,
directory: single.directory,
fileExtension: single.fileExtension,
fileName: single.fileName,
titleField: single.title,
dateField: single.dateField,
mainContent: single.mainContent,
isSingle: true,
type: single.type,
};
switch (contentSettings.fileExtension) {
case 'md':
case 'yaml':
case 'yml':
case null:
case undefined:
getContentType(1, 0, contentSettings);
break;
default:
console.log(
` ERROR: extension "${contentSettings.fileExtension}" not supported`
);
break;
}
}
}
} else {
console.log(
`\nConfiguration file not found. Run "contentful-hugo --init" to get started.\nFor more detailed instructions visit https://github.com/ModiiMedia/contentful-hugo\n`
);
}
}

@@ -129,208 +133,88 @@

function getContentType(limit, skip, contentSettings, itemsPulled) {
let previewMode = false;
if (argv.preview) {
previewMode = true;
}
if (previewMode && !process.env.CONTENTFUL_PREVIEW_TOKEN) {
throw new Error(
'Environment variable CONTENTFUL_PREVIEW_TOKEN not set'
);
} else if (!previewMode && !process.env.CONTENTFUL_TOKEN) {
throw new Error('Environment variable CONTENTFUL_TOKEN not set');
}
const options = {
space: process.env.CONTENTFUL_SPACE,
host: previewMode ? 'preview.contentful.com' : 'cdn.contentful.com',
accessToken: previewMode
? process.env.CONTENTFUL_PREVIEW_TOKEN
: process.env.CONTENTFUL_TOKEN,
};
const client = contentful.createClient(options);
let previewMode = false;
if (argv.preview) {
previewMode = true;
}
if (previewMode && !process.env.CONTENTFUL_PREVIEW_TOKEN) {
throw new Error(
'Environment variable CONTENTFUL_PREVIEW_TOKEN not set'
);
} else if (!previewMode && !process.env.CONTENTFUL_TOKEN) {
throw new Error('Environment variable CONTENTFUL_TOKEN not set');
}
const options = {
space: process.env.CONTENTFUL_SPACE,
host: previewMode ? 'preview.contentful.com' : 'cdn.contentful.com',
accessToken: previewMode
? process.env.CONTENTFUL_PREVIEW_TOKEN
: process.env.CONTENTFUL_TOKEN,
};
const client = contentful.createClient(options);
// check for file extension default to markdown
if (!contentSettings.fileExtension) {
contentSettings.fileExtension = 'md';
}
// check for file extension default to markdown
if (!contentSettings.fileExtension) {
contentSettings.fileExtension = 'md';
}
client
.getEntries({
content_type: contentSettings.typeId,
limit: limit,
skip: skip,
order: 'sys.updatedAt',
})
.then(data => {
// variable for counting number of items pulled
let itemCount;
if (itemsPulled) {
itemCount = itemsPulled;
} else {
itemCount = 0;
}
// create directory for file
mkdirp.sync(`.${contentSettings.directory}`);
client
.getEntries({
content_type: contentSettings.typeId,
limit: limit,
skip: skip,
order: 'sys.updatedAt',
})
.then(data => {
// variable for counting number of items pulled
let itemCount;
if (itemsPulled) {
itemCount = itemsPulled;
} else {
itemCount = 0;
}
// create directory for file
mkdirp.sync(
`./${removeLeadingAndTrailingSlashes(
contentSettings.directory
)}`
);
for (let i = 0; i < data.items.length; i++) {
const item = data.items[i];
const frontMatter = {};
if (contentSettings.isHeadless) {
frontMatter.headless = true;
mkdirp.sync(`.${contentSettings.directory + item.sys.id}`);
}
if (contentSettings.type) {
frontMatter.type = contentSettings.type;
}
frontMatter.updated = item.sys.updatedAt;
frontMatter.createdAt = item.sys.createdAt;
frontMatter.date = item.sys.createdAt;
for (const field of Object.keys(item.fields)) {
if (field === contentSettings.mainContent) {
// skips to prevent duplicating mainContent in frontmatter
continue;
} else if (field === 'date') {
// convert dates with time to ISO String so Hugo can properly Parse
const d = item.fields[field];
if (d.length > 10) {
frontMatter.date = new Date(d).toISOString();
} else {
frontMatter.date = d;
}
continue;
}
const fieldContent = item.fields[field];
switch (typeof fieldContent) {
case 'object':
if ('sys' in fieldContent) {
frontMatter[field] = {};
switch (fieldContent.sys.type) {
case 'Asset':
frontMatter[field] = getAssetFields(
fieldContent
);
break;
case 'Entry':
frontMatter[field] = getEntryFields(
fieldContent
);
break;
default:
frontMatter[field] = fieldContent;
break;
}
}
// rich text (see rich text function)
else if ('nodeType' in fieldContent) {
frontMatter[field] = [];
frontMatter[
`${field}_plaintext`
] = richTextToPlain(fieldContent);
const nodes = fieldContent.content;
for (let i = 0; i < nodes.length; i++) {
frontMatter[field].push(
richTextNodes(nodes[i])
);
}
}
// arrays
else {
if (!fieldContent.length) {
frontMatter[field] = fieldContent;
} else {
frontMatter[field] = [];
for (
let i = 0;
i < fieldContent.length;
i++
) {
const arrayNode = fieldContent[i];
switch (typeof arrayNode) {
case 'object': {
let arrayObject = {};
switch (arrayNode.sys.type) {
case 'Asset':
arrayObject = getAssetFields(
arrayNode
);
frontMatter[field].push(
arrayObject
);
break;
case 'Entry':
arrayObject = getEntryFields(
arrayNode
);
frontMatter[field].push(
arrayObject
);
break;
default:
frontMatter[field].push(
arrayNode
);
break;
}
break;
}
default:
frontMatter[field].push(
arrayNode
);
break;
}
}
}
}
break;
default:
frontMatter[field] = item.fields[field];
break;
}
}
let mainContent = null;
if (item.fields[contentSettings.mainContent]) {
mainContent = `${item.fields[contentSettings.mainContent]}`;
}
for (let i = 0; i < data.items.length; i++) {
const item = data.items[i];
processEntry(item, contentSettings);
itemCount++;
}
createFile(
contentSettings,
item.sys.id,
frontMatter,
mainContent
);
itemCount++;
}
// check total number of items against number of items pulled in API
if (data.total > data.limit) {
// run function again if there are still more items to get
const newSkip = skip + limit;
getContentType(limit, newSkip, contentSettings, itemCount);
} else {
let grammarStuff;
if (Number(data.total) === 1) {
grammarStuff = 'item';
} else {
grammarStuff = 'items';
}
console.log(
` ${contentSettings.typeId} - ${itemCount} ${grammarStuff}`
);
typesExtracted++;
if (checkIfFinished(typesExtracted, totalContentTypes)) {
console.log(
`\n---------------------------------------------\n`
);
}
}
})
.catch(error => {
const response = error.response;
if (response) {
console.log(
` --------------------------\n ${contentSettings.typeId} - ERROR ${response.status} ${response.statusText}\n (Note: ${response.data.message})\n --------------------------`
);
} else {
console.log(error);
}
});
// check total number of items against number of items pulled in API
if (data.total > data.limit) {
// run function again if there are still more items to get
const newSkip = skip + limit;
getContentType(limit, newSkip, contentSettings, itemCount);
} else {
let grammarStuff;
if (Number(data.total) === 1) {
grammarStuff = 'item';
} else {
grammarStuff = 'items';
}
console.log(
` ${contentSettings.typeId} - ${itemCount} ${grammarStuff}`
);
typesExtracted++;
if (checkIfFinished(typesExtracted, totalContentTypes)) {
console.log(
`\n---------------------------------------------\n`
);
}
}
})
.catch(error => {
const response = error.response;
if (response) {
console.log(
` --------------------------\n ${contentSettings.typeId} - ERROR ${response.status} ${response.statusText}\n (Note: ${response.data.message})\n --------------------------`
);
} else {
console.log(error);
}
});
}
{
"name": "contentful-hugo",
"version": "1.5.4",
"description": "Node module that pulls data from Contentful and turns it into markdown files for Hugo. Can be used with other Static Site Generators, but has some Hugo specific features.",
"main": "index.js",
"repository": {
"typ": "git",
"url": "https://github.com/ModiiMedia/contentful-hugo"
},
"keywords": [
"hugo",
"contentful",
"blog",
"markdown",
"yaml",
"ssg",
"website",
"static-site-generator",
"jamstack",
"frontmatter",
"static-site"
],
"author": {
"name": "Joshua Sosso",
"email": "josh@modiimedia.com",
"url": "https://www.modiimedia.com"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"license": "ISC",
"dependencies": {
"@contentful/rich-text-plain-text-renderer": "^13.4.0",
"contentful": "^7.14.0",
"dotenv": "^7.0.0",
"js-yaml": "^3.13.1",
"json-to-pretty-yaml": "^1.2.2",
"mkdirp": "^0.5.3",
"yargs": "^15.3.1"
},
"bin": {
"contentful-hugo": "./cli.js"
},
"files": [
"cli.js",
"images",
"readme.md",
"index.js",
"src"
],
"devDependencies": {
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-node": "^10.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"prettier": "^1.19.1"
}
"name": "contentful-hugo",
"version": "1.6.0",
"description": "Node module that pulls data from Contentful and turns it into markdown files for Hugo. Can be used with other Static Site Generators, but has some Hugo specific features.",
"main": "index.js",
"repository": {
"typ": "git",
"url": "https://github.com/ModiiMedia/contentful-hugo"
},
"keywords": [
"hugo",
"contentful",
"blog",
"markdown",
"yaml",
"ssg",
"website",
"static-site-generator",
"jamstack",
"frontmatter",
"static-site"
],
"author": {
"name": "Joshua Sosso",
"email": "josh@modiimedia.com",
"url": "https://www.modiimedia.com"
},
"scripts": {
"test": "jest --coverage",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"postinstall": "node postinstall.js"
},
"license": "ISC",
"dependencies": {
"@contentful/rich-text-html-renderer": "^13.4.0",
"@contentful/rich-text-plain-text-renderer": "^13.4.0",
"@contentful/rich-text-types": "^14.1.0",
"contentful": "^7.14.6",
"dotenv": "^7.0.0",
"js-yaml": "^3.14.0",
"json-to-pretty-yaml": "^1.2.2",
"mkdirp": "^0.5.5",
"yargs": "^15.4.1"
},
"bin": {
"contentful-hugo": "./cli.js"
},
"files": [
"cli.js",
"images",
"readme.md",
"index.js",
"src"
],
"devDependencies": {
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-node": "^10.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"jest": "^26.2.2",
"prettier": "^1.19.1"
}
}

@@ -14,2 +14,4 @@ # Contentful Hugo

- [Expected Output](#Expected-Output)
- [Standard Fields](#Default-Date-and-Time-Fields)
- [Richtext Fields](#Rich-Text-As-Main-Content)
- [Known Issues](#Known-Issues)

@@ -44,2 +46,6 @@

```powershell
## initialize the directory
contentful-hugo --init
## fetch from contentful
contentful-hugo

@@ -51,10 +57,14 @@ ```

```powershell
npx contentful-hugo --init
npx contentful-hugo
```
### Optional Flags
### Flags
| flag | aliases | description |
| --------- | ------- | ---------------------------------------------------------------------------------------- |
| --preview | -P | runs in preview mode, which pulls both published and unpublished entries from Contentful |
| flag | aliases | description |
| --------- | ------- | -------------------------------------------------------------------------------------------------------- |
| --init | | Initialize the directory. Generates a config file and default shortcodes for Contentful rich text fields |
| --preview | -P | Runs in preview mode, which pulls both published and unpublished entries from Contentful |
| --wait | -W | Wait for the specified number of milliseconds before pulling data from Contentful. |
| --config | -C | Specific the path to a config file. |

@@ -67,2 +77,8 @@ #### Preview Mode Example

#### Multiple Flags Example
```powershell
contentful-hugo --wait=2000 --preview --config="my_custom_config.js"
```
### Example Package.json

@@ -128,7 +144,57 @@

In order to pull the data you want you will need to create a **contentful-settings.yaml** file in the root of your repository.
In order to pull the data you want you will need to create a config file in the root of your repository. Contentful-hugo by default will search for the following files as a config.
Example **contentful-settings.yaml** file (see below for complete configuration options)
- `contentful-hugo.config.js`
- `contentful-hugo.config.yaml`
- `contentful-hugo.yaml`
- `contentful-settings.yaml`
You can also specify a custom config file using the `--config` flag. (Javascript or YAML config files are the only currently accepted filetypes)
#### Example Javascript Config
```javascript
// contentful-hugo.config.js
module.exports = {
singleTypes: [
{
id: 'homepage',
directory: 'content',
fileName: '_index',
fileExtension: 'md',
},
{
id: 'siteSettings',
directory: 'data',
fileName: 'settings',
fileExtension: 'yaml',
},
],
repeatableTypes: [
{
id: 'posts',
directory: 'content/posts',
fileExtension: 'md',
mainContent: 'content',
},
{
id: 'seoFields',
isHeadless: true,
directory: 'content/seo-fields',
},
{
id: 'reviews',
directory: 'content/reviews',
mainContent: 'reviewBody',
},
],
};
```
#### Example YAML Config
```yaml
# contentful-hugo.config.yaml
singleTypes:

@@ -138,3 +204,3 @@ # fetches only the most recently updated entry in a particular content type

- id: homepage
directory: /content/
directory: content
fileName: _index

@@ -145,3 +211,3 @@ fileExtension: md

- id: siteSettings
directory: /data/
directory: data
fileName: settings

@@ -155,3 +221,3 @@ fileExtension: yaml

- id: posts
directory: /content/posts/
directory: content/posts
fileExtension: md

@@ -162,6 +228,6 @@ mainContent: content

isHeadless: true
directory: /content/seo-fields/
directory: content/seo-fields
- id: reviews
directory: /content/reviews/
directory: content/reviews
mainContent: reviewBody

@@ -171,6 +237,6 @@

isHeadless: true
directory: /content/staff/
directory: content/staff
```
**Configuration Options**
#### **Config File Options**

@@ -180,3 +246,3 @@ | field | required | description |

| id | required | contentful content type ID goes here |
| directory | required | directory where you want the file(s) to be generated (leading and trailing slashes required for the time being) |
| directory | required | directory where you want the file(s) to be generated |
| fileName | required (single types only) | name of the file generated |

@@ -220,4 +286,4 @@ | fileExtension | optional | can be "md", "yml", or "yaml" (defaults to "md") |

<img
src="{{ .Params.assetFieldName.url }}"
width="{{ .Params.assetFieldName.width }}"
src="{{ .Params.assetFieldName.url }}"
width="{{ .Params.assetFieldName.width }}"
/>

@@ -270,4 +336,33 @@ ```

### Rich Text Fields
### Rich Text As Main Content
A rich text field that is set as the "mainContent" for a content type will be rendered as markdown for Hugo.
Dynamic content such as `embedded-entry-blocks` are rendered as shortcodes with parameters included that can be used to fetch the necessary data.
```md
<!-- example embedded entry -->
<!-- you can use the id, contentType, and parentContentType parameters to fetch the desired data -->
{{< contentful-hugo/embedded-entry id="nTLo2ffSJJp5QrnrO5IU9" contentType="gallery" parentContentType="post" >}}
```
Before fetching rich text data make sure you have run `contentful-hugo --init` so that you will have all the rich text shortcodes. Once you have these shortcodes you can extend and modify them to suit your needs.
The list of rich text short codes includes:
- contentful-hugo/asset-hyperlink.html
- contentful-hugo/embedded-asset.html
- contentful-hugo/embedded-entry.html
- contentful-hugo/entry-hyperlink.html
- contentful-hugo/inline-entry.html
By default the richtext short codes will show a notification for an unconfigured item.
![Unconfigured Embedded Entry Block](images/unconfigured-embedded-entry-block.jpg)
You can customize them by navigating to `layouts/shortcodes/contentful-hugo/{shortcode-name}.html`
### Rich Text In FrontMatter
A Rich text field will produce nested arrays mirroring the JSON structure that they have in the API. Each node will need to be looped through and produce HTML depending on the nodeType field.

@@ -318,2 +413,2 @@

- **Date & Time Field w/o Timezone**: Date fields that include time but do not have a specified timezone will have a timezone set based on whatever machine the script is run on. So using a date field in contentful with this setting could lead to unexpected results when formatting dates. Date fields that don't include time (ex: YYYY-MM-DD) are not effected by this.
- **Fetching Data Before Contentful CDN Updates**: Sometimes when triggering a build from a webhook, it won't always get the latest data. This is because it sometimes takes a couple seconds for the latest data to get distrubuted across Contentful's CDN. If you run into this issue it might be worth it to create a "wait function" just to delay fetching the data by a couple seconds. You could include it in the script you use contentful-hugo by doing something like the following `"node wait.js && contentful-hugo"`
- **Fetching Data Before Contentful CDN Updates**: Sometimes when triggering a build from a webhook, it won't always get the latest data. This is because it sometimes takes a couple seconds for the latest data to get distrubuted across Contentful's CDN. If you run into this issue add teh the `--wait` flag to your script. Here's an example where we wait an additional 6 seconds `contentful-hugo --wait=6000`.
const checkIfFinished = (num, totalContentTypes) => {
if (num === totalContentTypes) {
return true;
} else {
return false;
}
if (num === totalContentTypes) {
return true;
} else {
return false;
}
};
module.exports = checkIfFinished;
const YAML = require('json-to-pretty-yaml');
const fs = require('fs');
const { removeLeadingAndTrailingSlashes } = require('./strings');
const mkdirp = require('mkdirp');
module.exports = (contentSettings, entryId, frontMatter, mainContent) => {
let fileContent = '';
if (
contentSettings.fileExtension === 'md' ||
contentSettings.fileExtension === null ||
contentSettings.fileExtension === undefined
) {
fileContent += `---\n`;
}
/**
*
* @param {Object} contentSettings - Content settings object
* @param {String} entryId - The id of the Contentful entry
* @param {Object} frontMatter - Object containing all the data for frontmatter
* @param {String} mainContent - String data for the main content that will appear below the frontmatter
*/
const createFile = (contentSettings, entryId, frontMatter, mainContent) => {
let fileContent = '';
if (
contentSettings.fileExtension === 'md' ||
contentSettings.fileExtension === null ||
contentSettings.fileExtension === undefined
) {
fileContent += `---\n`;
}
// add current item to filecontent
fileContent += YAML.stringify(frontMatter);
if (
contentSettings.fileExtension !== 'yaml' ||
contentSettings.fileExtension !== 'yml'
) {
fileContent += `---\n`;
}
// add current item to filecontent
fileContent += YAML.stringify(frontMatter);
if (
contentSettings.fileExtension !== 'yaml' ||
contentSettings.fileExtension !== 'yml'
) {
fileContent += `---\n`;
}
// if set add the main content below the front matter
if (mainContent) {
fileContent += mainContent;
}
// if set add the main content below the front matter
if (mainContent) {
fileContent += mainContent;
}
// create file
let filePath = '';
if (contentSettings.isHeadless) {
filePath = `.${contentSettings.directory}/${entryId}/index.${contentSettings.fileExtension}`;
} else if (contentSettings.isSingle) {
filePath = `.${contentSettings.directory}/${contentSettings.fileName}.${contentSettings.fileExtension}`;
} else {
filePath = `.${contentSettings.directory}${entryId}.${contentSettings.fileExtension}`;
}
return fs.writeFile(filePath, fileContent, error => {
if (error) {
console.log(error);
}
});
// create file
let filePath = '';
const directory = removeLeadingAndTrailingSlashes(
contentSettings.directory
);
const { fileExtension, fileName, isSingle, isHeadless } = contentSettings;
if (isHeadless) {
mkdirp.sync(`./${directory}/${entryId}`);
filePath = `./${directory}/${entryId}/index.${fileExtension}`;
} else if (isSingle) {
filePath = `./${directory}/${fileName}.${fileExtension}`;
} else {
filePath = `./${directory}/${entryId}.${fileExtension}`;
}
return fs.writeFile(filePath, fileContent, error => {
if (error) {
console.log(error);
}
});
};
module.exports = createFile;

@@ -1,20 +0,28 @@

module.exports = contentfulObject => {
const frontMatter = {};
let assetType = '';
if (contentfulObject.fields.file) {
assetType = contentfulObject.fields.file.contentType;
}
frontMatter.assetType = assetType;
frontMatter.url = contentfulObject.fields.file.url;
frontMatter.title = contentfulObject.fields.title;
frontMatter.description = contentfulObject.fields.description;
/**
*
* @param {Object} contentfulObject
* @param {Object} contentfulObject.sys
* @param {Object} contentfulObject.fields
*/
const getAssetFields = contentfulObject => {
const frontMatter = {};
let assetType = '';
if (contentfulObject.fields.file) {
assetType = contentfulObject.fields.file.contentType;
}
frontMatter.assetType = assetType;
frontMatter.url = contentfulObject.fields.file.url;
frontMatter.title = contentfulObject.fields.title;
frontMatter.description = contentfulObject.fields.description;
// get specific details depending on the asset type
const details = contentfulObject.fields.file.details;
if (assetType.includes('image')) {
// image height and width
frontMatter.width = details.image.width;
frontMatter.height = details.image.height;
}
return frontMatter;
// get specific details depending on the asset type
const details = contentfulObject.fields.file.details;
if (assetType.includes('image')) {
// image height and width
frontMatter.width = details.image.width;
frontMatter.height = details.image.height;
}
return frontMatter;
};
module.exports = getAssetFields;
module.exports = entry => {
let obj = {};
if (entry.sys) {
obj = {
id: entry.sys.id,
contentType: entry.sys.contentType.sys.id,
};
}
return obj;
let obj = {};
if (entry.sys) {
obj = {
id: entry.sys.id,
contentType: entry.sys.contentType.sys.id,
};
}
return obj;
};
const getEntryFields = require('./getEntryFields');
const getAssetFields = require('./getAssetFields');
const mapDataNode = node => {
const { target } = node;
if (target) {
if (target.sys) {
switch (target.sys.type) {
case 'Entry':
return getEntryFields(target);
case 'Asset':
return getAssetFields(target);
}
} else {
console.log(node);
}
}
return node;
};
const mapContentNode = node => {
const contentArr = [];
for (const item of node) {
contentArr.push(richTextNodes(item));
}
return contentArr;
};
const mapMarks = node => {
const markArr = [];
for (const item of node) {
markArr.push(item.type);
}
return markArr;
};
const richTextNodes = node => {
const fieldContent = {};
for (const field of Object.keys(node)) {
switch (field) {
case 'data': {
const t = node[field].target;
if (t) {
if (t.sys) {
switch (t.sys.type) {
case 'Entry':
fieldContent[field] = getEntryFields(t);
break;
case 'Asset':
fieldContent[field] = getAssetFields(t);
break;
}
} else {
console.log(node[field]);
}
} else {
fieldContent[field] = node[field];
}
break;
}
case 'content': {
const contentArr = [];
for (const item of node[field]) {
contentArr.push(richTextNodes(item));
}
fieldContent[field] = contentArr;
break;
}
case 'marks': {
const markArr = [];
for (const item of node[field]) {
markArr.push(item.type);
}
fieldContent[field] = markArr;
break;
}
default:
fieldContent[field] = node[field];
break;
}
}
return fieldContent;
const fieldContent = {};
for (const field of Object.keys(node)) {
const subNode = node[field];
switch (field) {
case 'data': {
fieldContent[field] = mapDataNode(subNode);
break;
}
case 'content': {
fieldContent[field] = mapContentNode(subNode);
break;
}
case 'marks': {
fieldContent[field] = mapMarks(subNode);
break;
}
default:
fieldContent[field] = node[field];
break;
}
}
return fieldContent;
};
module.exports = richTextNodes;
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