marksmith 0.1.0 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e75eb38c87cf55bb17635627ebf0c3fa043e8f936d13e36faa997c311a81767a
4
- data.tar.gz: 6817d10490f87128ef997c34b1ffb666af6feb433bdde8a2f817b3f831995985
3
+ metadata.gz: 5018de3478a97ddcec156c4245851720d0ea86d36a2002ab82ba9a145f6739cc
4
+ data.tar.gz: 7fb9f7f2a8f702abad17476695f14bf65669af942609c2dffe1531bb71137f30
5
5
  SHA512:
6
- metadata.gz: 04f4b63bc45ad9ac1012aee2841e403678b6ef9ae7198e51c2bfeca355dbf04f97ec64220fd513a9bdc7455d46c79e33036f738c9449b0056d20baebc8bbe27d
7
- data.tar.gz: 93db1009535a17a459f69cf34a93febe2505fa68aefc29adb8559bd626cd1d48c32c7578ba857b8b74ea26e3e74691b3c51ce64152d4092e5f81ad7a53c8841d
6
+ metadata.gz: 813d6e4f66ac1a41c20afc5d1d6815d8695163badf4cb45ddbf49a1da394eb3c9436677610a61bf00bbf67e961abab9a6e5b89b1ccf61f203d82650d36f97292
7
+ data.tar.gz: 10b74b2a3af7f5ee6ecea2d76d54efe3d91d9784c4f3bd38ba807a828f36a79ae722deaab0285c8b9027660b452380f35df2b84af945971b85ed7199a4bd3a91
data/README.md CHANGED
@@ -8,6 +8,11 @@ It supports Active Storage attachments and comes with a built-in mardown preview
8
8
 
9
9
  ![Marksmith demo](./marksmith.gif)
10
10
 
11
+ > [!WARNING]
12
+ > Marksmith is at the initial stage of development. It's nearing a beta release, but the API might change and bugs are expected. Please continue to use the library and report any issues in the GitHub repo.
13
+
14
+ Temporary live demo here, under the description field: [https://main.avodemo.com/avo/resources/projects/new](https://main.avodemo.com/avo/resources/projects/new)
15
+
11
16
  ## Usage
12
17
 
13
18
  ```erb
@@ -16,7 +21,7 @@ It supports Active Storage attachments and comes with a built-in mardown preview
16
21
 
17
22
  ## Installation
18
23
 
19
- ### 1. Add `marksmith` to your `Gemfile`
24
+ #### 1. Add `marksmith` to your `Gemfile`
20
25
 
21
26
  Have Bundler add it by running this command:
22
27
 
@@ -33,20 +38,27 @@ Add this line to your application's Gemfile:
33
38
  gem "marksmith"
34
39
  ```
35
40
 
36
- ### 2. Install the NPM package to import the StimulusJS controller.
41
+ #### 2. Install the NPM package to import the StimulusJS controller.
37
42
 
38
- Install the package.
43
+ Install the package from npmjs.org.
39
44
 
40
45
  ```bash
41
46
  $ yarn add @avo-hq/marksmith
42
47
  ```
43
48
 
44
- Import and register it in your application.
49
+ Or pin it using importmap.
50
+
51
+ ```bash
52
+ bin/importmap pin @avo-hq/marksmith
53
+ ```
54
+
55
+ Import and register the controllers in your application. The `ListContinuationController` is optional and only needed if you want to have continued lists in your markdown.
45
56
 
46
57
  ```js
47
- import { MarksmithController } from '@avo-hq/marksmith'
58
+ import { MarksmithController, ListContinuationController } from '@avo-hq/marksmith'
48
59
 
49
60
  application.register('marksmith', MarksmithController)
61
+ application.register('list-continuation', ListContinuationController)
50
62
  ```
51
63
 
52
64
  > [!NOTE]
@@ -66,28 +78,78 @@ import { MarksmithController } from '@avo-hq/marksmith/core'
66
78
  application.register('marksmith', MarksmithController)
67
79
  ```
68
80
 
69
- ### 3. Add the style tag to your `application.html` layout
81
+ #### 3. Add the style tag to your `application.html` layout
70
82
 
71
83
  ```erb
72
84
  <%= stylesheet_link_tag "marksmith" %>
73
85
  ```
74
86
 
75
- ### 4. Use it
87
+ #### 4. Use it
76
88
 
77
89
  Use a form helper tag or attach it to your form builder.
78
90
 
79
91
  ```erb
80
92
  <%= marksmith_tag :body, value: "### This is important" %>
81
93
  or
82
- <%= @form.marksmith :body %>
94
+ <%= form.marksmith :body %>
83
95
  ```
84
96
 
85
- ## Options
97
+ ## Configuration
98
+
99
+ Marksmith accepts a few configuration options.
100
+
101
+ ### Field options
86
102
 
87
103
  The field supports a few of the regular options like `disabled`, `placeholder`, `autofocus`, `style`, `class`, `rows`, `data`, and `value`, but also a custom one.
88
104
 
89
105
  `extra_preview_params` - Sends extra params to the preview renderer.
90
106
 
107
+ `enable_file_uploads` - Whether to enable file uploads.
108
+
109
+ `upload_url` - The URL to use for file uploads. If not provided, the editor will use the `rails_direct_uploads_url` helper.
110
+
111
+ ```erb
112
+ <%= marksmith_tag :body,
113
+ disabled: true,
114
+ placeholder: "Write your best markdown here.",
115
+ extra_preview_params: { foo: "bar" },
116
+ enable_file_uploads: true,
117
+ upload_url: nil
118
+ %>
119
+ ```
120
+
121
+ ### Eject configuration file
122
+
123
+ Marksmith comes with a default configuration file that you can eject to your app.
124
+
125
+ ```bash
126
+ bin/rails generate marksmith:install
127
+ ```
128
+
129
+ This will create a `config/initializers/marksmith.rb` file in your app.
130
+
131
+ ### Mount path
132
+
133
+ The engine is mounted by default at `/marksmith`. You can change it by setting `Marksmith.configuration.mount_path` to a different path.
134
+
135
+ ```ruby
136
+ # config/initializers/marksmith.rb
137
+ Marksmith.configure do |config|
138
+ config.mount_path = "/markdown"
139
+ end
140
+ ```
141
+
142
+ ### Mounting the engine
143
+
144
+ The engine is mounted by default, but you can disable it by setting `Marksmith.configuration.automatically_mount_engine` to `false` and then manually mount the engine in your `routes.rb` file.
145
+
146
+ ```ruby
147
+ # config/routes.rb
148
+ Rails.application.routes.draw do
149
+ mount Marksmith::Engine => Marksmith.configuration.mount_path
150
+ end
151
+ ```
152
+
91
153
  ## Built-in preview renderer
92
154
 
93
155
  The renderer is powered by [`Redcarpet`](https://github.com/vmg/redcarpet).
@@ -96,16 +158,18 @@ It supports basic styles for headings, `strong`, `italic` and others.
96
158
  In your `show.html.erb` view or the place where you want to render the compiled markup use the `marksmithed` helper and it will run the content through the renderer.
97
159
 
98
160
  ```erb
99
- <%= marksmithed post.body %>
161
+ <%== marksmithed post.body %>
100
162
  ```
101
163
 
102
- ## Using with importmap
164
+ > [!WARNING]
165
+ > Using the `<%==` tag will output the raw HTML, so ensure you sanitize the content to avoid XSS attacks.
166
+ >
167
+ > See how we do it [here](https://github.com/avo-hq/avo/blob/main/app/views/marksmith/shared/_rendered_body.html.erb#L2).
168
+ > ```ruby
169
+ > # sample sanitization
170
+ > sanitize(body, tags: %w(table th tr td span) + ActionView::Helpers::SanitizeHelper.sanitizer_vendor.safe_list_sanitizer.allowed_tags.to_a)
171
+ > ```
103
172
 
104
- It should be as simple as running this command and have it pinned in your `importmap.rb` file.
105
-
106
- ```bash
107
- bin/importmap pin @avo-hq/marksmith
108
- ```
109
173
 
110
174
  ## Active Storage
111
175
 
@@ -128,6 +192,12 @@ application.register('marksmith', MarksmithController)
128
192
  application.register('list-continuation', ListContinuationController)
129
193
  ```
130
194
 
195
+ ## Who uses Marksmith?
196
+
197
+ - [Avo](https://avohq.io) - Ruby on Rails Code-Based App Builder Framework
198
+
199
+ *Open a PR and add your project here*
200
+
131
201
  ## Contributing
132
202
 
133
203
  Contribution directions go here.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Marksmith 0.1.0
2
+ Marksmith 0.1.2
3
3
  */
4
4
  var ListContinuationController = (function () {
5
5
  'use strict';
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Marksmith 0.1.0
2
+ Marksmith 0.1.2
3
3
  */
4
4
  var ListContinuationController = (function (stimulus) {
5
5
  'use strict';
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Marksmith 0.1.0
2
+ Marksmith 0.1.2
3
3
  */
4
4
  var MarksmithController = (function () {
5
5
  'use strict';
@@ -2827,10 +2827,15 @@ var MarksmithController = (function () {
2827
2827
  fieldId: String,
2828
2828
  galleryEnabled: { type: Boolean, default: false },
2829
2829
  galleryOpenPath: String,
2830
+ fileUploadsEnabled: { type: Boolean, default: true },
2830
2831
  }
2831
2832
 
2832
2833
  static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
2833
2834
 
2835
+ get #fileUploadsDisabled() {
2836
+ return !this.fileUploadsEnabledValue
2837
+ }
2838
+
2834
2839
  connect() {
2835
2840
  subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } });
2836
2841
  }
@@ -2878,11 +2883,15 @@ var MarksmithController = (function () {
2878
2883
  }
2879
2884
 
2880
2885
  dropUpload(event) {
2886
+ if (this.#fileUploadsDisabled) return
2887
+
2881
2888
  event.preventDefault();
2882
2889
  this.#uploadFiles(event.dataTransfer.files);
2883
2890
  }
2884
2891
 
2885
2892
  pasteUpload(event) {
2893
+ if (this.#fileUploadsDisabled) return
2894
+
2886
2895
  if (!event.clipboardData.files.length) return
2887
2896
 
2888
2897
  event.preventDefault();
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Marksmith 0.1.0
2
+ Marksmith 0.1.2
3
3
  */
4
4
  var MarksmithController = (function (stimulus) {
5
5
  'use strict';
@@ -2337,10 +2337,15 @@ var MarksmithController = (function (stimulus) {
2337
2337
  fieldId: String,
2338
2338
  galleryEnabled: { type: Boolean, default: false },
2339
2339
  galleryOpenPath: String,
2340
+ fileUploadsEnabled: { type: Boolean, default: true },
2340
2341
  }
2341
2342
 
2342
2343
  static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
2343
2344
 
2345
+ get #fileUploadsDisabled() {
2346
+ return !this.fileUploadsEnabledValue
2347
+ }
2348
+
2344
2349
  connect() {
2345
2350
  subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } });
2346
2351
  }
@@ -2388,11 +2393,15 @@ var MarksmithController = (function (stimulus) {
2388
2393
  }
2389
2394
 
2390
2395
  dropUpload(event) {
2396
+ if (this.#fileUploadsDisabled) return
2397
+
2391
2398
  event.preventDefault();
2392
2399
  this.#uploadFiles(event.dataTransfer.files);
2393
2400
  }
2394
2401
 
2395
2402
  pasteUpload(event) {
2403
+ if (this.#fileUploadsDisabled) return
2404
+
2396
2405
  if (!event.clipboardData.files.length) return
2397
2406
 
2398
2407
  event.preventDefault();
@@ -17,10 +17,15 @@ export default class extends Controller {
17
17
  fieldId: String,
18
18
  galleryEnabled: { type: Boolean, default: false },
19
19
  galleryOpenPath: String,
20
+ fileUploadsEnabled: { type: Boolean, default: true },
20
21
  }
21
22
 
22
23
  static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
23
24
 
25
+ get #fileUploadsDisabled() {
26
+ return !this.fileUploadsEnabledValue
27
+ }
28
+
24
29
  connect() {
25
30
  subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } })
26
31
  }
@@ -68,11 +73,15 @@ export default class extends Controller {
68
73
  }
69
74
 
70
75
  dropUpload(event) {
76
+ if (this.#fileUploadsDisabled) return
77
+
71
78
  event.preventDefault()
72
79
  this.#uploadFiles(event.dataTransfer.files)
73
80
  }
74
81
 
75
82
  pasteUpload(event) {
83
+ if (this.#fileUploadsDisabled) return
84
+
76
85
  if (!event.clipboardData.files.length) return
77
86
 
78
87
  event.preventDefault()
@@ -13,6 +13,20 @@
13
13
  local_assigns[:value] || nil
14
14
  end
15
15
  extra_preview_params = local_assigns[:extra_preview_params] || {}
16
+ upload_url = if local_assigns[:upload_url].present?
17
+ local_assigns[:upload_url]
18
+ elsif defined?(ActiveStorage)
19
+ main_app.rails_direct_uploads_url
20
+ end
21
+
22
+ enable_file_uploads = if upload_url.blank?
23
+ false
24
+ elsif local_assigns[:enable_file_uploads].nil?
25
+ true
26
+ else
27
+ local_assigns[:enable_file_uploads]
28
+ end
29
+
16
30
 
17
31
  # Used by Avo and other adapters to enable the gallery link.
18
32
  gallery_enabled = local_assigns.dig(:gallery, :enabled) || false
@@ -35,8 +49,9 @@
35
49
  ",
36
50
  unique_selector: ".#{@input_id}", # used to pinpoint the exact element in which to insert the attachment
37
51
  marksmith_preview_url_value: marksmith.markdown_previews_path,
52
+ marksmith_file_uploads_enabled_value: enable_file_uploads,
38
53
  marksmith_active_tab_class: "bg-white",
39
- marksmith_attach_url_value: main_app.rails_direct_uploads_url,
54
+ marksmith_attach_url_value: upload_url,
40
55
  marksmith_extra_preview_params_value: extra_preview_params.as_json,
41
56
  **local_assigns.fetch(:controller_data_attributes, {})
42
57
  } do %>
@@ -69,7 +84,7 @@
69
84
  <%= content_tag :div, class: "ms:flex ms:flex-1 ms:flex-col ms:size-full", data: { marksmith_target: "fieldContainer" } do %>
70
85
  <%= text_area_tag field_name, value,
71
86
  id: name,
72
- class: class_names("ms:flex ms:flex-1 ms:rounded ms:border-none ms:resize-y ms:focus:outline-none ms:font-mono ms:focus:ring-0 ms:leading-normal ms:p-2", classes),
87
+ class: class_names("ms:flex ms:flex-1 ms:rounded ms:border-none ms:resize-y ms:focus:outline-none ms:font-mono ms:focus:ring-0 ms:leading-normal ms:p-2 ms:text-sm", classes),
73
88
  rows: rows,
74
89
  data: {
75
90
  action: "drop->marksmith#dropUpload paste->marksmith#pasteUpload",
@@ -85,8 +100,10 @@
85
100
  <%= 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
101
  <%= image_tag asset_path("marksmith/svgs/markdown.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.markdown_is_supported").humanize %>
87
102
  <% end %>
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 %>
89
- <%= image_tag asset_path("marksmith/svgs/paperclip.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.upload_files").humanize %>
103
+ <% if enable_file_uploads %>
104
+ <%= 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 %>
105
+ <%= image_tag asset_path("marksmith/svgs/paperclip.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.upload_files").humanize %>
106
+ <% end %>
90
107
  <% end %>
91
108
  <% if gallery_enabled %>
92
109
  <%= 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 %>
@@ -0,0 +1,15 @@
1
+ require "rails/generators"
2
+
3
+ module Marksmith
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ desc "Creates a Marksmith initializer."
9
+
10
+ def create_initializer_file
11
+ template "initializer/marksmith.tt", "config/initializers/marksmith.rb"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ # Marksmith.configure do |config|
2
+ # config.automatically_mount_engine = true
3
+ # config.mount_path = "/marksmith"
4
+ # end
@@ -0,0 +1,16 @@
1
+ module Marksmith
2
+ class Configuration
3
+ include ActiveSupport::Configurable
4
+
5
+ config_accessor(:automatically_mount_engine) { true }
6
+ config_accessor(:mount_path) { "/marksmith" }
7
+ end
8
+
9
+ def self.configuration
10
+ @configuration ||= Configuration.new
11
+ end
12
+
13
+ def self.configure
14
+ yield configuration
15
+ end
16
+ end
@@ -17,6 +17,14 @@ module Marksmith
17
17
  end
18
18
  end
19
19
 
20
+ initializer "marksmith.routes" do |app|
21
+ if Marksmith.configuration.automatically_mount_engine
22
+ app.routes.append do
23
+ mount Marksmith::Engine => Marksmith.configuration.mount_path
24
+ end
25
+ end
26
+ end
27
+
20
28
  initializer "marksmith.assets.precompile" do |app|
21
29
  if Rails.application.config.respond_to?(:assets)
22
30
  # The manifest will expose the asset files to the main app.
@@ -24,14 +32,14 @@ module Marksmith
24
32
  end
25
33
  end
26
34
 
35
+ generators do |app|
36
+ Rails::Generators.configure! app.config.generators
37
+ end
38
+
27
39
  initializer "avo-markdown_field.init" do |app|
28
40
  if defined?(Avo)
29
41
  require "marksmith/fields/markdown_field"
30
42
 
31
- app.routes.append do
32
- mount Marksmith::Engine => "/marksmith"
33
- end
34
-
35
43
  ActiveSupport.on_load(:avo_boot) do
36
44
  Avo.plugin_manager.register :marksmith_field
37
45
 
@@ -1,3 +1,3 @@
1
1
  module Marksmith
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/marksmith.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "marksmith/version"
2
+ require "marksmith/configuration"
2
3
  require "marksmith/engine"
3
4
 
4
5
  module Marksmith
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marksmith
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
@@ -11,19 +11,19 @@ cert_chain: []
11
11
  date: 2025-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rails
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.0
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.0
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: redcarpet
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -96,7 +96,10 @@ files:
96
96
  - config/locales/marksmith.en.yml
97
97
  - config/routes.rb
98
98
  - config/vite.json
99
+ - lib/generators/marksmith/install_generator.rb
100
+ - lib/generators/marksmith/templates/initializer/marksmith.tt
99
101
  - lib/marksmith.rb
102
+ - lib/marksmith/configuration.rb
100
103
  - lib/marksmith/engine.rb
101
104
  - lib/marksmith/fields/markdown_field.rb
102
105
  - lib/marksmith/helper.rb
@@ -124,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
127
  - !ruby/object:Gem::Version
125
128
  version: '0'
126
129
  requirements: []
127
- rubygems_version: 3.5.9
130
+ rubygems_version: 3.5.22
128
131
  signing_key:
129
132
  specification_version: 4
130
133
  summary: Marksmith is a GitHub-style markdown editor for Ruby on Rails applications.