block_editor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +147 -0
- data/Rakefile +18 -0
- data/app/assets/config/block_editor_manifest.js +1 -0
- data/app/assets/stylesheets/block_editor/backend.scss +4 -0
- data/app/assets/stylesheets/block_editor/backend/blocks.scss +0 -0
- data/app/assets/stylesheets/block_editor/frontend.scss +1 -0
- data/app/assets/stylesheets/block_editor/frontend/blocks.scss +0 -0
- data/app/controllers/block_editor/application_controller.rb +4 -0
- data/app/helpers/block_editor/application_helper.rb +11 -0
- data/app/javascript/block_editor/blocks/button/edit.js +240 -0
- data/app/javascript/block_editor/blocks/column/edit.js +93 -0
- data/app/javascript/block_editor/blocks/image/edit.js +656 -0
- data/app/javascript/block_editor/blocks/index.js +263 -0
- data/app/javascript/block_editor/components/block-editor/index.js +88 -0
- data/app/javascript/block_editor/components/block-editor/styles.scss +39 -0
- data/app/javascript/block_editor/components/header/index.js +45 -0
- data/app/javascript/block_editor/components/header/redo.js +36 -0
- data/app/javascript/block_editor/components/header/styles.scss +14 -0
- data/app/javascript/block_editor/components/header/undo.js +36 -0
- data/app/javascript/block_editor/components/media-upload/index.js +37 -0
- data/app/javascript/block_editor/components/notices/index.js +26 -0
- data/app/javascript/block_editor/components/notices/styles.scss +9 -0
- data/app/javascript/block_editor/components/sidebar/index.js +31 -0
- data/app/javascript/block_editor/components/sidebar/styles.scss +43 -0
- data/app/javascript/block_editor/stores/action-types.js +4 -0
- data/app/javascript/block_editor/stores/actions.js +41 -0
- data/app/javascript/block_editor/stores/controls.js +21 -0
- data/app/javascript/block_editor/stores/index.js +30 -0
- data/app/javascript/block_editor/stores/reducer.js +20 -0
- data/app/javascript/block_editor/stores/resolvers.js +10 -0
- data/app/javascript/block_editor/stores/selectors.js +13 -0
- data/app/javascript/controllers/block_editor_controller.jsx +42 -0
- data/app/javascript/controllers/index.js +6 -0
- data/app/javascript/packs/block_editor/application.js +2 -0
- data/app/javascript/packs/block_editor/application.scss +108 -0
- data/app/jobs/block_editor/application_job.rb +4 -0
- data/app/mailers/block_editor/application_mailer.rb +6 -0
- data/app/models/block_editor/application_record.rb +5 -0
- data/app/models/block_editor/block_list.rb +7 -0
- data/app/models/concerns/block_editor/listable.rb +24 -0
- data/app/views/layouts/block_editor/application.html.erb +15 -0
- data/config/initializers/webpacker_extension.rb +12 -0
- data/config/routes.rb +2 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +3 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +92 -0
- data/db/migrate/20210312032114_create_block_lists.rb +11 -0
- data/lib/block_editor.rb +26 -0
- data/lib/block_editor/block_list_renderer.rb +43 -0
- data/lib/block_editor/blocks/base.rb +32 -0
- data/lib/block_editor/engine.rb +34 -0
- data/lib/block_editor/instance.rb +19 -0
- data/lib/block_editor/version.rb +3 -0
- data/lib/tasks/block_editor_tasks.rake +59 -0
- metadata +131 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
module BlockEditor
|
2
|
+
module Listable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
has_many :block_lists, as: :listable, class_name: 'BlockEditor::BlockList'
|
7
|
+
has_one :active_block_list, -> { where active: true }, class_name: 'BlockEditor::BlockList', as: :listable
|
8
|
+
|
9
|
+
validates :active_block_list, presence: true
|
10
|
+
|
11
|
+
accepts_nested_attributes_for :active_block_list
|
12
|
+
|
13
|
+
after_initialize :set_block_list_defaults
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def set_block_list_defaults
|
19
|
+
return if self.persisted?
|
20
|
+
|
21
|
+
self.active_block_list ||= self.build_active_block_list(listable: self)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Webpacker::DynamicTag
|
2
|
+
def javascript_pack_tag(*names, **options)
|
3
|
+
return super unless options[:webpacker]
|
4
|
+
new_helper = self.dup
|
5
|
+
new_helper.define_singleton_method(:current_webpacker_instance) do
|
6
|
+
options[:webpacker].constantize.webpacker
|
7
|
+
end
|
8
|
+
new_helper.javascript_pack_tag(*names, **options.except(:webpacker))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Webpacker::Helper.prepend Webpacker::DynamicTag
|
data/config/routes.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Note: You must restart bin/webpack-dev-server for changes to take effect
|
2
|
+
|
3
|
+
default: &default
|
4
|
+
source_path: app/javascript
|
5
|
+
source_entry_path: packs
|
6
|
+
public_root_path: public
|
7
|
+
public_output_path: packs
|
8
|
+
cache_path: tmp/cache/webpacker
|
9
|
+
webpack_compile_output: true
|
10
|
+
|
11
|
+
# Additional paths webpack should lookup modules
|
12
|
+
# ['app/assets', 'engine/foo/app/assets']
|
13
|
+
additional_paths: []
|
14
|
+
|
15
|
+
# Reload manifest.json on all requests so we reload latest compiled packs
|
16
|
+
cache_manifest: false
|
17
|
+
|
18
|
+
# Extract and emit a css file
|
19
|
+
extract_css: false
|
20
|
+
|
21
|
+
static_assets_extensions:
|
22
|
+
- .jpg
|
23
|
+
- .jpeg
|
24
|
+
- .png
|
25
|
+
- .gif
|
26
|
+
- .tiff
|
27
|
+
- .ico
|
28
|
+
- .svg
|
29
|
+
- .eot
|
30
|
+
- .otf
|
31
|
+
- .ttf
|
32
|
+
- .woff
|
33
|
+
- .woff2
|
34
|
+
|
35
|
+
extensions:
|
36
|
+
- .mjs
|
37
|
+
- .js
|
38
|
+
- .sass
|
39
|
+
- .scss
|
40
|
+
- .css
|
41
|
+
- .module.sass
|
42
|
+
- .module.scss
|
43
|
+
- .module.css
|
44
|
+
- .png
|
45
|
+
- .svg
|
46
|
+
- .gif
|
47
|
+
- .jpeg
|
48
|
+
- .jpg
|
49
|
+
|
50
|
+
development:
|
51
|
+
<<: *default
|
52
|
+
compile: true
|
53
|
+
|
54
|
+
# Reference: https://webpack.js.org/configuration/dev-server/
|
55
|
+
dev_server:
|
56
|
+
https: false
|
57
|
+
host: localhost
|
58
|
+
port: 3035
|
59
|
+
public: localhost:3035
|
60
|
+
hmr: false
|
61
|
+
# Inline should be set to true if using HMR
|
62
|
+
inline: true
|
63
|
+
overlay: true
|
64
|
+
compress: true
|
65
|
+
disable_host_check: true
|
66
|
+
use_local_ip: false
|
67
|
+
quiet: false
|
68
|
+
pretty: false
|
69
|
+
headers:
|
70
|
+
'Access-Control-Allow-Origin': '*'
|
71
|
+
watch_options:
|
72
|
+
ignored: '**/node_modules/**'
|
73
|
+
|
74
|
+
|
75
|
+
test:
|
76
|
+
<<: *default
|
77
|
+
compile: true
|
78
|
+
|
79
|
+
# Compile test packs to a separate directory
|
80
|
+
public_output_path: packs-test
|
81
|
+
|
82
|
+
production:
|
83
|
+
<<: *default
|
84
|
+
|
85
|
+
# Production depends on precompilation of packs prior to booting for performance.
|
86
|
+
compile: false
|
87
|
+
|
88
|
+
# Extract and emit a css file
|
89
|
+
extract_css: true
|
90
|
+
|
91
|
+
# Cache manifest.json for performance
|
92
|
+
cache_manifest: true
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class CreateBlockLists < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
create_table :block_editor_block_lists do |t|
|
4
|
+
t.string :name
|
5
|
+
t.text :content
|
6
|
+
t.boolean :active, default: false
|
7
|
+
t.references :listable, polymorphic: true
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/block_editor.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "block_editor/version"
|
2
|
+
require "block_editor/engine"
|
3
|
+
|
4
|
+
require "block_editor/instance"
|
5
|
+
require 'block_editor/blocks/base'
|
6
|
+
require 'block_editor/block_list_renderer'
|
7
|
+
|
8
|
+
module BlockEditor
|
9
|
+
ROOT_PATH = Pathname.new(File.join(__dir__, ".."))
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def webpacker
|
13
|
+
@webpacker ||= ::Webpacker::Instance.new(
|
14
|
+
root_path: ROOT_PATH,
|
15
|
+
config_path: ROOT_PATH.join("config/webpacker.yml")
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
mattr_accessor :dynamic_blocks
|
21
|
+
@@dynamic_blocks = []
|
22
|
+
|
23
|
+
mattr_accessor :frontend_parent_controller
|
24
|
+
@@frontend_parent_controller = 'ApplicationController'
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module BlockEditor
|
2
|
+
# Handles the rendering of a block list including dynamic blocks and removing HTML comments
|
3
|
+
class BlockListRenderer
|
4
|
+
# Renders dynamic blocks within the HTML snippet then strips all HTML comments (including Gutenberg markup)
|
5
|
+
#
|
6
|
+
# @param raw_html [String]
|
7
|
+
#
|
8
|
+
# @return [String] Parsed content
|
9
|
+
def self.render(raw_html)
|
10
|
+
html = Nokogiri::HTML(raw_html)
|
11
|
+
|
12
|
+
# # Find & render all instances of a dynamic block
|
13
|
+
BlockEditor.dynamic_blocks.each do |dynamic_block|
|
14
|
+
html.xpath('//comment()').select {|comment| comment.inner_text.starts_with?(" wp:#{dynamic_block.name}") }.each do |block_instance|
|
15
|
+
block_attributes = block_instance.inner_text.split(" wp:#{dynamic_block.name}")[1][0...-1]
|
16
|
+
block_attributes = block_attributes.blank? ? {} : JSON.parse(block_attributes)
|
17
|
+
block_instance.replace(render_block(dynamic_block, block_attributes))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
html.xpath('//comment()').remove
|
22
|
+
html.css('body').inner_html.html_safe
|
23
|
+
end
|
24
|
+
|
25
|
+
# Renders a specific block using the provided options
|
26
|
+
#
|
27
|
+
# @param block [String] name of block
|
28
|
+
# @param options [Hash] block options to use when rendering
|
29
|
+
#
|
30
|
+
# @return [String] block content (HTML)
|
31
|
+
def self.render_block(block, options)
|
32
|
+
block.render(options)
|
33
|
+
rescue StandardError => e
|
34
|
+
respond_with_block_error(e)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Handles block errors
|
38
|
+
def self.respond_with_block_error(error)
|
39
|
+
Rails.logger.error("Error rendering block - #{error.message}")
|
40
|
+
''
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module BlockEditor
|
2
|
+
# Blocks used to render dynamic content
|
3
|
+
module Blocks
|
4
|
+
# Base for dynamic blocks
|
5
|
+
class Base
|
6
|
+
def self.name
|
7
|
+
raise NotImplementedError, 'Must specify block name'
|
8
|
+
end
|
9
|
+
|
10
|
+
# Render the block
|
11
|
+
def self.render(options = {})
|
12
|
+
options = options.reverse_merge(default_options.with_indifferent_access)
|
13
|
+
|
14
|
+
controller.render(
|
15
|
+
partial: "block_editor/blocks/#{name}/block",
|
16
|
+
locals: { collection: options },
|
17
|
+
layout: false
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Frontend controller used to render views
|
22
|
+
def self.controller
|
23
|
+
BlockEditor.frontend_parent_controller.constantize
|
24
|
+
end
|
25
|
+
|
26
|
+
# Default widget options
|
27
|
+
def self.default_options
|
28
|
+
{}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module BlockEditor
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace BlockEditor
|
4
|
+
|
5
|
+
initializer "webpacker.proxy" do |app|
|
6
|
+
insert_middleware = begin
|
7
|
+
BlockEditor.webpacker.config.dev_server.present?
|
8
|
+
rescue
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
next unless insert_middleware
|
12
|
+
|
13
|
+
app.middleware.insert_before(
|
14
|
+
0, Webpacker::DevServerProxy,
|
15
|
+
ssl_verify_none: true,
|
16
|
+
webpacker: BlockEditor.webpacker
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Initializer to combine this engines static assets with the static assets of the host application
|
21
|
+
initializer 'static assets' do |app|
|
22
|
+
app.middleware.insert_before(::ActionDispatch::Static, ::ActionDispatch::Static, "#{root}/public")
|
23
|
+
end
|
24
|
+
|
25
|
+
initializer 'block_editor.assets.precompile' do |app|
|
26
|
+
assets_for_precompile = [
|
27
|
+
'block_editor/frontend.css',
|
28
|
+
'block_editor/backend.css'
|
29
|
+
]
|
30
|
+
|
31
|
+
app.config.assets.precompile.concat assets_for_precompile
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BlockEditor
|
2
|
+
class Instance
|
3
|
+
include ActionView::Helpers::TagHelper
|
4
|
+
include ActionView::Helpers::FormTagHelper
|
5
|
+
|
6
|
+
attr_accessor :output_buffer
|
7
|
+
|
8
|
+
def self.render(form_builder)
|
9
|
+
self.new.render(form_builder)
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(form_builder)
|
13
|
+
content_tag(:div, data: { controller: 'block-editor' }) do
|
14
|
+
form_builder.hidden_field(:content, data: { 'block-editor-target' => 'input' }) +
|
15
|
+
content_tag('div', nil, { class: 'block-editor', data: { 'block-editor-target' => 'output' } })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
def ensure_log_goes_to_stdout
|
2
|
+
old_logger = Webpacker.logger
|
3
|
+
Webpacker.logger = ActiveSupport::Logger.new(STDOUT)
|
4
|
+
yield
|
5
|
+
ensure
|
6
|
+
Webpacker.logger = old_logger
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
namespace :block_editor do
|
11
|
+
namespace :webpacker do
|
12
|
+
desc "Install deps with yarn"
|
13
|
+
task :yarn_install do
|
14
|
+
Dir.chdir(File.join(__dir__, "../..")) do
|
15
|
+
system "yarn install --no-progress --production"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Compile JavaScript packs using webpack for production with digests"
|
20
|
+
task compile: [:yarn_install, :environment] do
|
21
|
+
Webpacker.with_node_env("production") do
|
22
|
+
ensure_log_goes_to_stdout do
|
23
|
+
if BlockEditor.webpacker.commands.compile
|
24
|
+
# Successful compilation!
|
25
|
+
else
|
26
|
+
# Failed compilation
|
27
|
+
exit!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def yarn_install_available?
|
36
|
+
rails_major = Rails::VERSION::MAJOR
|
37
|
+
rails_minor = Rails::VERSION::MINOR
|
38
|
+
|
39
|
+
rails_major > 5 || (rails_major == 5 && rails_minor >= 1)
|
40
|
+
end
|
41
|
+
|
42
|
+
def enhance_assets_precompile
|
43
|
+
# yarn:install was added in Rails 5.1
|
44
|
+
deps = yarn_install_available? ? [] : ["block_editor:webpacker:yarn_install"]
|
45
|
+
Rake::Task["assets:precompile"].enhance(deps) do
|
46
|
+
Rake::Task["block_editor:webpacker:compile"].invoke
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Compile packs after we've compiled all other assets during precompilation
|
51
|
+
skip_webpacker_precompile = %w(no false n f).include?(ENV["WEBPACKER_PRECOMPILE"])
|
52
|
+
|
53
|
+
unless skip_webpacker_precompile
|
54
|
+
if Rake::Task.task_defined?("assets:precompile")
|
55
|
+
enhance_assets_precompile
|
56
|
+
else
|
57
|
+
Rake::Task.define_task("assets:precompile" => "block_editor:webpacker:compile")
|
58
|
+
end
|
59
|
+
end
|