diff --git a/lib/draftjs_exporter/entities/attachmentlink.rb b/lib/draftjs_exporter/entities/attachmentlink.rb new file mode 100644 index 0000000..4b72bbf --- /dev/null +++ b/lib/draftjs_exporter/entities/attachmentlink.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +module DraftjsExporter + module Entities + class AttachmentLink + attr_reader :configuration + + def initialize(configuration = { className: nil }) + @configuration = configuration + end + + def call(parent_element, data) + # TODO add more detail about the link(s) and icons + args = { href: data.fetch(:data, {}).fetch(:url) } + args[:class] = configuration.fetch(:className) if configuration[:className] + args[:target] = "_blank" + + element = parent_element.document.create_element('a', args) + # Add the icon part, depending on the article or + extension = data.fetch(:data, {}).fetch(:fileExtension, nil) + icon_args = {} + icon_args[:class] = "extension #{extension}" + icon_element = element.document.create_element('span', extension, icon_args) + element.add_child(icon_element) + + # Then append the element as a whole + parent_element.add_child(element) + element + end + end + end +end diff --git a/lib/draftjs_exporter/entities/bonsailink.rb b/lib/draftjs_exporter/entities/bonsailink.rb new file mode 100644 index 0000000..c3fb414 --- /dev/null +++ b/lib/draftjs_exporter/entities/bonsailink.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true +module DraftjsExporter + module Entities + class Bonsailink + attr_reader :configuration + + def initialize(configuration = { className: nil }) + @configuration = configuration + end + + def call(parent_element, data) + # TODO add more detail about the link(s) and icons + args = { href: data.fetch(:data, {}).fetch(:url) } + args[:class] = configuration.fetch(:className) if configuration[:className] + + element = parent_element.document.create_element('a', args) + # Add the icon part, depending on the article or + style = data.fetch(:data, {}).fetch(:article_id, nil) ? "bonsai-content-article" : "bonsai-content-category" + icon_args = {} + icon_args[:class] = style + icon_element = element.document.create_element('span', icon_args) + element.add_child(icon_element) + + # Then append the element as a whole + parent_element.add_child(element) + element + end + end + end +end diff --git a/lib/draftjs_exporter/entities/image.rb b/lib/draftjs_exporter/entities/image.rb new file mode 100644 index 0000000..1b97b74 --- /dev/null +++ b/lib/draftjs_exporter/entities/image.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +module DraftjsExporter + module Entities + class Image + attr_reader :configuration + + def initialize(configuration = { className: nil }) + # Default styles for images + @configuration = configuration.merge({style: "position: relative; cursor: default; max-width: 100%; height: auto;"}) + end + + def call(parent_element, data) + args = { src: data.fetch(:data, {}).fetch(:src) } + args[:class] = configuration.fetch(:className) if configuration[:className] + + element = parent_element.document.create_element('img', args) + parent_element.add_child(element) + element + end + end + end +end diff --git a/lib/draftjs_exporter/entities/link.rb b/lib/draftjs_exporter/entities/link.rb index 008f985..a6d55e9 100644 --- a/lib/draftjs_exporter/entities/link.rb +++ b/lib/draftjs_exporter/entities/link.rb @@ -9,8 +9,18 @@ def initialize(configuration = { className: nil }) end def call(parent_element, data) - args = { href: data.fetch(:data, {}).fetch(:url) } + url = data.fetch(:data, {}).fetch(:url) + if url.present? && !url.start_with?("mailto:") && !(%w{http https}.include?(URI.parse(URI.escape(url)).scheme)) + if url =~ URI::MailTo::EMAIL_REGEXP + url = "mailto:#{url}" + else + url = "https://#{url}" + end + end + + args = { href: url } args[:class] = configuration.fetch(:className) if configuration[:className] + args[:target] = "_blank" element = parent_element.document.create_element('a', args) parent_element.add_child(element) diff --git a/lib/draftjs_exporter/entities/table.rb b/lib/draftjs_exporter/entities/table.rb new file mode 100644 index 0000000..6d89570 --- /dev/null +++ b/lib/draftjs_exporter/entities/table.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true +module DraftjsExporter + module Entities + class Table + attr_reader :configuration + + def initialize(configuration = { className: nil, wrapperClassName: nil }) + # Default styles for images + @configuration = configuration.merge({style: "position: relative; cursor: default; max-width: 100%; height: auto;"}) + end + + def call(parent_element, data) + tableData = data.fetch(:data, {}).fetch(:tableData, []) + args = {} + args[:class] = configuration.fetch(:className) if configuration[:className] + + wrapperArgs = {} + wrapperArgs[:class] = configuration.fetch(:wrapperClassName) if configuration[:wrapperClassName] + + # Create the wrapper
+ wrapperElement = parent_element.document.create_element('div', wrapperArgs) + # Create the main + tableElement = wrapperElement.document.create_element('table', args) + # Now, we need to add the rows and columns + tableData.each do |row| + # Create a for each row + trElement = tableElement.document.create_element('tr') + row.each do |cell| + # Add in the content, if styled, then apply styles + cellContent = cell + tdElement = trElement.document.create_element('td', cellContent) + trElement.add_child(tdElement) + end + tableElement.add_child(trElement) + end + wrapperElement.add_child(tableElement) + parent_element.add_child(wrapperElement) + wrapperElement + end + end + end +end diff --git a/lib/draftjs_exporter/entities/video.rb b/lib/draftjs_exporter/entities/video.rb new file mode 100644 index 0000000..91aea6c --- /dev/null +++ b/lib/draftjs_exporter/entities/video.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true +module DraftjsExporter + module Entities + class Video + attr_reader :configuration + + def initialize(configuration = { className: nil }) + # Default styles for images + @configuration = configuration.merge({allowfullscreen: "1", frameborder: "0", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"}) + end + + def call(parent_element, data) + # Check for youtube links, and change watch to embed in order to embed correctly + src = data.fetch(:data, {}).fetch(:src) + if src && src.include?("https://www.youtube.com/watch") + video_id = src.split("=")[1] + src = "https://www.youtube.com/embed/#{video_id}" + end + + args = { src: src} + args[:class] = configuration.fetch(:className) if configuration[:className] + args[:allowfullscreen] = configuration.fetch(:allowfullscreen) if configuration[:allowfullscreen] + args[:allow] = configuration.fetch(:allow) if configuration[:allow] + args[:frameborder] = configuration.fetch(:frameborder) if configuration[:frameborder] + + element = parent_element.document.create_element('iframe', args) + parent_element.add_child(element) + element + end + end + end +end diff --git a/lib/draftjs_exporter/entity_state.rb b/lib/draftjs_exporter/entity_state.rb index 4d8dd12..2138993 100644 --- a/lib/draftjs_exporter/entity_state.rb +++ b/lib/draftjs_exporter/entity_state.rb @@ -1,5 +1,11 @@ # frozen_string_literal: true +require 'draftjs_exporter/entities/link' +require 'draftjs_exporter/entities/bonsailink' +require 'draftjs_exporter/entities/attachmentlink' +require 'draftjs_exporter/entities/image' +require 'draftjs_exporter/entities/video' require 'draftjs_exporter/entities/null' +require 'draftjs_exporter/entities/table' require 'draftjs_exporter/error' module DraftjsExporter diff --git a/lib/draftjs_exporter/html.rb b/lib/draftjs_exporter/html.rb index 9a05065..f061db6 100644 --- a/lib/draftjs_exporter/html.rb +++ b/lib/draftjs_exporter/html.rb @@ -37,7 +37,7 @@ def block_contents(element, block, entity_map) style_state.apply(command) end - add_node(entity_state.current_parent, text, style_state) + add_node(entity_state.current_parent, text || "", style_state) end end