marksmith 0.0.13 → 0.0.16

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.
@@ -1,5 +1,5 @@
1
- /*! tailwindcss v4.0.0 | MIT License | https://tailwindcss.com */
2
- :root {
1
+ /*! tailwindcss v4.0.1 | MIT License | https://tailwindcss.com */
2
+ :root, :host {
3
3
  --ms-font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
4
4
  'Segoe UI Symbol', 'Noto Color Emoji';
5
5
  --ms-font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
@@ -788,6 +788,9 @@
788
788
  margin-bottom: 0;
789
789
  }
790
790
  }
791
+ .ms\:mr-1 {
792
+ margin-right: calc(var(--ms-spacing) * 1);
793
+ }
791
794
  .ms\:block {
792
795
  display: block;
793
796
  }
@@ -841,9 +844,6 @@
841
844
  .ms\:items-center {
842
845
  align-items: center;
843
846
  }
844
- .ms\:gap-x-2 {
845
- column-gap: calc(var(--ms-spacing) * 2);
846
- }
847
847
  .ms\:gap-y-1 {
848
848
  row-gap: calc(var(--ms-spacing) * 1);
849
849
  }
@@ -0,0 +1,22 @@
1
+ <%= field_wrapper **field_wrapper_args, full_width: true do %>
2
+ <%= @form.marksmith @field.id,
3
+ gallery: {
4
+ enabled: true,
5
+ open_path: avo.attach_media_path,
6
+ turbo_frame: ::Avo::MODAL_FRAME_ID,
7
+ params: {
8
+ resource_name: @resource.singular_route_key,
9
+ controller_name: "marksmith",
10
+ controller_selector: "[data-unique-selector='#{unique_id}']",
11
+ record_id: @resource&.record&.to_param,
12
+ }
13
+ },
14
+ controller_data_attributes: {
15
+ unique_selector: unique_id, # it must coincide with the selector above
16
+ },
17
+ extra_preview_params: {
18
+ resource_class: @resource.class.name,
19
+ field_id: field.id,
20
+ }
21
+ %>
22
+ <% end %>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Marksmith::MarkdownField::EditComponent < Avo::Fields::EditComponent
4
+ def unique_id
5
+ [@field.type, @resource&.singular_route_key, @field.id].compact.join("_")
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ <%= field_wrapper **field_wrapper_args, full_width: true do %>
2
+ <%= render partial: "marksmith/shared/rendered_body", locals: { body: Marksmith::Renderer.new.renderer.render(@field.value) } %>
3
+ <% end %>
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Marksmith::MarkdownField::ShowComponent < Avo::Fields::ShowComponent
4
+ end
@@ -15,6 +15,8 @@ export default class extends Controller {
15
15
  previewUrl: String,
16
16
  extraPreviewParams: { type: Object, default: {} },
17
17
  fieldId: String,
18
+ galleryEnabled: { type: Boolean, default: false },
19
+ galleryOpenPath: String,
18
20
  }
19
21
 
20
22
  static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
@@ -67,14 +69,14 @@ export default class extends Controller {
67
69
 
68
70
  dropUpload(event) {
69
71
  event.preventDefault()
70
- this.uploadFiles(event.dataTransfer.files)
72
+ this.#uploadFiles(event.dataTransfer.files)
71
73
  }
72
74
 
73
75
  pasteUpload(event) {
74
76
  if (!event.clipboardData.files.length) return
75
77
 
76
78
  event.preventDefault()
77
- this.uploadFiles(event.clipboardData.files)
79
+ this.#uploadFiles(event.clipboardData.files)
78
80
  }
79
81
 
80
82
  buttonUpload(event) {
@@ -86,40 +88,58 @@ export default class extends Controller {
86
88
  fileInput.accept = 'image/*,.pdf,.doc,.docx,.txt'
87
89
 
88
90
  fileInput.addEventListener('change', (e) => {
89
- this.uploadFiles(e.target.files)
91
+ this.#uploadFiles(e.target.files)
90
92
  })
91
93
 
92
94
  fileInput.click()
93
95
  }
94
96
 
95
- uploadFiles(files) {
96
- Array.from(files).forEach((file) => this.uploadFile(file))
97
+ // Invoked by the other controllers (media-library)
98
+ insertAttachments(attachments, event) {
99
+ const editorAttachments = attachments.map((attachment) => {
100
+ const { blob, path, url } = attachment
101
+ const link = this.#markdownLinkFromUrl(blob.filename, path, blob.content_type)
102
+
103
+ this.#injectLink(link)
104
+ })
105
+
106
+ this.editor?.chain().focus().setAttachment(editorAttachments).run();
107
+ }
108
+
109
+ #uploadFiles(files) {
110
+ Array.from(files).forEach((file) => this.#uploadFile(file))
97
111
  }
98
112
 
99
- uploadFile(file) {
113
+ #uploadFile(file) {
100
114
  const upload = new DirectUpload(file, this.attachUrlValue)
101
115
 
102
116
  upload.create((error, blob) => {
103
117
  if (error) {
104
118
  console.log('Error', error)
105
119
  } else {
106
- const text = this.markdownLink(blob)
107
- const start = this.fieldElementTarget.selectionStart
108
- const end = this.fieldElementTarget.selectionEnd
109
- this.fieldElementTarget.setRangeText(text, start, end)
120
+ const link = this.#markdownLinkFromUrl(blob.filename, this.#pathFromBlob(blob), blob.content_type)
121
+ this.#injectLink(link)
110
122
  }
111
123
  })
112
124
  }
113
125
 
114
- markdownLink(blob) {
115
- const { filename } = blob
116
- const url = `/rails/active_storage/blobs/${blob.signed_id}/${filename}`
117
- const prefix = (this.isImage(blob.content_type) ? '!' : '')
126
+ #injectLink(link) {
127
+ const start = this.fieldElementTarget.selectionStart
128
+ const end = this.fieldElementTarget.selectionEnd
129
+ this.fieldElementTarget.setRangeText(link, start, end)
130
+ }
131
+
132
+ #pathFromBlob(blob) {
133
+ return `/rails/active_storage/blobs/redirect/${blob.signed_id}/${blob.filename}`
134
+ }
135
+
136
+ #markdownLinkFromUrl(filename, url, contentType) {
137
+ const prefix = (this.#isImage(contentType) ? '!' : '')
118
138
 
119
139
  return `${prefix}[${filename}](${url})\n`
120
140
  }
121
141
 
122
- isImage(contentType) {
142
+ #isImage(contentType) {
123
143
  return ['image/jpeg', 'image/gif', 'image/png'].includes(contentType)
124
144
  }
125
145
  }
@@ -13,6 +13,17 @@
13
13
  local_assigns[:value] || nil
14
14
  end
15
15
  extra_preview_params = local_assigns[:extra_preview_params] || {}
16
+
17
+ # Used by Avo and other adapters to enable the gallery link.
18
+ gallery_enabled = local_assigns.dig(:gallery, :enabled) || false
19
+ gallery_open_path = local_assigns.dig(:gallery, :open_path) || nil
20
+ gallery_params = local_assigns.dig(:gallery, :params) || {}
21
+ if gallery_open_path.present?
22
+ gallery_full_path = gallery_open_path + "?" + gallery_params.map { |k,v| "#{k}=#{v}" }.join('&')
23
+ else
24
+ gallery_full_path = nil
25
+ end
26
+ gallery_turbo_frame = local_assigns.dig(:gallery, :turbo_frame) || nil
16
27
  %>
17
28
  <%= content_tag :div,
18
29
  class: "ms:block ms:flex-col ms:w-full ms:border ms:border-neutral-300 ms:rounded ms:@container ms:focus-within:border-neutral-400",
@@ -22,10 +33,12 @@
22
33
  beforeinput->list-continuation#handleBeforeInput
23
34
  input->list-continuation#handleInput
24
35
  ",
36
+ unique_selector: ".#{@input_id}", # used to pinpoint the exact element in which to insert the attachment
25
37
  marksmith_preview_url_value: marksmith.markdown_previews_path,
26
38
  marksmith_active_tab_class: "bg-white",
27
39
  marksmith_attach_url_value: main_app.rails_direct_uploads_url,
28
40
  marksmith_extra_preview_params_value: extra_preview_params.as_json,
41
+ **local_assigns.fetch(:controller_data_attributes, {})
29
42
  } do %>
30
43
  <% toggle_button_classes = class_names(marksmith_button_classes, "ms:bg-neutral-200 ms:border-0 ms:bg-none ms:text-sm ms:hover:bg-neutral-300 ms:uppercase ms:text-xs ms:font-semibold ms:text-neutral-800") %>
31
44
  <div class="ms:flex-1 ms:flex-col-reverse ms:@md:flex-row ms:grow ms:flex ms:justify-bewteen ms:bg-neutral-50 ms:rounded ms:px-2 ms:py-1 ms:gap-y-1">
@@ -69,11 +82,16 @@
69
82
  style:
70
83
  %>
71
84
  <div class="ms:flex ms:flex-1 ms:flex-grow ms:space-x-2 ms:py-1 ms:border-t ms:border-neutral-300 ms:px-2 ms:font-sans ms:text-sm">
72
- <%= 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:gap-x-2 ms:text-neutral-800 ms:no-underline", toolbar_button_classes) do %>
73
- <%= image_tag asset_path("marksmith/svgs/markdown.svg"), class: "ms:inline ms:size-4" %> <%= t("marksmith.markdown_is_supported").humanize %>
85
+ <%= 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", toolbar_button_classes) do %>
86
+ <%= image_tag asset_path("marksmith/svgs/markdown.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.markdown_is_supported").humanize %>
74
87
  <% end %>
75
88
  <%= 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", toolbar_button_classes) do %>
76
- <%= image_tag asset_path("marksmith/svgs/paperclip.svg"), class: "ms:inline ms:size-4" %> <%= t("marksmith.attach_files").humanize %>
89
+ <%= image_tag asset_path("marksmith/svgs/paperclip.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.upload_files").humanize %>
90
+ <% end %>
91
+ <% if gallery_enabled %>
92
+ <%= link_to gallery_full_path, data: { turbo_frame: gallery_turbo_frame }, class: class_names("ms:flex ms:items-center ms:text-neutral-800 ms:no-underline", toolbar_button_classes) do %>
93
+ <%= image_tag asset_path("marksmith/svgs/gallery.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.attach_from_gallery").humanize %>
94
+ <% end %>
77
95
  <% end %>
78
96
  </div>
79
97
  <% end %>
@@ -30,7 +30,7 @@
30
30
 
31
31
  en:
32
32
  marksmith:
33
- attach_files: attach files
33
+ attach_from_gallery: Attach from gallery
34
34
  bold: bold
35
35
  code: code
36
36
  header: header
@@ -43,4 +43,5 @@ en:
43
43
  quote: quote
44
44
  task_list: task_list
45
45
  unordered_list: unordered list
46
+ upload_files: upload files
46
47
  write: write
@@ -19,8 +19,33 @@ module Marksmith
19
19
 
20
20
  initializer "marksmith.assets.precompile" do |app|
21
21
  if Rails.application.config.respond_to?(:assets)
22
+ # The manifest will expose the asset files to the main app.
22
23
  app.config.assets.precompile << "marksmith_manifest.js"
23
24
  end
24
25
  end
26
+
27
+ initializer "avo-markdown_field.init" do |app|
28
+ if defined?(Avo)
29
+ require "marksmith/fields/markdown_field"
30
+
31
+ app.routes.append do
32
+ mount Marksmith::Engine => "/marksmith"
33
+ end
34
+
35
+ ActiveSupport.on_load(:avo_boot) do
36
+ Avo.plugin_manager.register :marksmith_field
37
+
38
+ Avo.plugin_manager.register_field :markdown, Marksmith::Fields::MarkdownField
39
+ Avo.plugin_manager.register_field :marksmith, Marksmith::Fields::MarkdownField
40
+
41
+ Avo.asset_manager.add_stylesheet "marksmith"
42
+ Avo.asset_manager.add_javascript "marksmith_controller-no-stimulus.esm"
43
+ Avo.asset_manager.add_javascript "list_continuation_controller-no-stimulus.esm"
44
+
45
+ Avo.asset_manager.register_stimulus_controller "marksmith", "MarksmithController"
46
+ Avo.asset_manager.register_stimulus_controller "list-continuation", "ListContinuationController"
47
+ end
48
+ end
49
+ end
25
50
  end
26
51
  end
@@ -0,0 +1,15 @@
1
+ module Marksmith
2
+ module Fields
3
+ class MarkdownField < Avo::Fields::BaseField
4
+ def initialize(id, **args, &block)
5
+ super(id, **args, &block)
6
+
7
+ hide_on :index
8
+ end
9
+
10
+ def view_component_namespace
11
+ "Marksmith::MarkdownField"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Marksmith
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.16"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marksmith
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-23 00:00:00.000000000 Z
11
+ date: 2025-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -53,6 +53,7 @@ files:
53
53
  - app/assets/images/marksmith/svgs/code.svg
54
54
  - app/assets/images/marksmith/svgs/color-swatch copy.svg
55
55
  - app/assets/images/marksmith/svgs/color-swatch.svg
56
+ - app/assets/images/marksmith/svgs/gallery.svg
56
57
  - app/assets/images/marksmith/svgs/header.svg
57
58
  - app/assets/images/marksmith/svgs/image.svg
58
59
  - app/assets/images/marksmith/svgs/italic.svg
@@ -64,8 +65,16 @@ files:
64
65
  - app/assets/images/marksmith/svgs/quote.svg
65
66
  - app/assets/images/marksmith/svgs/task-list.svg
66
67
  - app/assets/images/marksmith/svgs/unordered-list.svg
68
+ - app/assets/javascripts/list_continuation_controller-full.esm.js
69
+ - app/assets/javascripts/list_continuation_controller-no-stimulus.esm.js
70
+ - app/assets/javascripts/marksmith_controller-full.esm.js
71
+ - app/assets/javascripts/marksmith_controller-no-stimulus.esm.js
67
72
  - app/assets/stylesheets/marksmith.css
68
73
  - app/assets/stylesheets/marksmith/application.css
74
+ - app/components/marksmith/markdown_field/edit_component.html.erb
75
+ - app/components/marksmith/markdown_field/edit_component.rb
76
+ - app/components/marksmith/markdown_field/show_component.html.erb
77
+ - app/components/marksmith/markdown_field/show_component.rb
69
78
  - app/controllers/marksmith/application_controller.rb
70
79
  - app/controllers/marksmith/markdown_previews_controller.rb
71
80
  - app/frontend/entrypoints/application.css
@@ -89,6 +98,7 @@ files:
89
98
  - config/vite.json
90
99
  - lib/marksmith.rb
91
100
  - lib/marksmith/engine.rb
101
+ - lib/marksmith/fields/markdown_field.rb
92
102
  - lib/marksmith/helper.rb
93
103
  - lib/marksmith/version.rb
94
104
  - lib/tasks/marksmith_tasks.rake
@@ -114,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
124
  - !ruby/object:Gem::Version
115
125
  version: '0'
116
126
  requirements: []
117
- rubygems_version: 3.4.10
127
+ rubygems_version: 3.5.9
118
128
  signing_key:
119
129
  specification_version: 4
120
130
  summary: Marksmith is a GitHub-style markdown editor for Ruby on Rails applications.