Low commit activity in last 3 years
Draft.js is a framework for building rich text editors. However, it does not support exporting documents at HTML. This gem is designed to take the raw `ContentState` (output of `convertToRaw`) from Draft.js and convert it to HTML using Ruby. This is a Zero One fork of the `draftjs_exporter` gem, published separately as `zo_draftjs_exporter`. It adds a `block_callback:` hook invoked after each block is rendered, and support for `className` entries in the `style_map` so inline styles can emit CSS classes alongside inline `style` attributes. It keeps the upstream `draftjs_exporter` require paths and `DraftjsExporter` namespace, so it cannot be installed alongside the original gem.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 3.4, >= 3.4.0
~> 0.40, >= 0.40.0
~> 0.11, >= 0.11.0

Runtime

~> 1.6, >= 1.6.0
 Project Readme

Draft.js Exporter (Zero One fork)

This is a Zero One fork of ignitionworks/draftjs_exporter, published to RubyGems as zo_draftjs_exporter.

It keeps the upstream draftjs_exporter require paths and DraftjsExporter namespace, so it is a drop-in replacement for the original gem — but for the same reason the two cannot be installed side by side. See Fork changes for what differs from upstream.

# Gemfile — note the `require:`, see Installation below
gem 'zo_draftjs_exporter', '~> 0.0.7', require: 'draftjs_exporter'

Draft.js is a framework for building rich text editors. However, it does not support exporting documents at HTML. This gem is designed to take the raw ContentState (output of convertToRaw) from Draft.js and convert it to HTML using Ruby.

Installation

# Gemfile
gem 'zo_draftjs_exporter', '~> 0.0.7', require: 'draftjs_exporter'

The require: option is required. The gem is published as zo_draftjs_exporter, but to stay a drop-in replacement for upstream it still ships its code at lib/draftjs_exporter/ under the DraftjsExporter namespace. The package name and the require path therefore differ, and Bundler auto-requires the package name by default — require 'zo_draftjs_exporter' — which does not exist.

Worse, that failure is silent. Bundler only raises a missing-file LoadError when the gem name contains a - it can retry as a /; zo_draftjs_exporter has none, so the error is swallowed and the gem simply never loads. You find out later, somewhere unrelated:

NameError: uninitialized constant DraftjsExporter::HTML

So if you omit require:, nothing appears to go wrong at boot. Set it.

Requiring by hand (outside Bundler) uses the same path:

require 'draftjs_exporter'                      # => DraftjsExporter::HTML

Note that this loads DraftjsExporter::HTML only. Entity decorators are not pulled in by the entry point, so require any you configure:

require 'draftjs_exporter/entities/link'        # => DraftjsExporter::Entities::Link

Because the require paths and namespace are shared with upstream draftjs_exporter, the two gems cannot be installed alongside each other — remove the original if it is still in your Gemfile.

Usage

# Create configuration for entities and styles
config = {
  entity_decorators: {
    'LINK' => DraftjsExporter::Entities::Link.new(className: 'link')
  },
  block_map: {
    'header-one' => { element: 'h1' },
    'unordered-list-item' => {
      element: 'li',
      wrapper: ['ul', { className: 'public-DraftStyleDefault-ul' }]
    },
    'unstyled' => { element: 'div' }
  },
  style_map: {
    'ITALIC' => { fontStyle: 'italic' }
  }
}

# New up the exporter
exporter = DraftjsExporter::HTML.new(config)

# Provide raw content state
exporter.call({
  entityMap: {
    '0' => {
      type: 'LINK',
      mutability: 'MUTABLE',
      data: {
        url: 'http://example.com'
      }
    }
  },
  blocks: [
    {
      key: '5s7g9',
      text: 'Header',
      type: 'header-one',
      depth: 0,
      inlineStyleRanges: [],
      entityRanges: []
    },
    {
      key: 'dem5p',
      text: 'some paragraph text',
      type: 'unstyled',
      depth: 0,
      inlineStyleRanges: [
        {
          offset: 0,
          length: 4,
          style: 'ITALIC'
        }
      ],
      entityRanges: [
        {
          offset: 5,
          length: 9,
          key: 0
        }
      ]
    }
  ]
})
# => "<h1>Header</h1><div>\n<span style=\"font-style: italic;\">some</span> <a href=\"http://example.com\" class=\"link\">paragraph</a> text</div>"

Fork changes

Changes in this fork that are not in upstream draftjs_exporter:

block_callback: — hook after each block

Pass a callable to be invoked with the rendered element and the source block, after each block is processed. Useful for post-processing or collecting metadata as the document is built.

exporter = DraftjsExporter::HTML.new(
  block_map: block_map,
  style_map: style_map,
  entity_decorators: entity_decorators,
  block_callback: ->(element, block) { puts "rendered #{block[:type]}" }
)

className in style_map — CSS classes for inline styles

A style_map entry may include a className: key. Matching text is given that class, and any remaining keys in the entry are still emitted as an inline style attribute. Classes from multiple applied styles are joined with a space.

style_map = {
  'ITALIC' => { fontStyle: 'italic' },
  'HIGHLIGHT' => { className: 'highlight' },
  'BIG_RED' => { className: 'big', color: 'red' }
}
# 'BIG_RED' text renders as: <span style="color: red;" class="big">...</span>

Note that a className-only entry still emits an empty style="" attribute (<span style="" class="highlight">), as the style attribute is always set.

Tests

$ rspec