JSON RTE Registry

View as Markdown

JSON RTE Registry

registerJsonRte

The registerJsonRte method registers custom element types (blocks) and text wrappers (inline marks) for JSON RTE content.

Use Case: Extend the default rich-text rendering with branded components, custom formatting, and visual effects.

Parameters:

NameTypeDescription
configIJsonToHtmlOptionsConfiguration object for custom JSON RTE rendering.

import { registerJsonRte } from '@contentstack/studio-react';

registerJsonRte({
  customElementTypes: {
    // Custom block-level elements
    infoBox: (attrs, child, jsonBlock, extraProps) => {
      return `<div class="info-box" style="padding: 1rem; background-color: #e3f2fd; border-left: 4px solid #2196f3;">${child}</div>`;
    },
    callout: (attrs, child, jsonBlock, extraProps) => {
      const type = jsonBlock.attrs?.type || 'info';
      const colors = {
        info: '#e3f2fd',
        warning: '#fff3e0',
        error: '#ffebee',
        success: '#e8f5e9'
      };
      return `<div class="callout callout-${type}" style="padding: 1rem; background-color: ${colors[type]}; border-radius: 4px; margin: 1rem 0;">${child}</div>`;
    }
  },

  customTextWrapper: {
    // Custom inline text formatting
    highlight: (child, value) => {
      return `<span class="highlight" style="background-color: #ffeb3b; padding: 2px 4px;">${child}</span>`;
    },
    color: (child, value) => {
      return `<span class="text-color" style="color: ${value};">${child}</span>`;
    },
    code: (child, value) => {
      return `<code class="inline-code" style="background-color: #f5f5f5; padding: 2px 4px; border-radius: 3px; font-family: monospace;">${child}</code>`;
    }
  },

  allowNonStandardTypes: true
});

Configuration Options

The configuration options let developers control how JSON RTE content is converted to HTML. You can define custom elements, text wrappers, and allow non-standard types to extend rendering behavior.

customElementTypes (IJsonToHtmlElementTags)

The customElementTypes option defines the block-level elements you want to support in rich text.

Function Signature

Parameters

NameTypeDescription
attrsstringHTML attributes represented as a string.
childstringThe rendered inner HTML content of the element.
jsonBlockobjectThe full JSON block object. Use jsonBlock.attrs to access attributes.
extraPropsobject (optional)Additional context props passed from the rendering environment.
customElementTypes: {
  // Custom info box component
  infoBox: (attrs, child, jsonBlock) => {
    const title = jsonBlock.attrs?.title || 'Information';
    const icon = jsonBlock.attrs?.icon || 'ℹ️';
    return `
<div class="info-box" style="border: 1px solid #ddd; border-radius: 8px; padding: 1rem; margin: 1rem 0;">
  <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
    <span style="font-size: 1.2rem; margin-right: 0.5rem;">${icon}</span>
    <strong>${title}</strong>
  </div>
  <div>${child}</div>
</div>
`;
  },

  // Custom quote component
  quote: (attrs, child, jsonBlock) => {
    const author = jsonBlock.attrs?.author || 'Unknown';
    const source = jsonBlock.attrs?.source || '';
    return `
<blockquote class="custom-quote" style="border-left: 4px solid #007bff; padding-left: 1rem; margin: 1rem 0; font-style: italic;">
  <div>${child}</div>
  <footer style="margin-top: 0.5rem; font-size: 0.9rem; color: #666;">
    — ${author}${source ? `, ${source}` : ''}
  </footer>
</blockquote>
`;
  }
}

customTextWrapper (IJsonToHtmlTextTags)

The customTextWrapper option defines inline text wrappers or marks used for applying formatting and effects to text within JSON RTE content.

Use Case: Enables custom styles such as highlights, keyboard inputs, or branded inline elements in rich-text fields.

Function Signature

(child: any, value: any) => string

Parameters

NameTypeDescription
childstringThe text content to wrap.
valueanyThe attribute value applied to the wrapper (for example, a color code, style, or effect).

Example

customTextWrapper: {
  // Highlight text with custom colors
  highlight: (child, value) => {
    const colors = {
      yellow: '#ffeb3b',
      green: '#4caf50',
      blue: '#2196f3',
      red: '#f44336'
    };
    const color = colors[value] || value;
    return `<span class="highlight" style="background-color: ${color}; padding: 2px 4px; border-radius: 3px;">${child}</span>`;
  },

  // Custom text styling
  style: (child, value) => {
    const styles = {
      bold: 'font-weight: bold;',
      italic: 'font-style: italic;',
      underline: 'text-decoration: underline;',
      strikethrough: 'text-decoration: line-through;'
    };
    const style = styles[value] || '';
    return `<span style="${style}">${child}</span>`;
  },

  // Custom font sizes
  fontSize: (child, value) => {
    return `<span style="font-size: ${value}px;">${child}</span>`;
  }
}

allowNonStandardTypes (boolean)

The allowNonStandardTypes option enables the use of non-standard element types in JSON RTE content.

Use Case:

  • Custom Components: Add branded elements such as info boxes, callouts, or product cards.
  • Enhanced Text: Format text with highlights, colors, or special fonts.
  • Interactive Elements: Insert interactive components, like buttons or widgets, into rich text.
  • Brand Consistency: Ensure rich text content aligns with your design system and styling standards.

Real World Example

import { registerJsonRte } from '@contentstack/studio-react';

// Register custom JSON RTE components for a marketing website
registerJsonRte({
  customElementTypes: {
    // Product showcase within rich text
    productShowcase: (attrs, child, jsonBlock) => {
      const product = jsonBlock.attrs;
      return `
<div class="product-showcase" style="
  border: 2px solid #e0e0e0;
  border-radius: 12px;
  padding: 1.5rem;
  margin: 1.5rem 0;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
">
  <div style="display: flex; align-items: center; gap: 1rem;">
    <img src="${product.image || '/placeholder.jpg'}"
      alt="${product.name || 'Product'}"
      style="width: 80px; height: 80px; border-radius: 8px; object-fit: cover;">
    <div>
      <h4 style="margin: 0 0 0.5rem 0; color: #2c3e50;">${product.name || 'Product Name'}</h4>
      <p style="margin: 0 0 0.5rem 0; color: #7f8c8d;">${product.description || 'Product description'}</p>
      <div style="font-size: 1.25rem; font-weight: bold; color: #e74c3c;">
        $${product.price || '0.00'}
      </div>
    </div>
  </div>
  ${child}
</div>
`;
    },

    // Testimonial block
    testimonial: (attrs, child, jsonBlock) => {
      const testimonial = jsonBlock.attrs;
      return `
<div class="testimonial" style="
  background-color: #f8f9fa;
  border-left: 4px solid #007bff;
  padding: 1.5rem;
  margin: 1.5rem 0;
  border-radius: 0 8px 8px 0;
">
  <div style="font-style: italic; margin-bottom: 1rem; color: #495057;">
    "${child}"
  </div>
  <div style="display: flex; align-items: center; gap: 0.5rem;">
    <img src="${testimonial.avatar || '/default-avatar.jpg'}"
      alt="${testimonial.author || 'Author'}"
      style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover;">
    <div>
      <strong style="color: #2c3e50;">${testimonial.author || 'Author Name'}</strong>
      ${testimonial.title ? `<br><span style="color: #6c757d; font-size: 0.9rem;">${testimonial.title}</span>` : ''}
    </div>
  </div>
</div>
`;
    },

    // Code block with syntax highlighting
    codeBlock: (attrs, child, jsonBlock) => {
      const language = jsonBlock.attrs?.language || 'text';
      return `
<div class="code-block" style="
  background-color: #2d3748;
  border-radius: 8px;
  padding: 1rem;
  margin: 1rem 0;
  overflow-x: auto;
">
  <div style="
    color: #e2e8f0;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 0.9rem;
    line-height: 1.5;
  ">
    <div style="
      color: #a0aec0;
      border-bottom: 1px solid #4a5568;
      padding-bottom: 0.5rem;
      margin-bottom: 1rem;
      font-size: 0.8rem;
      text-transform: uppercase;
      letter-spacing: 0.05em;
    ">
      ${language}
    </div>
    <pre style="margin: 0; white-space: pre-wrap;">${child}</pre>
  </div>
</div>
`;
    }
  },

  customTextWrapper: {
    // Brand colors for text
    brandColor: (child, value) => {
      const brandColors = {
        primary: '#007bff',
        secondary: '#6c757d',
        success: '#28a745',
        danger: '#dc3545',
        warning: '#ffc107',
        info: '#17a2b8'
      };
      const color = brandColors[value] || value;
      return `<span style="color: ${color}; font-weight: 500;">${child}</span>`;
    },

    // Custom text effects
    textEffect: (child, value) => {
      const effects = {
        glow: 'text-shadow: 0 0 10px currentColor;',
        shadow: 'text-shadow: 2px 2px 4px rgba(0,0,0,0.3);',
        outline: 'text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;'
      };
      const effect = effects[value] || '';
      return `<span style="${effect}">${child}</span>`;
    }
  },

  allowNonStandardTypes: true
});

Conditional Props

Conditional props are component props whose values depend on the values of other props. They enable components to change behavior or configuration dynamically, based on user selections or predefined logic.

Use Case: Show or modify a prop’s value only when another related prop meets a certain condition — for example, displaying a "link URL" field only when "link enabled" is set to true.

Example

props: {
  showAdvanced: {
    type: "boolean",
    displayName: "Show Advanced Options",
    defaultValue: false
  },
  advancedConfig: {
    type: "object",
    displayName: "Advanced Configuration",
    defaultValue: {},
    // This prop will only be shown when showAdvanced is true
    // (handled automatically by the Studio)
  }
}

Binding Support

Binding Support allows all component props to connect to external data sources using data binding.

Use Case: Dynamically populate component values  such as text, images, or links  by binding them to CMS entries, API responses, or environment variables within Studio.

Styles Configuration

The styles object defines the styling options available for your component, enabling customization of its visual appearance.

Example

styles: {
  // Default style group
  default: {
    styleSections: ["size", "spacing", "background", "border"],
    defaultClasses: ["my-component", "rounded"],
    defaultStyles: { padding: "1rem" },
    displayName: "Default Styles"
  },

  // Custom style group
  custom: {
    styleSections: ["typography", "transform"],
    defaultClasses: ["custom-text"],
    defaultStyles: { fontSize: "16px" },
    displayName: "Custom Styles"
  }
}

Available Style Sections

SectionDescription
classCustom CSS classes.
sizeWidth, height, min/max dimensions.
spacingMargin and padding.
positionPosition and z-index.
visibilityDisplay and opacity.
layoutFlexbox and grid properties.
typographyFont properties and text alignment.
transformTransform properties.
mediaMedia query styles.
backgroundBackground properties.
shadowBox and text shadow.
effectFilter and backdrop-filter.
overflowOverflow properties.
borderBorder properties.
responsiveResponsive design utilities.

Style Section Categories

CategoryDescription
blockAll block-level styling options.
textTypography-focused styling options.

Registry Options

The registerComponents configuration object controls built-in component availability, user overrides, and debug logging behavior.

allowedBuiltInComponents

The allowedBuiltInComponents option controls the built-in components available in the registry.

Type: boolean | string[]

Values:

  • true: Enable all built-ins (default)
  • false: Disable all built-ins
  • string[]: Enable only specific built-in types

overrideDefaultComponents

The overrideDefaultComponents option determines if user components override built-in components with the same type identifier.

Type: boolean

Values:

  • false: Prevent overriding built-ins (default)
  • true: Allow user components to override

debug

The debug option enables debug logging for troubleshooting during component registration.

Type: boolean

Values:

  • false: Disable logging (default)
  • true: Enable logging

Usage Example

// Basic component registration
registerComponents([
  {
    type: "hero-section",
    component: HeroSection,
    displayName: "Hero Section",
    description: "A prominent section for main content",
    sections: ["Custom Components"]
  }
]);

// Advanced component with full configuration
registerComponents([
  {
    type: "product-card",
    component: ProductCard,
    displayName: "Product Card",
    description: "Display product information in a card format",
    sections: ["Custom Components", "E-commerce"],
    wrap: false,
    thumbnailUrl: "/images/product-card-thumbnail.png",
    hideFromContentCreators: false,
    hideFromComponentList: false,
    props: {
      productId: {
        type: "string",
        displayName: "Product ID",
        placeholder: "Enter product ID"
      },
      showPrice: {
        type: "boolean",
        displayName: "Show Price",
        defaultValue: true
      }
    },
    styles: {
      default: {
        styleSections: ["size", "spacing", "background", "border"],
        defaultClasses: ["product-card"],
        displayName: "Card Styles"
      },
      content: {
        styleSections: ["typography"],
        defaultClasses: ["product-content"],
        displayName: "Content Styles"
      }
    }
  }
]);

// Component with validation
registerComponents([
  {
    type: "contact-form",
    component: ContactForm,
    displayName: "Contact Form",
    description: "A form for collecting contact information",
    sections: ["Forms"],
    props: {
      email: {
        type: "string",
        displayName: "Email",
        placeholder: "Enter email address"
      }
    }
  }
]);

registerComponents

The registerComponents method makes custom React components available in Studio. Once registered, these components can be added, configured, and styled by content creators within the Studio interface alongside built-in components.

Returns

Type void

Parameters

NameTypeDescription
componentConfig (required)Component configuration objectOne or more component configurations to register.
optionsOptional registry configurationControls built-ins, overrides, and debugging.

Example

import { registerComponents } from '@contentstack/studio-react';

registerComponents(componentConfig, options);

Best Practices

  • Performance: Keep custom element renders lightweight and avoid complex DOM manipulation.
  • Accessibility: Use semantic HTML and include appropriate ARIA attributes to ensure custom elements are usable with assistive technologies.
  • Responsiveness: Apply CSS and layout techniques that adapt well across devices.
  • Consistency: Align custom elements with your design system to maintain a cohesive appearance across content.
  • Testing: Validate custom elements with varied content scenarios, edge cases, and real-world usage to ensure stability and reliability.

Note

  • Unique type Each component requires a unique identifier.
  • System protection Built-in components cannot be overridden.
  • Validation Props can include custom validation rules.
  • Styling Components have access to design tokens and CSS-in-JS.
  • Interactivity Use useHiddenElementNotification with wrap: false for interactive components.
  • Performance Components are registered once and cached for efficiency.