Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,29 @@ Marksmith accepts a few configuration options.

### Field options

The field supports a few of the regular options like `disabled`, `placeholder`, `autofocus`, `style`, `class`, `data`, and `value`, but also a custom one.
The field supports a few of the regular options like `disabled`, `placeholder`, `autofocus`, `style`, `data`, and `value`, but also a custom one.

`extra_preview_params` - Sends extra params to the preview renderer.

`enable_file_uploads` - Whether to enable file uploads.

`upload_url` - The URL to use for file uploads. If not provided, the editor will use the `rails_direct_uploads_url` helper.

`classes` - A hash of classes to be applied to the editor.

```erb
<%= marksmith_tag :body,
disabled: true,
placeholder: "Write your best markdown here.",
extra_preview_params: { foo: "bar" },
enable_file_uploads: true,
upload_url: nil
upload_url: nil,
classes: {
textarea: "bg-red-500",
editor_pane: "bg-blue-500",
preview_pane: "bg-green-500",
action_bar: "bg-yellow-500",
}
%>
```

Expand Down
1 change: 0 additions & 1 deletion app/controllers/marksmith/markdown_previews_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ def create
end
end
end

26 changes: 2 additions & 24 deletions app/helpers/marksmith/marksmith_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,16 @@ def marksmith_asset_tags(*args, **kwargs)
javascript_include_tag("marksmith.esm.js", *args, **kwargs)
end

def marksmith_button_classes
class_names(
"ms:flex ms:items:center ms:cursor-pointer ms:py-1 ms:px-1.5 ms:hover:bg-neutral-200 ms:rounded",
"ms:dark:text-neutral-300 ms:dark:hover:bg-neutral-600"
)
end

def marksmith_toolbar_button(name, hotkey_scope: nil, hotkey: nil, **kwargs)
def marksmith_toolbar_button(name, hotkey_scope: nil, hotkey: nil, editor: nil, **kwargs)
content_tag "md-#{name}", marksmith_toolbar_svg(name),
title: t("marksmith.#{name.to_s.gsub("-", "_")}").humanize,
class: marksmith_button_classes,
class: editor&.element_classes(:toolbar_button),
data: {
hotkey_scope:,
hotkey:
}
end

def marksmith_tab_classes
class_names(
# marksmith_button_classes,
"marksmith-toggle-button ms:text-sm ms:hover:bg-neutral-300 ms:text-sm ms:font-medium ms:cursor-pointer ms:text-neutral-500 ms:px-3",
# borders
"ms:bg-transparent ms:hover:bg-transparent",
"ms:-my-px ms:-ml-px ms:border ms:border-transparent",
"ms:h-[calc(100%+3px)] ms:border-b-none",
# "ms:border-b-neutral-00",
# active classes
"ms:[.active]:bg-neutral-50 ms:[.active]:text-neutral-900 ms:dark:[.active]:text-neutral-300 ms:[.active]:dark:bg-neutral-800 ms:[.active]:dark:border-neutral-500 ms:[.active]:rounded-t-md ms:[.active]:border-neutral-500",

)
end

def marksmith_inline_svg(path)
File.open(Marksmith::Engine.root.join(path)).read.html_safe
end
Expand Down
76 changes: 76 additions & 0 deletions app/models/marksmith/default_classes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
class Marksmith::DefaultClasses
include ActionView::Helpers::TagHelper

def self.for(element, **options)
new(element, **options).default_classes
end

def initialize(element, **options)
@element = element
@options = options
end

def default_classes
case @element
when :action_bar
class_names("ms:flex ms:flex-wrap ms:px-2 ms:py-1", "ms:pointer-events-none": @options[:disabled])
when :container
"marksmith ms:block ms:flex-col ms:w-full ms:border ms:border-neutral-500 ms:rounded-md ms:@container ms:focus-within:outline-2 ms:outline-blue-500 ms:-outline-offset-1"
when :editor_content
"ms:border-t ms:w-full ms:border-neutral-500 ms:flex ms:flex-1"
when :editor_pane
"ms:flex ms:flex-1 ms:flex-col ms:size-full"
when :editor_pane_footer
"ms:flex ms:flex-1 ms:flex-grow ms:space-x-2 ms:py-1 ms:border-t ms:border-neutral-500 ms:px-2 ms:font-sans ms:text-sm ms:p-2 ms:dark:bg-neutral-800 ms:dark:text-neutral-300 ms:rounded-b-md"
when :footer_gallery_link
class_names(
"ms:flex ms:items-center ms:text-neutral-800 ms:no-underline ms:gap-1",
self.class.for(:toolbar_button)
)
when :footer_markdown_link
class_names(
"ms:flex ms:items-center ms:text-neutral-800 ms:no-underline ms:gap-1",
self.class.for(:toolbar_button)
)
when :footer_upload_button
class_names(
"ms:bg-none ms:border-none ms:bg-transparent ms:text-neutral-600 ms:items-center ms:flex ms:gap-1",
self.class.for(:toolbar_button)
)
when :loading_spinner
"ms:button-spinner"
when :preview_pane
"ms:hidden ms:markdown-preview ms:size-full ms:flex-1 ms:flex ms:size-full ms:p-2 ms:overflow-auto ms:bg-white ms:dark:bg-neutral-800 ms:rounded-b-md"
when :rendered_body
"ms:block ms:w-full ms:prose ms:max-w-none ms:prose-neutral ms:dark:prose-invert"
when :tab_button
class_names(
# marksmith_button_classes,
"marksmith-toggle-button ms:text-sm ms:hover:bg-neutral-300 ms:text-sm ms:font-medium ms:cursor-pointer ms:text-neutral-500 ms:px-3",
# borders
"ms:bg-transparent ms:hover:bg-transparent",
"ms:-my-px ms:-ml-px ms:border ms:border-transparent",
"ms:h-[calc(100%+3px)] ms:border-b-none",
# "ms:border-b-neutral-00",
# active classes
"ms:[.active]:bg-neutral-50 ms:[.active]:text-neutral-900 ms:dark:[.active]:text-neutral-300 ms:[.active]:dark:bg-neutral-800 ms:[.active]:dark:border-neutral-500 ms:[.active]:rounded-t-md ms:[.active]:border-neutral-500",
)
when :tabs_container
"ms:flex-1 ms:flex ms:items-center"
when :textarea
class_names(
"ms:flex ms:flex-1 ms:border-none ms:resize-none ms:focus:outline-none ms:font-mono ms:focus:ring-0 ms:leading-normal ms:p-2 ms:text-sm ms:field-sizing-content ms:min-h-60",
"ms:dark:bg-neutral-800 ms:dark:text-neutral-200"
)
when :toolbar
class_names(
"ms:flex-1 ms:flex-col-reverse ms:@md:flex-row ms:grow ms:flex ms:justify-bewteen ms:bg-neutral-50 ms:rounded-t-md ms:gap-y-1",
"ms:dark:bg-neutral-700 ms:dark:text-neutral-200"
)
when :toolbar_button
"ms:cursor-pointer ms:hover:bg-neutral-200 ms:px-1 ms:py-px ms:rounded ms:text-sm ms:dark:text-neutral-300 ms:dark:hover:bg-neutral-600"
else
""
end
end
end
13 changes: 12 additions & 1 deletion app/models/marksmith/editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def initialize(name:,
form: nil,
disabled: false,
controller_data_attributes: {},
classes: nil,
classes: {},
data_attributes: {},
placeholder: nil,
autofocus: false,
Expand Down Expand Up @@ -52,6 +52,17 @@ def initialize(name:,
@gallery = gallery
end

def element_classes(element, **options)
# backwards compatibility
@classes = { textarea: @classes } if @classes.is_a?(String)

[
"ms--#{element.to_s.gsub('_', '-')}",
Marksmith::DefaultClasses.for(element, **options),
@classes[element]
].compact_blank.join(" ")
end

def gallery_enabled
gallery.fetch(:enabled, false)
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<%= turbo_stream.update params[:element_id] do %>
<%= render partial: "marksmith/shared/rendered_body", locals: { body: @body } %>
<% end %>

22 changes: 11 additions & 11 deletions app/views/marksmith/shared/_action_bar.html.erb
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<%= tag.markdown_toolbar for: textarea_id,
class: class_names("ms:flex ms:flex-wrap ms:px-2 ms:py-1", "ms:pointer-events-none": disabled),
class: editor.element_classes(:action_bar, disabled:),
data: { marksmith_target: "toolbar" } do
%>
<%= marksmith_toolbar_button "bold", hotkey: "Meta+b", hotkey_scope: textarea_id %>
<%= marksmith_toolbar_button "header", hotkey: "Meta+h", hotkey_scope: textarea_id %>
<%= marksmith_toolbar_button "italic", hotkey: "Meta+i", hotkey_scope: textarea_id %>
<%= marksmith_toolbar_button "quote" %>
<%= marksmith_toolbar_button "code" %>
<%= marksmith_toolbar_button "link" %>
<%= marksmith_toolbar_button "image" %>
<%= marksmith_toolbar_button "unordered-list" %>
<%= marksmith_toolbar_button "ordered-list" %>
<%= marksmith_toolbar_button "task-list" %>
<%= marksmith_toolbar_button "bold", hotkey: "Meta+b", hotkey_scope: textarea_id, editor: %>
<%= marksmith_toolbar_button "header", hotkey: "Meta+h", hotkey_scope: textarea_id, editor: %>
<%= marksmith_toolbar_button "italic", hotkey: "Meta+i", hotkey_scope: textarea_id, editor: %>
<%= marksmith_toolbar_button "quote", editor: %>
<%= marksmith_toolbar_button "code", editor: %>
<%= marksmith_toolbar_button "link", editor: %>
<%= marksmith_toolbar_button "image", editor: %>
<%= marksmith_toolbar_button "unordered-list", editor: %>
<%= marksmith_toolbar_button "ordered-list", editor: %>
<%= marksmith_toolbar_button "task-list", editor: %>
<% end %>
8 changes: 4 additions & 4 deletions app/views/marksmith/shared/_editor.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<%= content_tag :div,
id: editor.id,
class: "marksmith ms:block ms:flex-col ms:w-full ms:border ms:border-neutral-500 ms:rounded-md ms:@container ms:focus-within:outline-2 ms:outline-blue-500 ms:-outline-offset-1",
class: editor.element_classes(:container),
data: {
controller: "marksmith list-continuation",
action: "
Expand All @@ -15,9 +15,9 @@
marksmith_extra_preview_params_value: editor.extra_preview_params.as_json,
**editor.controller_data_attributes,
} do %>
<%= render partial: "marksmith/shared/toolbar", locals: { textarea_id: editor.textarea_id, disabled: editor.disabled} %>
<div class="ms:border-t ms:w-full ms:border-neutral-500 ms:flex ms:flex-1">
<%= render partial: "marksmith/shared/toolbar", locals: { textarea_id: editor.textarea_id, disabled: editor.disabled, editor: } %>
<%= content_tag :div, class: editor.element_classes(:editor_content) do %>
<%= render partial: "marksmith/shared/editor_pane", locals: { editor: } %>
<%= render partial: "marksmith/shared/preview_pane", locals: { editor: } %>
</div>
<% end %>
<% end %>
19 changes: 7 additions & 12 deletions app/views/marksmith/shared/_editor_pane.html.erb
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
<%= content_tag :div, class: "ms:flex ms:flex-1 ms:flex-col ms:size-full", data: { marksmith_target: "fieldContainer" } do %>
<%= content_tag :div, class: editor.element_classes(:editor_pane), data: { marksmith_target: "fieldContainer" } do %>
<%= text_area_tag editor.field_name, editor.value,
id: editor.textarea_id,
class: class_names(
"ms:flex ms:flex-1 ms:border-none ms:resize-none ms:focus:outline-none ms:font-mono ms:focus:ring-0 ms:leading-normal ms:p-2 ms:text-sm ms:field-sizing-content ms:min-h-60",
"ms:dark:bg-neutral-800 ms:dark:text-neutral-200",
editor.classes
),
class: editor.element_classes(:textarea),
data: {
action: "drop->marksmith#dropUpload paste->marksmith#pasteUpload",
marksmith_target: "fieldElement",
Expand All @@ -16,20 +12,19 @@
autofocus: editor.autofocus,
style: editor.style
%>
<% toolbar_button_classes = "ms:cursor-pointer ms:hover:bg-neutral-200 ms:px-1 ms:py-px ms:rounded ms:text-sm ms:dark:text-neutral-300 ms:dark:hover:bg-neutral-600" %>
<div class="ms:flex ms:flex-1 ms:flex-grow ms:space-x-2 ms:py-1 ms:border-t ms:border-neutral-500 ms:px-2 ms:font-sans ms:text-sm ms:p-2 ms:dark:bg-neutral-800 ms:dark:text-neutral-300 ms:rounded-b-md">
<%= link_to "https://docs.github.com/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax", target: "_blank", class: class_names("ms:flex ms:items-center ms:text-neutral-800 ms:no-underline ms:gap-1", toolbar_button_classes) do %>
<%= content_tag :div, class: editor.element_classes(:editor_pane_footer) do %>
<%= link_to "https://docs.github.com/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax", target: "_blank", class: editor.element_classes(:footer_markdown_link) do %>
<%= marksmith_inline_svg("app/assets/images/marksmith/svgs/markdown.svg") %> <span><%= t("marksmith.markdown_is_supported").humanize %></span>
<% end %>
<% if editor.enable_file_uploads %>
<%= button_tag data: { action: "click->marksmith#buttonUpload" }, class: class_names("ms:bg-none ms:border-none ms:bg-transparent ms:text-neutral-600 ms:items-center ms:flex ms:gap-1", toolbar_button_classes) do %>
<%= button_tag data: { action: "click->marksmith#buttonUpload" }, class: editor.element_classes(:footer_upload_button) do %>
<%= marksmith_inline_svg("app/assets/images/marksmith/svgs/paperclip.svg") %> <span><%= t("marksmith.upload_files").humanize %></span>
<% end %>
<% end %>
<% if editor.gallery_enabled %>
<%= link_to editor.gallery_full_path, data: { turbo_frame: editor.gallery_turbo_frame }, class: class_names("ms:flex ms:items-center ms:text-neutral-800 ms:no-underline ms:gap-1", toolbar_button_classes) do %>
<%= link_to editor.gallery_full_path, data: { turbo_frame: editor.gallery_turbo_frame }, class: editor.element_classes(:footer_gallery_link) do %>
<%= marksmith_inline_svg("app/assets/images/marksmith/svgs/gallery.svg") %> <span><%= t("marksmith.attach_from_gallery").humanize %></span>
<% end %>
<% end %>
</div>
<% end %>
<% end %>
4 changes: 2 additions & 2 deletions app/views/marksmith/shared/_loading_indicator.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="ms:button-spinner">
<%= content_tag :div, class: editor.element_classes(:loading_spinner) do %>
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
<% end %>
4 changes: 2 additions & 2 deletions app/views/marksmith/shared/_preview_pane.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<%= content_tag :div,
class: "ms:hidden ms:markdown-preview ms:size-full ms:flex-1 ms:flex ms:size-full ms:p-2 ms:overflow-auto ms:bg-white ms:dark:bg-neutral-800 ms:rounded-b-md",
class: editor.element_classes(:preview_pane),
id: editor.preview_pane_id,
data: {
marksmith_target: "previewPane",
} do %>
<%= render partial: "marksmith/shared/loading_indicator" %>
<%= render partial: "marksmith/shared/loading_indicator", locals: { editor: } %>
<% end %>
2 changes: 1 addition & 1 deletion app/views/marksmith/shared/_rendered_body.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<%= content_tag :div, class: "ms:block ms:w-full ms:prose ms:max-w-none ms:prose-neutral ms:dark:prose-invert" do %>
<%= content_tag :div, class: class_names("ms--rendered-body", Marksmith::DefaultClasses.for(:rendered_body)) do %>
<%= sanitize(body, tags: %w(table th tr td span) + ActionView::Helpers::SanitizeHelper.sanitizer_vendor.safe_list_sanitizer.allowed_tags.to_a) %>
<% end %>
16 changes: 8 additions & 8 deletions app/views/marksmith/shared/_tabs.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div class="ms:flex-1 ms:flex ms:items:center">
<button class="<%= marksmith_tab_classes %> active" data-action="click->marksmith#switchToWrite" data-marksmith-target="writeTabButton" type="button">
<%= t('marksmith.write').humanize %>
</button>
<button class="<%= marksmith_tab_classes %>" data-action="click->marksmith#switchToPreview" data-marksmith-target="previewTabButton" type="button">
<%= t('marksmith.preview').humanize %>
</button>
</div>
<%= content_tag :div, class: editor.element_classes(:tabs_container) do %>
<%= button_tag type: "button", class: class_names(editor.element_classes(:tab_button), "active"), data: { action: "click->marksmith#switchToWrite", marksmith_target: "writeTabButton" } do %>
<%= t("marksmith.write").humanize %>
<% end %>
<%= button_tag type: "button", class: editor.element_classes(:tab_button), data: { action: "click->marksmith#switchToPreview", marksmith_target: "previewTabButton" } do %>
<%= t("marksmith.preview").humanize %>
<% end %>
<% end %>
10 changes: 3 additions & 7 deletions app/views/marksmith/shared/_toolbar.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
<%= tag.div class: class_names(
"ms:flex-1 ms:flex-col-reverse ms:@md:flex-row ms:grow ms:flex ms:justify-bewteen ms:bg-neutral-50 ms:rounded-t-md ms:gap-y-1",
"ms:dark:bg-neutral-700 ms:dark:text-neutral-200"
) do %>
<%= render partial: "marksmith/shared/tabs" %>

<%= render partial: "marksmith/shared/action_bar", locals: { textarea_id:, disabled: } %>
<%= tag.div class: editor.element_classes(:toolbar) do %>
<%= render partial: "marksmith/shared/tabs", locals: { editor: } %>
<%= render partial: "marksmith/shared/action_bar", locals: { textarea_id:, disabled:, editor: } %>
<% end %>