Skip to content

Instantly share code, notes, and snippets.

@andiappan-ar
Last active August 20, 2023 13:50
Show Gist options
  • Save andiappan-ar/aab51377d95fff024aff3eb3b54ef9c0 to your computer and use it in GitHub Desktop.
Save andiappan-ar/aab51377d95fff024aff3eb3b54ef9c0 to your computer and use it in GitHub Desktop.
Sitecore headless JSS customize component scaffold creation

How to customize Sitecore JSS scaffold component

Requirement

We have a component group which is similar to our helix layer. Example Banner folder contains different types of banner components.

  1. We need a command like below to create a component

> jss scaffold <ComponentName> <FeatureName>

  1. This command needs to create a component under a specific location “/src/components/feature/{FeatureName}/ComponentName”

  2. Disable the manifest file creation.

  3. Create a component file with our own component. Below example of a PromoBanner component,

import React from 'react';
import { Text } from '@sitecore-jss/sitecore-jss-react';

// Component name should be dynamically pick from the command
const PromoBanner = (props) => (
  <div>
    <p>PromoBanner Component created from scaffold cmd.</p>
    <Text field={props.fields.heading} />
  </div>
);

export default PromoBanner;

Read detailed blog from here https://andisitecore.wordpress.com/

/*
Component Scaffolding Script
This is a script that enables scaffolding a new JSS component using `jss scaffold <componentname>`.
Edit this script if you wish to use your own conventions for component storage in your JSS app.
*/
/* eslint-disable no-throw-literal,no-console */
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
/*
SCAFFOLDING SCRIPT
*/
const componentName = process.argv[2];
if (!componentName) {
throw 'Component name was not passed. Usage: jss scaffold <ComponentName> <FeatureName>';
}
if (!/^[A-Z][A-Za-z0-9-]+$/.test(componentName)) {
throw 'Component name should start with an uppercase letter and contain only letters and numbers.';
}
const featureName = process.argv[3];
if (!featureName) {
throw 'Feature name was not passed. Usage: jss scaffold <ComponentName> <FeatureName>';
}
if (!/^[A-Z][A-Za-z0-9-]+$/.test(featureName)) {
throw 'Feature name should start with an uppercase letter and contain only letters and numbers.';
}
const componentManifestDefinitionsPath = 'sitecore/definitions/components';
const componentRootPath = 'src/components/feature';
/*****DISABLED manifest creation******/
// let manifestOutputPath = null;
// if (fs.existsSync(componentManifestDefinitionsPath)) {
// manifestOutputPath = scaffoldManifest();
// } else {
// console.log(
// `Not scaffolding manifest because ${componentManifestDefinitionsPath} did not exist. This is normal for Sitecore-first workflow.`
// );
// }
const componentOutputPath = scaffoldComponent();
console.log();
console.log(chalk.green(`Component ${componentName} has been scaffolded.`));
console.log(chalk.green('Next step:'));
console.log(chalk.green('Check the layout service for this component & map with available fields.'));
/*****DISABLED manifest creation******/
// if (manifestOutputPath) {
// console.log(`* Define the component's data in ${chalk.green(manifestOutputPath)}`);
// } else {
// console.log(
// `* Scaffold the component in Sitecore using '${chalk.green(
// `jss deploy component ${componentName} --allowedPlaceholders placeholder-for-component`
// )}, or create the rendering item and datasource template yourself.`
// );
// }
// console.log(`* Implement the React component in ${chalk.green(componentOutputPath)}`);
// if (manifestOutputPath) {
// console.log(
// `* Add the component to a route layout (/data/routes) and test it with ${chalk.green(
// 'jss start'
// )}`
// );
// } else {
// console.log(
// `* Deploy your app with the new component to Sitecore (${chalk.green(
// 'jss deploy:watch'
// )} or ${chalk.green('jss deploy files')})`
// );
// console.log('* Add the component to a route using Sitecore Experience Editor, and test it.');
// }
/*
TEMPLATING FUNCTIONS
*/
/**
* Force to use `crlf` line endings, we are using `crlf` across the project.
* Replace: `lf` (\n), `cr` (\r)
* @param {string} content
*/
function editLineEndings(content) {
return content.replace(/\r|\n/gm, '\r\n');
}
function scaffoldComponent() {
const exportVarName = componentName.replace(/[^\w]+/g, '');
const componentTemplate = `import React from 'react';
import { Text } from '@sitecore-jss/sitecore-jss-react';
const ${exportVarName} = (props) => (
<div>
<p>${componentName} Component created from scaffold cmd.</p>
<Text field={props.fields.heading} />
</div>
);
export default ${exportVarName};
`;
const outputFeatureDirecotoryPath = path.join(componentRootPath, featureName);
const outputDirectoryPath = path.join(componentRootPath, featureName, componentName);
if (fs.existsSync(outputDirectoryPath)) {
throw `Component path ${outputDirectoryPath} already existed. Not creating component.`;
}
if (!fs.existsSync(outputFeatureDirecotoryPath)) {
console.log(chalk.green('New feature folder created:'+ outputFeatureDirecotoryPath));
fs.mkdirSync(outputFeatureDirecotoryPath);
}
fs.mkdirSync(outputDirectoryPath);
const outputFilePath = path.join(outputDirectoryPath, 'index.js');
fs.writeFileSync(outputFilePath, editLineEndings(componentTemplate), 'utf8');
return outputFilePath;
}
// function scaffoldManifest() {
// const manifestTemplate = `// eslint-disable-next-line no-unused-vars
// import { CommonFieldTypes, SitecoreIcon, Manifest } from '@sitecore-jss/sitecore-jss-dev-tools';
// /**
// * Adds the ${componentName} component to the disconnected manifest.
// * This function is invoked by convention (*.sitecore.js) when 'jss manifest' is run.
// * @param {Manifest} manifest Manifest instance to add components to
// */
// export default function (manifest) {
// manifest.addComponent({
// name: '${componentName}',
// icon: SitecoreIcon.DocumentTag,
// fields: [{ name: 'heading', type: CommonFieldTypes.SingleLineText }],
// /*
// If the component implementation uses <Placeholder> or withPlaceholder to expose a placeholder,
// register it here, or components added to that placeholder will not be returned by Sitecore:
// placeholders: ['exposed-placeholder-name']
// */
// });
// }
// `;
// const outputFilePath = path.join(
// componentManifestDefinitionsPath,
// `${componentName}.sitecore.js`
// );
// if (fs.existsSync(outputFilePath)) {
// throw `Manifest definition path ${outputFilePath} already exists. Not creating manifest definition.`;
// }
// fs.writeFileSync(outputFilePath, editLineEndings(manifestTemplate), 'utf8');
// return outputFilePath;
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment