From 7e5c8d8019be88039546a8999415e91f6f3ba887 Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 12:11:55 +0200 Subject: [PATCH 01/13] feature: markdown field (easy_mde replacement) --- .../easy_mde_field/edit_component.html.erb | 17 ++++++++++++++ .../fields/easy_mde_field/edit_component.rb | 4 ++++ .../easy_mde_field/show_component.html.erb | 11 ++++++++++ .../fields/easy_mde_field/show_component.rb | 4 ++++ lib/avo/fields/easy_mde_field.rb | 22 +++++++++++++++++++ spec/dummy/app/avo/resources/city.rb | 2 +- .../avo/resource_tools/_city_editor.html.erb | 2 +- 7 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 app/components/avo/fields/easy_mde_field/edit_component.html.erb create mode 100644 app/components/avo/fields/easy_mde_field/edit_component.rb create mode 100644 app/components/avo/fields/easy_mde_field/show_component.html.erb create mode 100644 app/components/avo/fields/easy_mde_field/show_component.rb create mode 100644 lib/avo/fields/easy_mde_field.rb diff --git a/app/components/avo/fields/easy_mde_field/edit_component.html.erb b/app/components/avo/fields/easy_mde_field/edit_component.html.erb new file mode 100644 index 0000000000..51724f4e2d --- /dev/null +++ b/app/components/avo/fields/easy_mde_field/edit_component.html.erb @@ -0,0 +1,17 @@ +<%= field_wrapper **field_wrapper_args, full_width: true do %> +
+ <%= @form.text_area @field.id, + value: @field.value, + class: classes("w-full js-has-easy-mde-editor"), + data: { + view: view, + 'easy-mde-target': 'element', + 'component-options': @field.options.to_json, + }, + disabled: disabled?, + placeholder: @field.placeholder, + autofocus: @autofocus, + style: @field.get_html(:style, view: view, element: :input) + %> +
+<% end %> diff --git a/app/components/avo/fields/easy_mde_field/edit_component.rb b/app/components/avo/fields/easy_mde_field/edit_component.rb new file mode 100644 index 0000000000..80d30d2ae3 --- /dev/null +++ b/app/components/avo/fields/easy_mde_field/edit_component.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class Avo::Fields::EasyMdeField::EditComponent < Avo::Fields::EditComponent +end diff --git a/app/components/avo/fields/easy_mde_field/show_component.html.erb b/app/components/avo/fields/easy_mde_field/show_component.html.erb new file mode 100644 index 0000000000..822045e6f8 --- /dev/null +++ b/app/components/avo/fields/easy_mde_field/show_component.html.erb @@ -0,0 +1,11 @@ +<%= field_wrapper **field_wrapper_args, full_width: true do %> +
+ <%= text_area_tag @field.id, @field.value, + class: helpers.input_classes('w-full js-has-easy-mde-editor'), + placeholder: @field.placeholder, + disabled: disabled?, + 'data-easy-mde-target': 'element', + 'data-component-options': @field.options.to_json, + 'data-view': :show %> +
+<% end %> diff --git a/app/components/avo/fields/easy_mde_field/show_component.rb b/app/components/avo/fields/easy_mde_field/show_component.rb new file mode 100644 index 0000000000..78b07fcc45 --- /dev/null +++ b/app/components/avo/fields/easy_mde_field/show_component.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class Avo::Fields::EasyMdeField::ShowComponent < Avo::Fields::ShowComponent +end diff --git a/lib/avo/fields/easy_mde_field.rb b/lib/avo/fields/easy_mde_field.rb new file mode 100644 index 0000000000..2dc572fa79 --- /dev/null +++ b/lib/avo/fields/easy_mde_field.rb @@ -0,0 +1,22 @@ +module Avo + module Fields + class EasyMdeField < BaseField + attr_reader :options + + def initialize(id, **args, &block) + super(id, **args, &block) + + hide_on :index + + @always_show = args[:always_show].present? ? args[:always_show] : false + @height = args[:height].present? ? args[:height].to_s : "auto" + @spell_checker = args[:spell_checker].present? ? args[:spell_checker] : false + @options = { + spell_checker: @spell_checker, + always_show: @always_show, + height: @height + } + end + end + end +end diff --git a/spec/dummy/app/avo/resources/city.rb b/spec/dummy/app/avo/resources/city.rb index b9fdc9087b..9e2e1f0d4c 100644 --- a/spec/dummy/app/avo/resources/city.rb +++ b/spec/dummy/app/avo/resources/city.rb @@ -91,7 +91,7 @@ def tool_fields field :is_capital, as: :boolean, filterable: true field :features, as: :key_value field :image_url, as: :external_image - field :tiny_description, as: :markdown + field :tiny_description, as: :easy_mde field :status, as: :badge, enum: ::City.statuses end end diff --git a/spec/dummy/app/views/avo/resource_tools/_city_editor.html.erb b/spec/dummy/app/views/avo/resource_tools/_city_editor.html.erb index 56064ab617..ca2ac9e9da 100644 --- a/spec/dummy/app/views/avo/resource_tools/_city_editor.html.erb +++ b/spec/dummy/app/views/avo/resource_tools/_city_editor.html.erb @@ -14,7 +14,7 @@ <% if params[:show_native_fields].present? %> <%= avo_edit_field(:description, as: :trix, form: form, component_options: {resource_name: 'cities', resource_id: @resource.record&.id}) %> <% end %> - <%= avo_edit_field(:tiny_description, as: :markdown, form: form) %> + <%= avo_edit_field(:tiny_description, as: :easy_mde, form: form) %> <%= avo_edit_field(:status, as: :select, enum: ::City.statuses, form: form) %> <%= avo_show_field(:status, as: :badge, enum: ::City.statuses, form: form) %> <% end %> From f13ca26aa4fb19a7ed9103d81a329c4cec6927f1 Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 14:55:57 +0200 Subject: [PATCH 02/13] wip --- Gemfile | 2 + Gemfile.lock | 2 + app/assets/svgs/avo/heading.svg | 1 + app/assets/svgs/avo/list-todo.svg | 1 + app/assets/svgs/avo/quote.svg | 1 + .../markdown_field/edit_component.html.erb | 72 ++++++++++--- .../fields/markdown_field/edit_component.rb | 1 + .../markdown_field/show_component.html.erb | 10 +- .../fields/markdown_field/show_component.rb | 5 + .../avo/markdown_previews_controller.rb | 10 ++ app/javascript/js/controllers.js | 2 + .../controllers/fields/markdown_controller.js | 100 ++++++++++++++++++ .../markdown_previews/create.turbo_stream.erb | 5 + config/routes.rb | 2 + lib/avo/fields/markdown_field.rb | 12 +-- package.json | 2 + yarn.lock | 44 ++++++-- 17 files changed, 233 insertions(+), 39 deletions(-) create mode 100644 app/assets/svgs/avo/heading.svg create mode 100644 app/assets/svgs/avo/list-todo.svg create mode 100644 app/assets/svgs/avo/quote.svg create mode 100644 app/controllers/avo/markdown_previews_controller.rb create mode 100644 app/javascript/js/controllers/fields/markdown_controller.js create mode 100644 app/views/avo/markdown_previews/create.turbo_stream.erb diff --git a/Gemfile b/Gemfile index 814760193b..a311d137d3 100644 --- a/Gemfile +++ b/Gemfile @@ -193,3 +193,5 @@ gem "avo-record_link_field" gem "pagy", "> 8" gem "csv" + +gem "redcarpet" diff --git a/Gemfile.lock b/Gemfile.lock index 8a0fa2569f..b035640bb9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -494,6 +494,7 @@ GEM rbs (2.8.4) rdoc (6.10.0) psych (>= 4.0.0) + redcarpet (3.6.0) redis (5.3.0) redis-client (>= 0.22.0) redis-client (0.23.0) @@ -741,6 +742,7 @@ DEPENDENCIES rails (>= 8.0.0) rails-controller-testing ransack (>= 4.2.0) + redcarpet redis (~> 5.0) ripper-tags rspec-rails (~> 6.0, >= 6.0.3) diff --git a/app/assets/svgs/avo/heading.svg b/app/assets/svgs/avo/heading.svg new file mode 100644 index 0000000000..bb2f2526c4 --- /dev/null +++ b/app/assets/svgs/avo/heading.svg @@ -0,0 +1 @@ + diff --git a/app/assets/svgs/avo/list-todo.svg b/app/assets/svgs/avo/list-todo.svg new file mode 100644 index 0000000000..d134716e07 --- /dev/null +++ b/app/assets/svgs/avo/list-todo.svg @@ -0,0 +1 @@ + diff --git a/app/assets/svgs/avo/quote.svg b/app/assets/svgs/avo/quote.svg new file mode 100644 index 0000000000..b970db1430 --- /dev/null +++ b/app/assets/svgs/avo/quote.svg @@ -0,0 +1 @@ + diff --git a/app/components/avo/fields/markdown_field/edit_component.html.erb b/app/components/avo/fields/markdown_field/edit_component.html.erb index 51724f4e2d..23d9713cba 100644 --- a/app/components/avo/fields/markdown_field/edit_component.html.erb +++ b/app/components/avo/fields/markdown_field/edit_component.html.erb @@ -1,17 +1,61 @@ <%= field_wrapper **field_wrapper_args, full_width: true do %> -
- <%= @form.text_area @field.id, - value: @field.value, - class: classes("w-full js-has-easy-mde-editor"), - data: { - view: view, - 'easy-mde-target': 'element', - 'component-options': @field.options.to_json, - }, - disabled: disabled?, - placeholder: @field.placeholder, - autofocus: @autofocus, - style: @field.get_html(:style, view: view, element: :input) - %> + <%= content_tag :div, + class: "flex flex-col w-full border rounded", + data: { + controller: "markdown-field", + markdown_field_target: "toolbar", + markdown_field_preview_url_value: helpers.avo.markdown_previews_path, + markdown_field_active_tab_class: "bg-white", + markdown_field_attach_url_value: rails_direct_uploads_url, + markdown_field_resource_class_value: @resource.class.name, + markdown_field_field_id_value: @field.id, + } do %> +
+
+ + +
+ + + <%= helpers.svg "heroicons/outline/bold", class: "inline size-4" %> + <%= helpers.svg "avo/heading", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/italic", class: "inline size-4" %> + <%= helpers.svg "avo/quote", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/code", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/link", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/photo", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/list-bullet", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/numbered-list", class: "inline size-4" %> + <%= helpers.svg "avo/list-todo", class: "inline size-4" %> + +
+ +
+ <%= @form.text_area @field.id, + id: @field.id, + value: @field.value, + class: ("flex flex-1 rounded border-none w-full py-2 px-3"), + rows: 20, + data: { + markdown_field_target: "fieldElement", + action: "drop->markdown-field#dropUpload paste->markdown-field#pasteUpload" + }, + disabled: disabled?, + placeholder: @field.placeholder, + autofocus: @autofocus, + style: @field.get_html(:style, view: view, element: :input) + %> + <%= content_tag :div, class: "hidden markdown-preview", id: "markdown-preview-#{@field.id}", data: { markdown_field_target: "previewElement" } do %> +
+
+
+
+ <% end %> +
+ <% end %> <% end %> diff --git a/app/components/avo/fields/markdown_field/edit_component.rb b/app/components/avo/fields/markdown_field/edit_component.rb index 4844dcb3fe..be59612e7f 100644 --- a/app/components/avo/fields/markdown_field/edit_component.rb +++ b/app/components/avo/fields/markdown_field/edit_component.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true class Avo::Fields::MarkdownField::EditComponent < Avo::Fields::EditComponent + BUTTON_CLASSES = "cursor-pointer py-1 px-1.5 hover:bg-slate-200 rounded" end diff --git a/app/components/avo/fields/markdown_field/show_component.html.erb b/app/components/avo/fields/markdown_field/show_component.html.erb index 822045e6f8..19e3ce0fc7 100644 --- a/app/components/avo/fields/markdown_field/show_component.html.erb +++ b/app/components/avo/fields/markdown_field/show_component.html.erb @@ -1,11 +1,3 @@ <%= field_wrapper **field_wrapper_args, full_width: true do %> -
- <%= text_area_tag @field.id, @field.value, - class: helpers.input_classes('w-full js-has-easy-mde-editor'), - placeholder: @field.placeholder, - disabled: disabled?, - 'data-easy-mde-target': 'element', - 'data-component-options': @field.options.to_json, - 'data-view': :show %> -
+ <%= content_tag :div, sanitize(parsed_body), class: "trix-content" %> <% end %> diff --git a/app/components/avo/fields/markdown_field/show_component.rb b/app/components/avo/fields/markdown_field/show_component.rb index a8d7e5fbc3..30732b779b 100644 --- a/app/components/avo/fields/markdown_field/show_component.rb +++ b/app/components/avo/fields/markdown_field/show_component.rb @@ -1,4 +1,9 @@ # frozen_string_literal: true class Avo::Fields::MarkdownField::ShowComponent < Avo::Fields::ShowComponent + def parsed_body + renderer = Redcarpet::Render::HTML.new(hard_wrap: true) + parser = Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) + parser.render(@field.value) + end end diff --git a/app/controllers/avo/markdown_previews_controller.rb b/app/controllers/avo/markdown_previews_controller.rb new file mode 100644 index 0000000000..6b014f5784 --- /dev/null +++ b/app/controllers/avo/markdown_previews_controller.rb @@ -0,0 +1,10 @@ +module Avo + class MarkdownPreviewsController < ApplicationController + def create + renderer = Redcarpet::Render::HTML.new(hard_wrap: true) + parser = Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) + + @result = parser.render(params[:body]) + end + end +end diff --git a/app/javascript/js/controllers.js b/app/javascript/js/controllers.js index 48ad154aee..dfadf2abf7 100644 --- a/app/javascript/js/controllers.js +++ b/app/javascript/js/controllers.js @@ -22,6 +22,7 @@ import ItemSelectAllController from './controllers/item_select_all_controller' import ItemSelectorController from './controllers/item_selector_controller' import KeyValueController from './controllers/fields/key_value_controller' import LoadingButtonController from './controllers/loading_button_controller' +import MarkdownController from './controllers/fields/markdown_controller' import MenuController from './controllers/menu_controller' import ModalController from './controllers/modal_controller' import MultipleSelectFilterController from './controllers/multiple_select_filter_controller' @@ -96,6 +97,7 @@ application.register('code-field', CodeFieldController) application.register('date-field', DateFieldController) application.register('easy-mde', EasyMdeController) application.register('key-value', KeyValueController) +application.register('markdown-field', MarkdownController) application.register('progress-bar-field', ProgressBarFieldController) application.register('reload-belongs-to-field', ReloadBelongsToFieldController) application.register('tags-field', TagsFieldController) diff --git a/app/javascript/js/controllers/fields/markdown_controller.js b/app/javascript/js/controllers/fields/markdown_controller.js new file mode 100644 index 0000000000..5256724b29 --- /dev/null +++ b/app/javascript/js/controllers/fields/markdown_controller.js @@ -0,0 +1,100 @@ +/* eslint-disable camelcase */ +import '@github/markdown-toolbar-element' +import { Controller } from '@hotwired/stimulus' +import { DirectUpload } from '@rails/activestorage' +import { post } from '@rails/request.js' + +// upload code from Jeremy Smith's blog post +// https://hybrd.co/posts/github-issue-style-file-uploader-using-stimulus-and-active-storage + +// Connects to data-controller="form" +export default class extends Controller { + static values = { + attachUrl: String, + previewUrl: String, + resourceClass: String, + fieldId: String, + } + + static targets = ['fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton'] + + switchToWrite(event) { + event.preventDefault() + + // toggle buttons + this.writeTabButtonTarget.classList.add('hidden') + this.previewTabButtonTarget.classList.remove('hidden') + + // toggle write/preview buttons + this.fieldElementTarget.classList.remove('hidden') + this.previewElementTarget.classList.add('hidden') + } + + switchToPreview(event) { + event.preventDefault() + + post(this.previewUrlValue, { + body: { + body: this.fieldElementTarget.value, + resource_class: this.resourceClassValue, + field_id: this.fieldIdValue, + element_id: this.previewElementTarget.id, + }, + responseKind: 'turbo-stream', + }) + + // set the min height to the field element height + this.previewElementTarget.style.minHeight = `${this.fieldElementTarget.offsetHeight}px` + + // toggle buttons + this.writeTabButtonTarget.classList.remove('hidden') + this.previewTabButtonTarget.classList.add('hidden') + + // toggle elements + this.fieldElementTarget.classList.add('hidden') + this.previewElementTarget.classList.remove('hidden') + } + + dropUpload(event) { + event.preventDefault() + this.uploadFiles(event.dataTransfer.files) + } + + pasteUpload(event) { + if (!event.clipboardData.files.length) return + + event.preventDefault() + this.uploadFiles(event.clipboardData.files) + } + + uploadFiles(files) { + Array.from(files).forEach((file) => this.uploadFile(file)) + } + + uploadFile(file) { + const upload = new DirectUpload(file, this.attachUrlValue) + + upload.create((error, blob) => { + if (error) { + console.log('Error', error) + } else { + const text = this.markdownLink(blob) + const start = this.fieldElementTarget.selectionStart + const end = this.fieldElementTarget.selectionEnd + this.fieldElementTarget.setRangeText(text, start, end) + } + }) + } + + markdownLink(blob) { + const { filename } = blob + const url = `/rails/active_storage/blobs/${blob.signed_id}/${filename}` + const prefix = (this.isImage(blob.content_type) ? '!' : '') + + return `${prefix}[${filename}](${url})\n` + } + + isImage(contentType) { + return ['image/jpeg', 'image/gif', 'image/png'].includes(contentType) + } +} diff --git a/app/views/avo/markdown_previews/create.turbo_stream.erb b/app/views/avo/markdown_previews/create.turbo_stream.erb new file mode 100644 index 0000000000..24be1c53e6 --- /dev/null +++ b/app/views/avo/markdown_previews/create.turbo_stream.erb @@ -0,0 +1,5 @@ +<%= turbo_stream.update params[:element_id] do %> +
+ <%= sanitize(@result) %> +
+<% end %> diff --git a/config/routes.rb b/config/routes.rb index e5480b2117..0a0a0cafd9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,8 @@ instance_exec(&Avo.mount_engines) end + resources :markdown_previews, only: [:create] + post "/rails/active_storage/direct_uploads", to: "/active_storage/direct_uploads#create" scope "avo_api", as: "avo_api" do diff --git a/lib/avo/fields/markdown_field.rb b/lib/avo/fields/markdown_field.rb index 4ca474201e..40abcbf62b 100644 --- a/lib/avo/fields/markdown_field.rb +++ b/lib/avo/fields/markdown_field.rb @@ -1,21 +1,13 @@ module Avo module Fields class MarkdownField < BaseField - attr_reader :options + attr_reader :rows def initialize(id, **args, &block) super(id, **args, &block) hide_on :index - - @always_show = args[:always_show].present? ? args[:always_show] : false - @height = args[:height].present? ? args[:height].to_s : "auto" - @spell_checker = args[:spell_checker].present? ? args[:spell_checker] : false - @options = { - spell_checker: @spell_checker, - always_show: @always_show, - height: @height - } + add_string_prop args, :rows, default: 20 end end end diff --git a/package.json b/package.json index c49fde8f6f..0ec08e0174 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,11 @@ "@algolia/autocomplete-js": "^1.0.0-alpha.46", "@algolia/autocomplete-theme-classic": "^1.0.0-alpha.46", "@babel/plugin-proposal-class-properties": "^7.12.1", + "@github/markdown-toolbar-element": "^2.2.3", "@hotwired/stimulus": "^3.2.2", "@hotwired/turbo-rails": "^8.0.12", "@rails/activestorage": "^6.1.710", + "@rails/request.js": "^0.0.11", "@stimulus-components/clipboard": "^5.0.0", "@stimulus-components/password-visibility": "^3.0.0", "@tailwindcss/forms": "^0.5.10", diff --git a/yarn.lock b/yarn.lock index 24b525a3b8..bb91e944a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1350,6 +1350,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@github/markdown-toolbar-element@^2.2.3": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@github/markdown-toolbar-element/-/markdown-toolbar-element-2.2.3.tgz#a062b0f79ab458b0adae01b6bb6c51c846526049" + integrity sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A== + "@hotwired/stimulus@>=3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.0.1.tgz#141f15645acaa3b133b7c247cad58ae252ffae85" @@ -1515,6 +1520,11 @@ dependencies: spark-md5 "^3.0.0" +"@rails/request.js@^0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@rails/request.js/-/request.js-0.0.11.tgz#4d9be25a49d97911c64ccd0f00b79d57fca4c3b4" + integrity sha512-2U3uYS0kbljt+pAstN+LIlZOl7xmOKig5N6FrvtUWO1wq0zR1Hf90fHfD2SYiyV8yH1nyKpoTmbLqWT0xe1zDg== + "@remirror/core-constants@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@remirror/core-constants/-/core-constants-3.0.0.tgz#96fdb89d25c62e7b6a5d08caf0ce5114370e3b8f" @@ -5103,8 +5113,16 @@ stimulus-use@^0.50.0: dependencies: hotkeys-js ">=3" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0: - name string-width-cjs +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5204,8 +5222,14 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - name strip-ansi-cjs +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5605,8 +5629,16 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== From 64b7f09a9a3b44b7874b53f5974eff84670cfbdc Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 15:02:10 +0200 Subject: [PATCH 03/13] add pasting support --- app/javascript/js/controllers/fields/markdown_controller.js | 5 +++++ package.json | 1 + yarn.lock | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/app/javascript/js/controllers/fields/markdown_controller.js b/app/javascript/js/controllers/fields/markdown_controller.js index 5256724b29..05781c9e8b 100644 --- a/app/javascript/js/controllers/fields/markdown_controller.js +++ b/app/javascript/js/controllers/fields/markdown_controller.js @@ -3,6 +3,7 @@ import '@github/markdown-toolbar-element' import { Controller } from '@hotwired/stimulus' import { DirectUpload } from '@rails/activestorage' import { post } from '@rails/request.js' +import { subscribe } from '@github/paste-markdown' // upload code from Jeremy Smith's blog post // https://hybrd.co/posts/github-issue-style-file-uploader-using-stimulus-and-active-storage @@ -18,6 +19,10 @@ export default class extends Controller { static targets = ['fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton'] + connect() { + subscribe(this.fieldElementTarget, { defaultPlainTextPaste: { urlLinks: true } }) + } + switchToWrite(event) { event.preventDefault() diff --git a/package.json b/package.json index 0ec08e0174..b6c92d9973 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@algolia/autocomplete-theme-classic": "^1.0.0-alpha.46", "@babel/plugin-proposal-class-properties": "^7.12.1", "@github/markdown-toolbar-element": "^2.2.3", + "@github/paste-markdown": "^1.5.3", "@hotwired/stimulus": "^3.2.2", "@hotwired/turbo-rails": "^8.0.12", "@rails/activestorage": "^6.1.710", diff --git a/yarn.lock b/yarn.lock index bb91e944a3..5f97ad9f53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1355,6 +1355,11 @@ resolved "https://registry.yarnpkg.com/@github/markdown-toolbar-element/-/markdown-toolbar-element-2.2.3.tgz#a062b0f79ab458b0adae01b6bb6c51c846526049" integrity sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A== +"@github/paste-markdown@^1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@github/paste-markdown/-/paste-markdown-1.5.3.tgz#75b404fbbae173e7c7f0ab1d7a920623b7eadc0c" + integrity sha512-PzZ1b3PaqBzYqbT4fwKEhiORf38h2OcGp2+JdXNNM7inZ7egaSmfmhyNkQILpqWfS0AYtRS3CDq6z03eZ8yOMQ== + "@hotwired/stimulus@>=3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.0.1.tgz#141f15645acaa3b133b7c247cad58ae252ffae85" From 23a375071d60628bc0cbe897147411b1af6934b7 Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 15:14:55 +0200 Subject: [PATCH 04/13] add better styles --- app/assets/stylesheets/avo.base.css | 1 + .../stylesheets/css/fields/markdown.css | 119 ++++++++++++++++++ .../markdown_field/show_component.html.erb | 2 +- .../fields/markdown_field/show_component.rb | 4 +- .../avo/markdown_previews_controller.rb | 5 +- .../markdown_previews/create.turbo_stream.erb | 2 +- lib/avo/fields/markdown_field.rb | 5 + 7 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 app/assets/stylesheets/css/fields/markdown.css diff --git a/app/assets/stylesheets/avo.base.css b/app/assets/stylesheets/avo.base.css index 4ed8088797..4b24c9283c 100644 --- a/app/assets/stylesheets/avo.base.css +++ b/app/assets/stylesheets/avo.base.css @@ -23,6 +23,7 @@ @import './css/fields/status.css'; @import './css/fields/code.css'; @import './css/fields/progress.css'; +@import './css/fields/markdown.css'; @import './css/fields/trix.css'; @import './css/fields/tags.css'; @import './css/fields/tiptap.css'; diff --git a/app/assets/stylesheets/css/fields/markdown.css b/app/assets/stylesheets/css/fields/markdown.css new file mode 100644 index 0000000000..08b4ea7f09 --- /dev/null +++ b/app/assets/stylesheets/css/fields/markdown.css @@ -0,0 +1,119 @@ +.markdown-content { + line-height: 1.5; + overflow-wrap: break-word; + word-break: break-word; + + & p, + & ul, + & ol, + & blockquote { + @apply mt-4; + } + + & ul { + @apply list-disc; + } + + & ol { + @apply list-decimal; + } +} + +/* original `trix-content` styles taken from the trix.css */ +.markdown-content { + line-height: 1.5; + overflow-wrap: break-word; + word-break: break-word; +} +.markdown-content * { + box-sizing: border-box; + margin: 0; + padding: 0; +} +.markdown-content h1 { + font-size: 1.2em; + line-height: 1.2; +} +.markdown-content blockquote { + border: 0 solid #ccc; + border-left-width: 0.3em; + margin-left: 0.3em; + padding-left: 0.6em; +} +.markdown-content [dir=rtl] blockquote, +.markdown-content blockquote[dir=rtl] { + border-width: 0; + border-right-width: 0.3em; + margin-right: 0.3em; + padding-right: 0.6em; +} +.markdown-content li { + margin-left: 1em; +} +.markdown-content [dir=rtl] li { + margin-right: 1em; +} +.markdown-content pre { + display: inline-block; + width: 100%; + vertical-align: top; + font-family: monospace; + font-size: 0.9em; + padding: 0.5em; + white-space: pre; + background-color: #eee; + overflow-x: auto; +} +.markdown-content img { + max-width: 100%; + height: auto; +} +.markdown-content .attachment { + display: inline-block; + position: relative; + max-width: 100%; +} +.markdown-content .attachment a { + color: inherit; + text-decoration: none; +} +.markdown-content .attachment a:hover, .markdown-content .attachment a:visited:hover { + color: inherit; +} +.markdown-content .attachment__caption { + text-align: center; +} +.markdown-content .attachment__caption .attachment__name + .attachment__size::before { + content: " •"; +} +.markdown-content .attachment--preview { + width: 100%; + text-align: center; +} +.markdown-content .attachment--preview .attachment__caption { + color: #666; + font-size: 0.9em; + line-height: 1.2; +} +.markdown-content .attachment--file { + color: #333; + line-height: 1; + margin: 0 2px 2px 2px; + padding: 0.4em 1em; + border: 1px solid #bbb; + border-radius: 5px; +} +.markdown-content .attachment-gallery { + display: flex; + flex-wrap: wrap; + position: relative; +} +.markdown-content .attachment-gallery .attachment { + flex: 1 0 33%; + padding: 0 0.5em; + max-width: 33%; +} +.markdown-content .attachment-gallery.attachment-gallery--2 .attachment, .markdown-content .attachment-gallery.attachment-gallery--4 .attachment { + flex-basis: 50%; + max-width: 50%; +} diff --git a/app/components/avo/fields/markdown_field/show_component.html.erb b/app/components/avo/fields/markdown_field/show_component.html.erb index 19e3ce0fc7..57c2819fa9 100644 --- a/app/components/avo/fields/markdown_field/show_component.html.erb +++ b/app/components/avo/fields/markdown_field/show_component.html.erb @@ -1,3 +1,3 @@ <%= field_wrapper **field_wrapper_args, full_width: true do %> - <%= content_tag :div, sanitize(parsed_body), class: "trix-content" %> + <%= content_tag :div, sanitize(parsed_body), class: "markdown-content" %> <% end %> diff --git a/app/components/avo/fields/markdown_field/show_component.rb b/app/components/avo/fields/markdown_field/show_component.rb index 30732b779b..ee8847f254 100644 --- a/app/components/avo/fields/markdown_field/show_component.rb +++ b/app/components/avo/fields/markdown_field/show_component.rb @@ -2,8 +2,6 @@ class Avo::Fields::MarkdownField::ShowComponent < Avo::Fields::ShowComponent def parsed_body - renderer = Redcarpet::Render::HTML.new(hard_wrap: true) - parser = Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) - parser.render(@field.value) + Avo::Fields::MarkdownField.parser.render(@field.value) end end diff --git a/app/controllers/avo/markdown_previews_controller.rb b/app/controllers/avo/markdown_previews_controller.rb index 6b014f5784..632725540c 100644 --- a/app/controllers/avo/markdown_previews_controller.rb +++ b/app/controllers/avo/markdown_previews_controller.rb @@ -1,10 +1,7 @@ module Avo class MarkdownPreviewsController < ApplicationController def create - renderer = Redcarpet::Render::HTML.new(hard_wrap: true) - parser = Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) - - @result = parser.render(params[:body]) + @result = Avo::Fields::MarkdownField.parser.render(params[:body]) end end end diff --git a/app/views/avo/markdown_previews/create.turbo_stream.erb b/app/views/avo/markdown_previews/create.turbo_stream.erb index 24be1c53e6..7caedf058a 100644 --- a/app/views/avo/markdown_previews/create.turbo_stream.erb +++ b/app/views/avo/markdown_previews/create.turbo_stream.erb @@ -1,5 +1,5 @@ <%= turbo_stream.update params[:element_id] do %> -
+
<%= sanitize(@result) %>
<% end %> diff --git a/lib/avo/fields/markdown_field.rb b/lib/avo/fields/markdown_field.rb index 40abcbf62b..9cb6938b4a 100644 --- a/lib/avo/fields/markdown_field.rb +++ b/lib/avo/fields/markdown_field.rb @@ -9,6 +9,11 @@ def initialize(id, **args, &block) hide_on :index add_string_prop args, :rows, default: 20 end + + def self.parser + renderer = Redcarpet::Render::HTML.new(hard_wrap: true) + Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) + end end end end From e921f83da897c1338c6ee4812eabad78450c5a52 Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 15:23:36 +0200 Subject: [PATCH 05/13] update appraisals --- gemfiles/rails_6.1_ruby_3.1.4.gemfile | 1 + gemfiles/rails_6.1_ruby_3.1.4.gemfile.lock | 2 ++ gemfiles/rails_6.1_ruby_3.3.0.gemfile | 1 + gemfiles/rails_6.1_ruby_3.3.0.gemfile.lock | 2 ++ gemfiles/rails_7.1_ruby_3.1.4.gemfile | 1 + gemfiles/rails_7.1_ruby_3.1.4.gemfile.lock | 2 ++ gemfiles/rails_7.1_ruby_3.3.0.gemfile | 1 + gemfiles/rails_7.1_ruby_3.3.0.gemfile.lock | 2 ++ gemfiles/rails_8.0_ruby_3.3.0.gemfile | 1 + gemfiles/rails_8.0_ruby_3.3.0.gemfile.lock | 2 ++ lib/avo/fields/markdown_field.rb | 4 ++-- 11 files changed, 17 insertions(+), 2 deletions(-) diff --git a/gemfiles/rails_6.1_ruby_3.1.4.gemfile b/gemfiles/rails_6.1_ruby_3.1.4.gemfile index 3efa925762..62348739af 100644 --- a/gemfiles/rails_6.1_ruby_3.1.4.gemfile +++ b/gemfiles/rails_6.1_ruby_3.1.4.gemfile @@ -45,6 +45,7 @@ gem "avo-money_field" gem "avo-record_link_field" gem "pagy", "> 8" gem "csv" +gem "redcarpet" gem "psych", "< 4" group :development do diff --git a/gemfiles/rails_6.1_ruby_3.1.4.gemfile.lock b/gemfiles/rails_6.1_ruby_3.1.4.gemfile.lock index ff5b510e1d..06c5d0eb8a 100644 --- a/gemfiles/rails_6.1_ruby_3.1.4.gemfile.lock +++ b/gemfiles/rails_6.1_ruby_3.1.4.gemfile.lock @@ -471,6 +471,7 @@ GEM ffi (~> 1.0) rbs (2.8.4) rdoc (6.3.4.1) + redcarpet (3.6.0) redis (5.3.0) redis-client (>= 0.22.0) redis-client (0.23.0) @@ -716,6 +717,7 @@ DEPENDENCIES rails (~> 6.1) rails-controller-testing ransack (>= 4.2.0) + redcarpet redis (~> 5.0) ripper-tags rspec-rails (~> 6.0, >= 6.0.3) diff --git a/gemfiles/rails_6.1_ruby_3.3.0.gemfile b/gemfiles/rails_6.1_ruby_3.3.0.gemfile index 3efa925762..62348739af 100644 --- a/gemfiles/rails_6.1_ruby_3.3.0.gemfile +++ b/gemfiles/rails_6.1_ruby_3.3.0.gemfile @@ -45,6 +45,7 @@ gem "avo-money_field" gem "avo-record_link_field" gem "pagy", "> 8" gem "csv" +gem "redcarpet" gem "psych", "< 4" group :development do diff --git a/gemfiles/rails_6.1_ruby_3.3.0.gemfile.lock b/gemfiles/rails_6.1_ruby_3.3.0.gemfile.lock index cdb920bd98..2a29be5e44 100644 --- a/gemfiles/rails_6.1_ruby_3.3.0.gemfile.lock +++ b/gemfiles/rails_6.1_ruby_3.3.0.gemfile.lock @@ -443,6 +443,7 @@ GEM ffi (~> 1.0) rbs (2.8.4) rdoc (6.3.4.1) + redcarpet (3.6.0) redis (5.3.0) redis-client (>= 0.22.0) redis-client (0.23.0) @@ -688,6 +689,7 @@ DEPENDENCIES rails (~> 6.1) rails-controller-testing ransack (>= 4.2.0) + redcarpet redis (~> 5.0) ripper-tags rspec-rails (~> 6.0, >= 6.0.3) diff --git a/gemfiles/rails_7.1_ruby_3.1.4.gemfile b/gemfiles/rails_7.1_ruby_3.1.4.gemfile index fa6cf77d06..3cac656285 100644 --- a/gemfiles/rails_7.1_ruby_3.1.4.gemfile +++ b/gemfiles/rails_7.1_ruby_3.1.4.gemfile @@ -45,6 +45,7 @@ gem "avo-money_field" gem "avo-record_link_field" gem "pagy", "> 8" gem "csv" +gem "redcarpet" gem "psych", "< 4" group :development do diff --git a/gemfiles/rails_7.1_ruby_3.1.4.gemfile.lock b/gemfiles/rails_7.1_ruby_3.1.4.gemfile.lock index 11e68b0520..f7f2361277 100644 --- a/gemfiles/rails_7.1_ruby_3.1.4.gemfile.lock +++ b/gemfiles/rails_7.1_ruby_3.1.4.gemfile.lock @@ -491,6 +491,7 @@ GEM ffi (~> 1.0) rbs (2.8.4) rdoc (6.3.4.1) + redcarpet (3.6.0) redis (5.3.0) redis-client (>= 0.22.0) redis-client (0.23.0) @@ -738,6 +739,7 @@ DEPENDENCIES rails (~> 7.1) rails-controller-testing ransack (>= 4.2.0) + redcarpet redis (~> 5.0) ripper-tags rspec-rails (~> 6.0, >= 6.0.3) diff --git a/gemfiles/rails_7.1_ruby_3.3.0.gemfile b/gemfiles/rails_7.1_ruby_3.3.0.gemfile index fa6cf77d06..3cac656285 100644 --- a/gemfiles/rails_7.1_ruby_3.3.0.gemfile +++ b/gemfiles/rails_7.1_ruby_3.3.0.gemfile @@ -45,6 +45,7 @@ gem "avo-money_field" gem "avo-record_link_field" gem "pagy", "> 8" gem "csv" +gem "redcarpet" gem "psych", "< 4" group :development do diff --git a/gemfiles/rails_7.1_ruby_3.3.0.gemfile.lock b/gemfiles/rails_7.1_ruby_3.3.0.gemfile.lock index c2049a0fb0..2339bfe94d 100644 --- a/gemfiles/rails_7.1_ruby_3.3.0.gemfile.lock +++ b/gemfiles/rails_7.1_ruby_3.3.0.gemfile.lock @@ -463,6 +463,7 @@ GEM ffi (~> 1.0) rbs (2.8.4) rdoc (6.3.4.1) + redcarpet (3.6.0) redis (5.3.0) redis-client (>= 0.22.0) redis-client (0.23.0) @@ -710,6 +711,7 @@ DEPENDENCIES rails (~> 7.1) rails-controller-testing ransack (>= 4.2.0) + redcarpet redis (~> 5.0) ripper-tags rspec-rails (~> 6.0, >= 6.0.3) diff --git a/gemfiles/rails_8.0_ruby_3.3.0.gemfile b/gemfiles/rails_8.0_ruby_3.3.0.gemfile index dd2424f93e..e7a16ccf9d 100644 --- a/gemfiles/rails_8.0_ruby_3.3.0.gemfile +++ b/gemfiles/rails_8.0_ruby_3.3.0.gemfile @@ -45,6 +45,7 @@ gem "avo-money_field" gem "avo-record_link_field" gem "pagy", "> 8" gem "csv" +gem "redcarpet" gem "psych", "< 4" group :development do diff --git a/gemfiles/rails_8.0_ruby_3.3.0.gemfile.lock b/gemfiles/rails_8.0_ruby_3.3.0.gemfile.lock index b498df40e7..110594b9fb 100644 --- a/gemfiles/rails_8.0_ruby_3.3.0.gemfile.lock +++ b/gemfiles/rails_8.0_ruby_3.3.0.gemfile.lock @@ -463,6 +463,7 @@ GEM ffi (~> 1.0) rbs (2.8.4) rdoc (6.3.4.1) + redcarpet (3.6.0) redis (5.3.0) redis-client (>= 0.22.0) redis-client (0.23.0) @@ -710,6 +711,7 @@ DEPENDENCIES rails (~> 8.0) rails-controller-testing ransack (>= 4.2.0) + redcarpet redis (~> 5.0) ripper-tags rspec-rails (~> 6.0, >= 6.0.3) diff --git a/lib/avo/fields/markdown_field.rb b/lib/avo/fields/markdown_field.rb index 9cb6938b4a..1c54a8c0ef 100644 --- a/lib/avo/fields/markdown_field.rb +++ b/lib/avo/fields/markdown_field.rb @@ -11,8 +11,8 @@ def initialize(id, **args, &block) end def self.parser - renderer = Redcarpet::Render::HTML.new(hard_wrap: true) - Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) + renderer = ::Redcarpet::Render::HTML.new(hard_wrap: true) + ::Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) end end end From 928623ea7dd0e82ee9ba04cfbd591e1b0dd425b9 Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 15:25:38 +0200 Subject: [PATCH 06/13] color zinc --- .../avo/fields/markdown_field/edit_component.html.erb | 4 ++-- app/components/avo/fields/markdown_field/edit_component.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/avo/fields/markdown_field/edit_component.html.erb b/app/components/avo/fields/markdown_field/edit_component.html.erb index 23d9713cba..57d0cb77b8 100644 --- a/app/components/avo/fields/markdown_field/edit_component.html.erb +++ b/app/components/avo/fields/markdown_field/edit_component.html.erb @@ -10,12 +10,12 @@ markdown_field_resource_class_value: @resource.class.name, markdown_field_field_id_value: @field.id, } do %> -
+
-
diff --git a/app/components/avo/fields/markdown_field/edit_component.rb b/app/components/avo/fields/markdown_field/edit_component.rb index be59612e7f..b9c1483a34 100644 --- a/app/components/avo/fields/markdown_field/edit_component.rb +++ b/app/components/avo/fields/markdown_field/edit_component.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true class Avo::Fields::MarkdownField::EditComponent < Avo::Fields::EditComponent - BUTTON_CLASSES = "cursor-pointer py-1 px-1.5 hover:bg-slate-200 rounded" + BUTTON_CLASSES = "cursor-pointer py-1 px-1.5 hover:bg-zinc-200 rounded" end From 1c008af920d699ee2467dc483d60bcae06f7a2bd Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 15:41:14 +0200 Subject: [PATCH 07/13] add i18n --- .../markdown_field/edit_component.html.erb | 24 +++++++++---------- .../avo/templates/locales/avo.en.yml | 12 ++++++++++ spec/dummy/config/locales/avo.en.yml | 12 ++++++++++ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/app/components/avo/fields/markdown_field/edit_component.html.erb b/app/components/avo/fields/markdown_field/edit_component.html.erb index 57d0cb77b8..639cda9f43 100644 --- a/app/components/avo/fields/markdown_field/edit_component.html.erb +++ b/app/components/avo/fields/markdown_field/edit_component.html.erb @@ -13,24 +13,24 @@
- <%= helpers.svg "heroicons/outline/bold", class: "inline size-4" %> - <%= helpers.svg "avo/heading", class: "inline size-4" %> - <%= helpers.svg "heroicons/outline/italic", class: "inline size-4" %> - <%= helpers.svg "avo/quote", class: "inline size-4" %> - <%= helpers.svg "heroicons/outline/code", class: "inline size-4" %> - <%= helpers.svg "heroicons/outline/link", class: "inline size-4" %> - <%= helpers.svg "heroicons/outline/photo", class: "inline size-4" %> - <%= helpers.svg "heroicons/outline/list-bullet", class: "inline size-4" %> - <%= helpers.svg "heroicons/outline/numbered-list", class: "inline size-4" %> - <%= helpers.svg "avo/list-todo", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/bold", class: "inline size-4" %> + <%= helpers.svg "avo/heading", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/italic", class: "inline size-4" %> + <%= helpers.svg "avo/quote", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/code", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/link", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/photo", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/list-bullet", class: "inline size-4" %> + <%= helpers.svg "heroicons/outline/numbered-list", class: "inline size-4" %> + <%= helpers.svg "avo/list-todo", class: "inline size-4" %>
diff --git a/lib/generators/avo/templates/locales/avo.en.yml b/lib/generators/avo/templates/locales/avo.en.yml index ca4b5e87e2..23b39a5524 100644 --- a/lib/generators/avo/templates/locales/avo.en.yml +++ b/lib/generators/avo/templates/locales/avo.en.yml @@ -85,6 +85,7 @@ en: to_top: Move record to top per_page: Per page prev_page: Previous page + preview: preview records_selected_from_all_pages_html: All records selected from all pages remove_selection: Remove selection reset: reset @@ -118,6 +119,7 @@ en: visit_record_on_external_path: Visit record on external path was_successfully_created: was successfully created was_successfully_updated: was successfully updated + write: write x_items_more: one: one more item other: "%{count} more items" @@ -129,3 +131,13 @@ en: you_cant_upload_new_resource: You can't upload files into the Trix editor until you save the resource. you_havent_set_attachment_key: You haven't set an `attachment_key` to this Trix field. you_missed_something_check_form: You might have missed something. Please check the form. + bold: bold + heading: heading + italic: italic + quote: quote + code: code + link: link + image: image + unordered_list: unordered list + ordered_list: ordered list + task_list: task list diff --git a/spec/dummy/config/locales/avo.en.yml b/spec/dummy/config/locales/avo.en.yml index 94c1036381..42d21e71d4 100644 --- a/spec/dummy/config/locales/avo.en.yml +++ b/spec/dummy/config/locales/avo.en.yml @@ -82,6 +82,7 @@ en: to_top: Move record to top per_page: Per page prev_page: Previous page + preview: preview records_selected_from_all_pages_html: All records selected from all pages remove_selection: Remove selection reset_filters: Reset filters @@ -113,6 +114,7 @@ en: visit_record_on_external_path: Visit record on external path was_successfully_created: was successfully created was_successfully_updated: was successfully updated + write: write x_items_more: one: one more item other: "%{count} more items" @@ -127,3 +129,13 @@ en: user_names_filter: name: User names filter button_label: Filter by user names + bold: bold + heading: heading + italic: italic + quote: quote + code: code + link: link + image: image + unordered_list: unordered list + ordered_list: ordered list + task_list: task list From a58ac736eeeca2cd863d98e36ce8411e2da97f5b Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 14 Jan 2025 16:33:55 +0200 Subject: [PATCH 08/13] wip --- app/assets/stylesheets/css/fields/markdown.css | 9 +++++++++ lib/avo/fields/markdown_field.rb | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/css/fields/markdown.css b/app/assets/stylesheets/css/fields/markdown.css index 08b4ea7f09..51346215f2 100644 --- a/app/assets/stylesheets/css/fields/markdown.css +++ b/app/assets/stylesheets/css/fields/markdown.css @@ -3,6 +3,15 @@ overflow-wrap: break-word; word-break: break-word; + & h1, + & h2, + & h3, + & h4, + & h5, + & h6, + & table, + & div, + & pre, & p, & ul, & ol, diff --git a/lib/avo/fields/markdown_field.rb b/lib/avo/fields/markdown_field.rb index 1c54a8c0ef..7ea3d53024 100644 --- a/lib/avo/fields/markdown_field.rb +++ b/lib/avo/fields/markdown_field.rb @@ -11,8 +11,19 @@ def initialize(id, **args, &block) end def self.parser - renderer = ::Redcarpet::Render::HTML.new(hard_wrap: true) - ::Redcarpet::Markdown.new(renderer, lax_spacing: true, fenced_code_blocks: true, hard_wrap: true) + ::Redcarpet::Markdown.new(::Redcarpet::Render::HTML, + tables: true, + lax_spacing: true, + fenced_code_blocks: true, + space_after_headers: true, + hard_wrap: true, + autolink: true, + strikethrough: true, + underline: true, + highlight: true, + quote: true, + with_toc_data: true + ) end end end From 968459197c9fb33c9a39208ff8f6c9689db8e926 Mon Sep 17 00:00:00 2001 From: Paul Bob Date: Wed, 15 Jan 2025 12:17:26 +0200 Subject: [PATCH 09/13] i18n tasks --- CONTRIBUTING.MD | 29 +++++++++++++++++++ .../avo/templates/locales/avo.ar.yml | 12 ++++++++ .../avo/templates/locales/avo.de.yml | 12 ++++++++ .../avo/templates/locales/avo.en.yml | 20 ++++++------- .../avo/templates/locales/avo.es.yml | 12 ++++++++ .../avo/templates/locales/avo.fr.yml | 12 ++++++++ .../avo/templates/locales/avo.it.yml | 12 ++++++++ .../avo/templates/locales/avo.ja.yml | 12 ++++++++ .../avo/templates/locales/avo.nb.yml | 12 ++++++++ .../avo/templates/locales/avo.nl.yml | 12 ++++++++ .../avo/templates/locales/avo.nn.yml | 12 ++++++++ .../avo/templates/locales/avo.pl.yml | 12 ++++++++ .../avo/templates/locales/avo.pt-BR.yml | 12 ++++++++ .../avo/templates/locales/avo.pt.yml | 12 ++++++++ .../avo/templates/locales/avo.ro.yml | 12 ++++++++ .../avo/templates/locales/avo.ru.yml | 12 ++++++++ .../avo/templates/locales/avo.tr.yml | 12 ++++++++ .../avo/templates/locales/avo.uk.yml | 12 ++++++++ .../avo/templates/locales/avo.zh.yml | 12 ++++++++ 19 files changed, 243 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD index 6004c46a6e..b42c4e131e 100644 --- a/CONTRIBUTING.MD +++ b/CONTRIBUTING.MD @@ -224,3 +224,32 @@ To keep track of the schema structure for the models, run `annotate --models --e ## Using VSCode? We compiled [an extension pack](https://marketplace.visualstudio.com/items?itemName=adrianthedev.vsruby) with a few extensions that should help you with Ruby development. We use them with Avo. + +## Adding I18n Keys + +When incorporating I18n keys, such as `avo.preview`, it's important to ensure that all locale files include the key with appropriate translations. + +### Step 1: Add and Normalize +First, add the key to the `avo.en.yml` file. Then, run the following command to normalize the locale files alphabetically: +```bash +i18n-tasks normalize +``` + +### Step 2: Adding Missing Keys with or without Translation + +When adding missing keys, you have two options: proceed without translation or automatically translate them using OpenAI. + +#### Option 1: Add Missing Keys Without Translation +Run the following command to add the missing keys to all locale files: +```bash +i18n-tasks add-missing +``` +This will populate the missing keys but retain the original label without translations applied. + +#### Option 2: Add and Automatically Translate Missing Keys +If you prefer to automatically translate the missing keys, skip the previous step and execute this command with your OpenAI API token: +```bash +OPENAI_API_KEY=TOKEN bundle exec i18n-tasks translate-missing --backend=openai +``` + +Replace `TOKEN` with your actual OpenAI API key. This step will both add the missing keys and translate them automatically. diff --git a/lib/generators/avo/templates/locales/avo.ar.yml b/lib/generators/avo/templates/locales/avo.ar.yml index 9c132a9fc1..7d3945958b 100644 --- a/lib/generators/avo/templates/locales/avo.ar.yml +++ b/lib/generators/avo/templates/locales/avo.ar.yml @@ -22,6 +22,7 @@ ar: attachment_class_detached: "%{attachment_class} تم فصل" attachment_destroyed: تم حذف المرفق attachment_failed: فشل في إرفاق %{attachment_class} + bold: bold cancel: إلغاء choose_a_country: اختر دولة choose_an_option: اختر خيارًا @@ -29,6 +30,7 @@ ar: clear_value: مسح القيمة click_to_reveal_filters: انقر لإظهار المرشحات close_modal: أغلق النافذة + code: code confirm: تأكيد copy: نسخ create_new_item: إنشاء %{item} جديد @@ -60,8 +62,11 @@ ar: filters: مرشحات go_back: العودة للخلف grid_view: عرض الشبكة + heading: heading hide_content: إخفاء المحتوى home: الصفحة الرئيسية + image: image + italic: italic key_value_field: add_row: إضافة صف delete_row: حذف صف @@ -69,6 +74,7 @@ ar: reorder_row: إعادة ترتيب الصف value: القيمة less_content: محتوى أقل + link: link list_is_empty: القائمة فارغة loading: جاري التحميل more: المزيد @@ -93,8 +99,11 @@ ar: reorder_record: إعادة ترتيب السجل to_bottom: حرك السجل للأسفل بشكل كامل to_top: حرك السجل للأعلى بشكل كامل + ordered_list: ordered list per_page: لكل صفحة prev_page: الصفحة السابقة + preview: معاينة + quote: quote records_selected_from_all_pages_html: جميع السجلات مختارة من جميع الصفحات remove_selection: إزالة التحديد reset: اعاده تعيين @@ -118,16 +127,19 @@ ar: sort_reset: إعادة تهيئة الترتيب switch_to_view: التبديل إلى عرض %{view_type} table_view: عرض الجدول + task_list: task list this_field_has_attachments_disabled: هذا الحقل لديه المرفقات معطلة. tools: الأدوات type_to_search: اكتب للبحث. unauthorized: غير مصرح به undo: تراجع + unordered_list: unordered list view: عرض view_item: عرض %{item} visit_record_on_external_path: زيارة السجل على الرابط الخارجي was_successfully_created: تم إنشاؤه بنجاح was_successfully_updated: تم تحديثه بنجاح + write: كتابة x_items_more: one: عنصر واحد إضافي other: "%{count} عناصر إضافية" diff --git a/lib/generators/avo/templates/locales/avo.de.yml b/lib/generators/avo/templates/locales/avo.de.yml index 7b470689e7..f02f6dd85b 100644 --- a/lib/generators/avo/templates/locales/avo.de.yml +++ b/lib/generators/avo/templates/locales/avo.de.yml @@ -16,6 +16,7 @@ de: attachment_class_detached: "%{attachment_class} abgehängt." attachment_destroyed: Anhang gelöscht attachment_failed: "%{attachment_class} konnte nicht angehängt werden" + bold: bold cancel: Abbrechen choose_a_country: Land auswählen choose_an_option: Option auswählen @@ -23,6 +24,7 @@ de: clear_value: Wert löschen click_to_reveal_filters: Klicken, um Filter anzuzeigen close_modal: Modal schließen + code: code confirm: Bestätigen copy: Kopieren create_new_item: Neues %{item} erstellen @@ -50,8 +52,11 @@ de: filters: Filter go_back: Zurück grid_view: Rasteransicht + heading: heading hide_content: Inhalt ausblenden home: Startseite + image: image + italic: italic key_value_field: add_row: Zeile hinzufügen delete_row: Zeile löschen @@ -59,6 +64,7 @@ de: reorder_row: Zeile neu anordnen value: Wert less_content: Weniger Inhalt + link: link list_is_empty: Liste ist leer loading: Lade... more: Mehr @@ -83,8 +89,11 @@ de: reorder_record: Eintrag neu anordnen to_bottom: Eintrag ans Ende verschieben to_top: Eintrag an den Anfang verschieben + ordered_list: ordered list per_page: Pro Seite prev_page: Vorherige Seite + preview: Vorschau + quote: quote records_selected_from_all_pages_html: Alle Einträge von allen Seiten ausgewählt remove_selection: Auswahl aufheben reset: zurücksetzen @@ -108,16 +117,19 @@ de: sort_reset: Sortierung zurücksetzen switch_to_view: Wechseln zur %{view_type}-Ansicht table_view: Tabellenansicht + task_list: task list this_field_has_attachments_disabled: Für dieses Feld sind Anhänge deaktiviert. tools: Werkzeuge type_to_search: Tippen, um zu suchen. unauthorized: Nicht autorisiert undo: Rückgängig machen + unordered_list: unordered list view: Anzeigen view_item: "%{item} anzeigen" visit_record_on_external_path: Datensatz über externen Link besuchen was_successfully_created: wurde erfolgreich erstellt was_successfully_updated: wurde erfolgreich aktualisiert + write: schreiben x_items_more: one: noch ein Eintrag other: "%{count} weitere Einträge" diff --git a/lib/generators/avo/templates/locales/avo.en.yml b/lib/generators/avo/templates/locales/avo.en.yml index 23b39a5524..cbcac2fd96 100644 --- a/lib/generators/avo/templates/locales/avo.en.yml +++ b/lib/generators/avo/templates/locales/avo.en.yml @@ -16,6 +16,7 @@ en: attachment_class_detached: "%{attachment_class} detached." attachment_destroyed: Attachment destroyed attachment_failed: Failed to attach %{attachment_class} + bold: bold cancel: Cancel choose_a_country: Choose a country choose_an_option: Choose an option @@ -23,6 +24,7 @@ en: clear_value: Clear value click_to_reveal_filters: Click to reveal filters close_modal: Close modal + code: code confirm: Confirm copy: Copy create_new_item: Create new %{item} @@ -50,8 +52,11 @@ en: filters: Filters go_back: Go back grid_view: Grid view + heading: heading hide_content: Hide content home: Home + image: image + italic: italic key_value_field: add_row: Add row delete_row: Delete row @@ -59,6 +64,7 @@ en: reorder_row: Reorder row value: Value less_content: Less content + link: link list_is_empty: List is empty loading: Loading more: More @@ -83,9 +89,11 @@ en: reorder_record: Reorder record to_bottom: Move record to bottom to_top: Move record to top + ordered_list: ordered list per_page: Per page prev_page: Previous page preview: preview + quote: quote records_selected_from_all_pages_html: All records selected from all pages remove_selection: Remove selection reset: reset @@ -109,11 +117,13 @@ en: sort_reset: Reset sorting switch_to_view: Switch to %{view_type} view table_view: Table view + task_list: task list this_field_has_attachments_disabled: This field has attachments disabled. tools: Tools type_to_search: Type to search. unauthorized: Unauthorized undo: undo + unordered_list: unordered list view: View view_item: view %{item} visit_record_on_external_path: Visit record on external path @@ -131,13 +141,3 @@ en: you_cant_upload_new_resource: You can't upload files into the Trix editor until you save the resource. you_havent_set_attachment_key: You haven't set an `attachment_key` to this Trix field. you_missed_something_check_form: You might have missed something. Please check the form. - bold: bold - heading: heading - italic: italic - quote: quote - code: code - link: link - image: image - unordered_list: unordered list - ordered_list: ordered list - task_list: task list diff --git a/lib/generators/avo/templates/locales/avo.es.yml b/lib/generators/avo/templates/locales/avo.es.yml index 5b8f4f968e..209976b913 100644 --- a/lib/generators/avo/templates/locales/avo.es.yml +++ b/lib/generators/avo/templates/locales/avo.es.yml @@ -18,6 +18,7 @@ es: attachment_class_detached: "%{attachment_class} adjuntado/a." attachment_destroyed: Adjunto eliminado attachment_failed: No se pudo adjuntar %{attachment_class} + bold: bold cancel: Cancelar choose_a_country: Elige un país choose_an_option: Elige una opción @@ -25,6 +26,7 @@ es: clear_value: Borrar el valor click_to_reveal_filters: Pulsa para mostrar los filtros close_modal: Cerrar modal + code: code confirm: Confirmar copy: Copiar create_new_item: Crear nuevo/a %{item} @@ -52,8 +54,11 @@ es: filters: Filtros go_back: Volver grid_view: Vista en cuardrícula + heading: heading hide_content: Ocultar contenido home: Inicio + image: image + italic: italic key_value_field: add_row: Añadir fila delete_row: Eliminar fila @@ -61,6 +66,7 @@ es: reorder_row: Reordenar fila value: Valor less_content: Menos contenido + link: link list_is_empty: La lista está vacía loading: Cargando more: Más @@ -85,8 +91,11 @@ es: reorder_record: Reordenar registro to_bottom: Mover abajo del todo to_top: Mover arriba del todo + ordered_list: ordered list per_page: Por página prev_page: Página anterior + preview: vista previa + quote: quote records_selected_from_all_pages_html: Todos los registros seleccionados de todas las páginas. remove_selection: Quitar la selección reset: restablecer @@ -110,16 +119,19 @@ es: sort_reset: Restablecer ordenación switch_to_view: Cambiar a la vista %{view_type} table_view: Vista en tabla + task_list: task list this_field_has_attachments_disabled: Este campo tiene los adjuntos deshabilitados. tools: Herramientas type_to_search: Escribe para buscar. unauthorized: No autorizado undo: deshacer + unordered_list: unordered list view: Vista view_item: ver %{item} visit_record_on_external_path: Visitar registro en enlace externo was_successfully_created: se ha creado con éxito was_successfully_updated: se ha actualizado con éxito + write: escribir x_items_more: one: un elemento más other: "%{count} elementos más" diff --git a/lib/generators/avo/templates/locales/avo.fr.yml b/lib/generators/avo/templates/locales/avo.fr.yml index 469734a976..5b0865e0af 100644 --- a/lib/generators/avo/templates/locales/avo.fr.yml +++ b/lib/generators/avo/templates/locales/avo.fr.yml @@ -18,6 +18,7 @@ fr: attachment_class_detached: "%{attachment_class} détaché." attachment_destroyed: Pièce jointe détruite attachment_failed: Échec de l'ajout de %{attachment_class} + bold: bold cancel: Annuler choose_a_country: Sélectionnez un pays choose_an_option: Sélectionnez une option @@ -25,6 +26,7 @@ fr: clear_value: Effacer la valeur click_to_reveal_filters: Cliquez pour révéler les filtres close_modal: Fermer la fenêtre modale + code: code confirm: Confirmer copy: Copier create_new_item: Créer un nouveau %{item} @@ -52,8 +54,11 @@ fr: filters: Filtres go_back: Retourner en arrière grid_view: Vue grille + heading: heading hide_content: Cacher le contenu home: Accueil + image: image + italic: italic key_value_field: add_row: Ajouter une ligne delete_row: Supprimer une ligne @@ -61,6 +66,7 @@ fr: reorder_row: Réorganiser la ligne value: Valeur less_content: Moins de contenu + link: link list_is_empty: La liste est vide loading: Chargement more: Plus @@ -85,8 +91,11 @@ fr: reorder_record: Réorganiser to_bottom: Déplacer tout en bas to_top: Déplacer tout en haut + ordered_list: ordered list per_page: Par page prev_page: Page précédente + preview: aperçu + quote: quote records_selected_from_all_pages_html: tous les éléments sélectionnés de toutes les pages remove_selection: Supprimer la sélection reset: réinitialiser @@ -110,16 +119,19 @@ fr: sort_reset: Réinitialiser le tri switch_to_view: Passez à la vue %{view_type} table_view: Vue table + task_list: task list this_field_has_attachments_disabled: Ce champ a les pièces jointes désactivées. tools: Outils type_to_search: Type à rechercher. unauthorized: Non autorisé undo: annuler + unordered_list: unordered list view: Vue view_item: voir %{item} visit_record_on_external_path: Consulter l'enregistrement via un lien externe was_successfully_created: a été créé avec succès was_successfully_updated: a été mis à jour avec succès + write: écrire x_items_more: one: un élément de plus other: "%{count} éléments en plus" diff --git a/lib/generators/avo/templates/locales/avo.it.yml b/lib/generators/avo/templates/locales/avo.it.yml index 4948c695b3..9e451cee61 100644 --- a/lib/generators/avo/templates/locales/avo.it.yml +++ b/lib/generators/avo/templates/locales/avo.it.yml @@ -16,6 +16,7 @@ it: attachment_class_detached: "%{attachment_class} staccato." attachment_destroyed: Allegato distrutto attachment_failed: Impossibile allegare %{attachment_class} + bold: bold cancel: Annulla choose_a_country: Scegli un paese choose_an_option: Scegli un'opzione @@ -23,6 +24,7 @@ it: clear_value: Cancella valore click_to_reveal_filters: Clicca per mostrare i filtri close_modal: Chiudi modale + code: code confirm: Conferma copy: Copia create_new_item: Crea nuovo %{item} @@ -50,8 +52,11 @@ it: filters: Filtri go_back: Torna indietro grid_view: Vista griglia + heading: heading hide_content: Nascondi contenuto home: Home + image: image + italic: italic key_value_field: add_row: Aggiungi riga delete_row: Elimina riga @@ -59,6 +64,7 @@ it: reorder_row: Riordina riga value: Valore less_content: Meno contenuti + link: link list_is_empty: La lista è vuota loading: Caricamento in corso more: Altro @@ -83,8 +89,11 @@ it: reorder_record: Riordina record to_bottom: Sposta record in fondo to_top: Sposta record in cima + ordered_list: ordered list per_page: Per pagina prev_page: Pagina precedente + preview: anteprima + quote: quote records_selected_from_all_pages_html: Tutti i record selezionati da tutte le pagine remove_selection: Rimuovi selezione reset: Reimposta @@ -108,16 +117,19 @@ it: sort_reset: Reimposta ordinamento switch_to_view: Passa a vista %{view_type} table_view: Vista tabella + task_list: task list this_field_has_attachments_disabled: Gli allegati sono disabilitati per questo campo. tools: Strumenti type_to_search: Digita per cercare. unauthorized: Non autorizzato undo: Annulla + unordered_list: unordered list view: Visualizza view_item: Visualizza %{item} visit_record_on_external_path: Visita il record tramite link esterno was_successfully_created: è stato creato con successo was_successfully_updated: è stato aggiornato con successo + write: scrivi x_items_more: one: un altro elemento other: "%{count} altri elementi" diff --git a/lib/generators/avo/templates/locales/avo.ja.yml b/lib/generators/avo/templates/locales/avo.ja.yml index 29503a65c4..796555db82 100644 --- a/lib/generators/avo/templates/locales/avo.ja.yml +++ b/lib/generators/avo/templates/locales/avo.ja.yml @@ -18,6 +18,7 @@ ja: attachment_class_detached: "%{attachment_class}をデタッチしました。" attachment_destroyed: アタッチは削除されました attachment_failed: "%{attachment_class}の添付に失敗しました" + bold: bold cancel: キャンセル choose_a_country: 国を選択 choose_an_option: オプションを選択 @@ -25,6 +26,7 @@ ja: clear_value: 値をクリア click_to_reveal_filters: フィルターを表示するにはクリック close_modal: モーダルを閉じる + code: code confirm: 確認 copy: コピー create_new_item: 新しい%{item}を作成 @@ -52,8 +54,11 @@ ja: filters: フィルター go_back: 戻る grid_view: グリッドビュー + heading: heading hide_content: 内容を非表示 home: ホーム + image: image + italic: italic key_value_field: add_row: 行を追加 delete_row: 行を削除 @@ -61,6 +66,7 @@ ja: reorder_row: 行の並べ替え value: 値 less_content: コンテンツが少ない + link: link list_is_empty: リストは空です loading: 読み込み中 more: もっと @@ -85,8 +91,11 @@ ja: reorder_record: レコードを並べ替える to_bottom: レコードを一番下に移動 to_top: レコードを一番上に移動 + ordered_list: ordered list per_page: ページあたり prev_page: 前のページ + preview: プレビュー + quote: quote records_selected_from_all_pages_html: 全ページから選択された全レコード remove_selection: 選択を解除 reset: リセット @@ -110,16 +119,19 @@ ja: sort_reset: ソートをリセット switch_to_view: "%{view_type}ビューに切り替える" table_view: テーブルビュー + task_list: task list this_field_has_attachments_disabled: このフィールドには添付ファイルが無効になっています。 tools: ツール type_to_search: 検索する内容を入力してください。 unauthorized: 許可されていません undo: 元に戻す + unordered_list: unordered list view: ビュー view_item: "%{item}を表示" visit_record_on_external_path: 外部リンクで記録を確認する was_successfully_created: は正常に作成されました was_successfully_updated: は正常に更新されました + write: 書く x_items_more: one: もう一つのアイテム other: "%{count}個のその他のアイテム" diff --git a/lib/generators/avo/templates/locales/avo.nb.yml b/lib/generators/avo/templates/locales/avo.nb.yml index 804688b0ef..9ebccff822 100644 --- a/lib/generators/avo/templates/locales/avo.nb.yml +++ b/lib/generators/avo/templates/locales/avo.nb.yml @@ -18,6 +18,7 @@ nb: attachment_class_detached: "%{attachment_class} fjernet." attachment_destroyed: Vedlett slettet attachment_failed: Kunne ikke legge ved %{attachment_class} + bold: bold cancel: Avbryt choose_a_country: Velg et land choose_an_option: Velg et alternativ @@ -25,6 +26,7 @@ nb: clear_value: Nullstill verdi click_to_reveal_filters: Vis filter close_modal: Lukk modal + code: code confirm: Bekreft copy: Kopier create_new_item: Lag ny %{item} @@ -52,8 +54,11 @@ nb: filters: Filter go_back: Gå tilbake grid_view: Grid visning + heading: heading hide_content: Skjul innhold home: Hjem + image: image + italic: italic key_value_field: add_row: Legg til rad delete_row: Slett rad @@ -61,6 +66,7 @@ nb: reorder_row: Omorganiser rad value: Verdi less_content: Mindre innhold + link: link list_is_empty: Listen er tom loading: Laster more: Mer @@ -85,8 +91,11 @@ nb: reorder_record: Sorter elementer to_bottom: Flytt elementet til bunnen to_top: Flytt elementet til toppen + ordered_list: ordered list per_page: Per side prev_page: Forrige side + preview: forhåndsvisning + quote: quote records_selected_from_all_pages_html: Alle poster valgt fra alle sider remove_selection: Fjern valg reset: nullstille @@ -110,16 +119,19 @@ nb: sort_reset: Tilbakestill sortering switch_to_view: Bytt til %{view_type} vis table_view: Tabell visning + task_list: task list this_field_has_attachments_disabled: Dette feltet har vedlegg deaktivert. tools: Redskapene type_to_search: Søk. unauthorized: Ikke autorisert undo: angre + unordered_list: unordered list view: Vis view_item: vis %{item} visit_record_on_external_path: Besøk posten via en ekstern lenke was_successfully_created: ble opprettet was_successfully_updated: ble oppdatert + write: skriv x_items_more: one: ett element til other: "%{count} flere elementer" diff --git a/lib/generators/avo/templates/locales/avo.nl.yml b/lib/generators/avo/templates/locales/avo.nl.yml index 3cf83b2f0a..3581794f84 100644 --- a/lib/generators/avo/templates/locales/avo.nl.yml +++ b/lib/generators/avo/templates/locales/avo.nl.yml @@ -16,6 +16,7 @@ nl: attachment_class_detached: "%{attachment_class} losgekoppeld." attachment_destroyed: Bijlage verwijderd attachment_failed: Kon %{attachment_class} niet bijvoegen + bold: bold cancel: Annuleren choose_a_country: Kies een land choose_an_option: Kies een optie @@ -23,6 +24,7 @@ nl: clear_value: Waarde wissen click_to_reveal_filters: Klik om filters te tonen close_modal: Modaal sluiten + code: code confirm: Bevestigen copy: Kopie create_new_item: Nieuw %{item} aanmaken @@ -50,8 +52,11 @@ nl: filters: Filters go_back: Terug grid_view: Rasterweergave + heading: heading hide_content: Inhoud verbergen home: Startpagina + image: image + italic: italic key_value_field: add_row: Rij toevoegen delete_row: Rij verwijderen @@ -59,6 +64,7 @@ nl: reorder_row: Rij herschikken value: Waarde less_content: Minder inhoud + link: link list_is_empty: Lijst is leeg loading: Laden... more: Meer @@ -83,8 +89,11 @@ nl: reorder_record: Record opnieuw ordenen to_bottom: Verplaats record naar onderen to_top: Verplaats record naar boven + ordered_list: ordered list per_page: Per pagina prev_page: Vorige pagina + preview: voorbeeld + quote: quote records_selected_from_all_pages_html: Alle geselecteerde records van alle pagina's remove_selection: Selectie verwijderen reset: resetten @@ -108,16 +117,19 @@ nl: sort_reset: Sortering resetten switch_to_view: Schakelen naar %{view_type}-weergave table_view: Tabelweergave + task_list: task list this_field_has_attachments_disabled: Bijlagen zijn uitgeschakeld voor dit veld. tools: Gereedschappen type_to_search: Typ om te zoeken. unauthorized: Niet geautoriseerd undo: Ongedaan maken + unordered_list: unordered list view: Bekijken view_item: "%{item} bekijken" visit_record_on_external_path: Bezoek record via een externe link was_successfully_created: is succesvol aangemaakt was_successfully_updated: is succesvol bijgewerkt + write: schrijf x_items_more: one: nog één item other: "%{count} andere items" diff --git a/lib/generators/avo/templates/locales/avo.nn.yml b/lib/generators/avo/templates/locales/avo.nn.yml index 91006ffc43..8aedf30c23 100644 --- a/lib/generators/avo/templates/locales/avo.nn.yml +++ b/lib/generators/avo/templates/locales/avo.nn.yml @@ -18,6 +18,7 @@ nn: attachment_class_detached: "%{attachment_class} fjerna." attachment_destroyed: Vedlegg sletta attachment_failed: Klarte ikkje å legge ved %{attachment_class} + bold: bold cancel: Avbryt choose_a_country: Vel eit land choose_an_option: Vel eit alternativ @@ -25,6 +26,7 @@ nn: clear_value: Nullstill verdi click_to_reveal_filters: Vis filter close_modal: Lukk modal + code: code confirm: Stadfest copy: Kopier create_new_item: Lag ny %{item} @@ -52,8 +54,11 @@ nn: filters: Filter go_back: Gå tilbake grid_view: Gridvisning + heading: heading hide_content: Skjul innhald home: Heim + image: image + italic: italic key_value_field: add_row: Legg til rad delete_row: Slett rad @@ -61,6 +66,7 @@ nn: reorder_row: Omorganiser rad value: Verdi less_content: Mindre innhold + link: link list_is_empty: Lista er tom loading: Lastar more: Meir @@ -85,8 +91,11 @@ nn: reorder_record: Sorter element to_bottom: Flytt elementet til botnen to_top: Flytt elementet til toppen + ordered_list: ordered list per_page: Per side prev_page: Førre side + preview: førevising + quote: quote records_selected_from_all_pages_html: Alle poster valgt fra alle sider remove_selection: Fjern val reset: nullstille @@ -110,16 +119,19 @@ nn: sort_reset: Nullstill sortering switch_to_view: Bytt til %{view_type} vis table_view: Tabellvisning + task_list: task list this_field_has_attachments_disabled: Dette feltet har vedlegg deaktivert. tools: Reiskapane type_to_search: Søk. unauthorized: Ikkje autorisert undo: angre + unordered_list: unordered list view: Vis view_item: vis %{item} visit_record_on_external_path: Besøk posten via ein ekstern lenke was_successfully_created: vart oppretta was_successfully_updated: vart oppdatert + write: skriv x_items_more: one: eitt element til other: "%{count} fleire element" diff --git a/lib/generators/avo/templates/locales/avo.pl.yml b/lib/generators/avo/templates/locales/avo.pl.yml index 225c5e1d8a..410633a1ca 100644 --- a/lib/generators/avo/templates/locales/avo.pl.yml +++ b/lib/generators/avo/templates/locales/avo.pl.yml @@ -16,6 +16,7 @@ pl: attachment_class_detached: "%{attachment_class} odłączony." attachment_destroyed: Załącznik usunięty attachment_failed: Nie udało się dołączyć %{attachment_class} + bold: bold cancel: Anuluj choose_a_country: Wybierz kraj choose_an_option: Wybierz opcję @@ -23,6 +24,7 @@ pl: clear_value: Wyczyść wartość click_to_reveal_filters: Kliknij, aby pokazać filtry close_modal: Zamknij okno modalne + code: code confirm: Potwierdź copy: Kopiuj create_new_item: Utwórz nowy %{item} @@ -52,8 +54,11 @@ pl: filters: Filtry go_back: Wróć grid_view: Widok siatki + heading: heading hide_content: Ukryj zawartość home: Strona główna + image: image + italic: italic key_value_field: add_row: Dodaj wiersz delete_row: Usuń wiersz @@ -61,6 +66,7 @@ pl: reorder_row: Zmień kolejność wiersza value: Wartość less_content: Pokaż mniej + link: link list_is_empty: Lista jest pusta loading: Ładowanie more: Więcej @@ -85,8 +91,11 @@ pl: reorder_record: Zmień kolejność rekordów to_bottom: Przenieś rekord na dół to_top: Przenieś rekord na górę + ordered_list: ordered list per_page: Na stronie prev_page: Poprzednia strona + preview: podgląd + quote: quote records_selected_from_all_pages_html: Wybrane rekordy z wszystkich stron remove_selection: Usuń zaznaczenie reset: Resetuj @@ -110,16 +119,19 @@ pl: sort_reset: Resetuj sortowanie switch_to_view: Przełącz na widok %{view_type} table_view: Widok tabelaryczny + task_list: task list this_field_has_attachments_disabled: Załączniki są wyłączone dla tego pola. tools: Narzędzia type_to_search: Wpisz, aby wyszukać. unauthorized: Brak autoryzacji undo: Cofnij + unordered_list: unordered list view: Widok view_item: Wyświetl %{item} visit_record_on_external_path: Odwiedź rekord za pomocą zewnętrznego linku was_successfully_created: został pomyślnie utworzony was_successfully_updated: został pomyślnie zaktualizowany + write: napisz x_items_more: one: jeszcze jeden element other: "%{count} innych elementów" diff --git a/lib/generators/avo/templates/locales/avo.pt-BR.yml b/lib/generators/avo/templates/locales/avo.pt-BR.yml index 6fc43325d4..66f2b62b1a 100644 --- a/lib/generators/avo/templates/locales/avo.pt-BR.yml +++ b/lib/generators/avo/templates/locales/avo.pt-BR.yml @@ -18,6 +18,7 @@ pt-BR: attachment_class_detached: "%{attachment_class} separado." attachment_destroyed: Anexo destruído attachment_failed: Não foi possível anexar %{attachment_class} + bold: bold cancel: Cancelar choose_a_country: Escolha um país choose_an_option: Escolha uma opção @@ -25,6 +26,7 @@ pt-BR: clear_value: Limpar valor click_to_reveal_filters: Clique para revelar os filtros close_modal: Fechar modal + code: code confirm: Confirmar copy: Copiar create_new_item: Criar novo %{item} @@ -52,8 +54,11 @@ pt-BR: filters: Filtros go_back: Voltar grid_view: Visualização em grade + heading: heading hide_content: Esconder conteúdo home: Início + image: image + italic: italic key_value_field: add_row: Adicionar linha delete_row: Remover linha @@ -61,6 +66,7 @@ pt-BR: reorder_row: Reordenar linha value: Valor less_content: Menos conteúdo + link: link list_is_empty: Lista vazia loading: Carregando more: Mais @@ -85,8 +91,11 @@ pt-BR: reorder_record: Reordenar registro to_bottom: Mover registro para baixo to_top: Mover registro para cima + ordered_list: ordered list per_page: Por página prev_page: Página anterior + preview: visualização + quote: quote records_selected_from_all_pages_html: Todos os registros de todas as páginas selecionados remove_selection: Remover seleção reset: resetar @@ -110,16 +119,19 @@ pt-BR: sort_reset: Redefinir ordenação switch_to_view: Alterar para visão %{view_type} table_view: Visualização em tabela + task_list: task list this_field_has_attachments_disabled: Este campo tem anexos desativados. tools: Ferramentas type_to_search: Digite para buscar. unauthorized: Não autorizado undo: desfazer + unordered_list: unordered list view: Visualizar view_item: visualizar %{item} visit_record_on_external_path: Visitar registro através de link externo was_successfully_created: foi criado com sucesso was_successfully_updated: foi atualizado com sucesso + write: escrever x_items_more: one: mais um item other: "%{count} mais items" diff --git a/lib/generators/avo/templates/locales/avo.pt.yml b/lib/generators/avo/templates/locales/avo.pt.yml index 1af99f480c..ce6b02ac4a 100644 --- a/lib/generators/avo/templates/locales/avo.pt.yml +++ b/lib/generators/avo/templates/locales/avo.pt.yml @@ -18,6 +18,7 @@ pt: attachment_class_detached: "%{attachment_class} separado." attachment_destroyed: Anexo destruído attachment_failed: Não foi possível anexar %{attachment_class} + bold: bold cancel: Cancelar choose_a_country: Escolha um país choose_an_option: Escolha uma opção @@ -25,6 +26,7 @@ pt: clear_value: Apagar valor click_to_reveal_filters: Clique para mostrar os filtros close_modal: Fechar modal + code: code confirm: Confirmar copy: Copiar create_new_item: Criar novo %{item} @@ -52,8 +54,11 @@ pt: filters: Filtros go_back: Voltar grid_view: Visualização em grelha + heading: heading hide_content: Esconder conteúdo home: Início + image: image + italic: italic key_value_field: add_row: Adicionar linha delete_row: Apagar linha @@ -61,6 +66,7 @@ pt: reorder_row: Reordenar linha value: Valor less_content: Menos conteúdo + link: link list_is_empty: Lista vazia loading: A carregar more: Mais @@ -85,8 +91,11 @@ pt: reorder_record: Reordenar recurso to_bottom: Mover recurso para o fundo to_top: Mover recurso para o topo + ordered_list: ordered list per_page: Por página prev_page: Página anterior + preview: visualização + quote: quote records_selected_from_all_pages_html: Todos os itens de todas as páginas selecionados remove_selection: Remover seleção reset: restaurar @@ -110,16 +119,19 @@ pt: sort_reset: Redefinir ordenação switch_to_view: Alterar para visão %{view_type} table_view: Visualização em tabela + task_list: task list this_field_has_attachments_disabled: Este campo tem anexos desativados. tools: Ferramentas type_to_search: Escreva para pesquisar. unauthorized: Não autorizado undo: desfazer + unordered_list: unordered list view: Ver view_item: ver %{item} visit_record_on_external_path: Visitar registro através de link externo was_successfully_created: foi criado com sucesso was_successfully_updated: foi atualizado com sucesso + write: escrever x_items_more: one: mais um item other: "%{count} mais items" diff --git a/lib/generators/avo/templates/locales/avo.ro.yml b/lib/generators/avo/templates/locales/avo.ro.yml index 0e55df44f2..e4d08c0eda 100644 --- a/lib/generators/avo/templates/locales/avo.ro.yml +++ b/lib/generators/avo/templates/locales/avo.ro.yml @@ -19,6 +19,7 @@ ro: attachment_class_detached: "%{attachment_class} separat." attachment_destroyed: Atașamentul a fost distrus attachment_failed: Nu s-a reușit atașarea %{attachment_class} + bold: bold cancel: Anulează choose_a_country: Alege o țară choose_an_option: Alege o opțiune @@ -26,6 +27,7 @@ ro: clear_value: Șterge valoarea click_to_reveal_filters: Faceți clic pentru a afișa filtrele close_modal: Închide modalul + code: code confirm: Confirm copy: Copiază create_new_item: Creează %{item} @@ -54,8 +56,11 @@ ro: filters: Filtre go_back: Înapoi grid_view: Vezi sub formă de grid + heading: heading hide_content: Ascunde conținutul home: Acasă + image: image + italic: italic key_value_field: add_row: Adaugă rând delete_row: Șterge rând @@ -63,6 +68,7 @@ ro: reorder_row: Reordonează rând value: Valoare less_content: Mai puțin conținut + link: link list_is_empty: Lista este goală loading: Se incarcă more: Mai multe @@ -87,8 +93,11 @@ ro: reorder_record: Reordonați înregistrarea to_bottom: Mutați înregistrarea jos de tot to_top: Mutați înregistrarea sus de tot + ordered_list: ordered list per_page: Pe pagină prev_page: Pagina anterioara + preview: previzualizare + quote: quote records_selected_from_all_pages_html: Toate selectate din toate paginile remove_selection: Șterge selecția reset: resetare @@ -112,16 +121,19 @@ ro: sort_reset: Resetare sortare switch_to_view: Comutați la vizualizarea %{view_type} table_view: Vezi sub formă de tabel + task_list: task list this_field_has_attachments_disabled: Acest câmp are atașamente dezactivate. tools: Instrumente type_to_search: Caută aici... unauthorized: Neautorizat undo: Anulează + unordered_list: unordered list view: vezi view_item: vezi %{item} visit_record_on_external_path: Vizitați înregistrarea printr-un link extern was_successfully_created: a fost creat was_successfully_updated: a fost actualizat + write: scrie x_items_more: one: încă un articol other: "%{count} mai multe articole" diff --git a/lib/generators/avo/templates/locales/avo.ru.yml b/lib/generators/avo/templates/locales/avo.ru.yml index 4176255b50..f2c14a863a 100644 --- a/lib/generators/avo/templates/locales/avo.ru.yml +++ b/lib/generators/avo/templates/locales/avo.ru.yml @@ -16,6 +16,7 @@ ru: attachment_class_detached: "%{attachment_class} отсоединено." attachment_destroyed: Вложение удалено attachment_failed: Не удалось прикрепить %{attachment_class} + bold: bold cancel: Отмена choose_a_country: Выберите страну choose_an_option: Выберите опцию @@ -23,6 +24,7 @@ ru: clear_value: Очистить значение click_to_reveal_filters: Нажмите, чтобы открыть фильтры close_modal: Закрыть модальное окно + code: code confirm: Подтвердить copy: Копировать create_new_item: Создать новый %{item} @@ -52,8 +54,11 @@ ru: filters: Фильтры go_back: Назад grid_view: Сетка + heading: heading hide_content: Скрыть содержимое home: Главная + image: image + italic: italic key_value_field: add_row: Добавить строку delete_row: Удалить строку @@ -61,6 +66,7 @@ ru: reorder_row: Перенести строку value: Значение less_content: Меньше контента + link: link list_is_empty: Список пуст loading: Загрузка... more: Ещё @@ -85,8 +91,11 @@ ru: reorder_record: Переупорядочить запись to_bottom: Переместить запись в конец to_top: Переместить запись в начало + ordered_list: ordered list per_page: На странице prev_page: Предыдущая страница + preview: предпросмотр + quote: quote records_selected_from_all_pages_html: Все записи выбраны со всех страниц remove_selection: Убрать выбор reset: сбросить @@ -110,16 +119,19 @@ ru: sort_reset: Сбросить сортировку switch_to_view: Переключиться на вид %{view_type} table_view: Таблица + task_list: task list this_field_has_attachments_disabled: Для этого поля прикрепления отключены. tools: Инструменты type_to_search: Поиск... unauthorized: Не авторизован undo: Отменить + unordered_list: unordered list view: Просмотр view_item: Просмотр %{item} visit_record_on_external_path: Перейти к записи через внешнюю ссылку was_successfully_created: успешно создана was_successfully_updated: успешно обновлена + write: написать x_items_more: one: ещё один элемент other: "%{count} других элементов" diff --git a/lib/generators/avo/templates/locales/avo.tr.yml b/lib/generators/avo/templates/locales/avo.tr.yml index 85736fe6cc..2edfee7434 100644 --- a/lib/generators/avo/templates/locales/avo.tr.yml +++ b/lib/generators/avo/templates/locales/avo.tr.yml @@ -18,6 +18,7 @@ tr: attachment_class_detached: "%{attachment_class} ilişkisi kesildi." attachment_destroyed: Ek silindi attachment_failed: "%{attachment_class} eklenemedi" + bold: bold cancel: İptal et choose_a_country: Bir ülke seç choose_an_option: Bir seçenek seç @@ -25,6 +26,7 @@ tr: clear_value: Değeri temizle click_to_reveal_filters: Filtreleri ortaya çıkarmak için tıklayın close_modal: Modali kapat + code: code confirm: Onayla copy: Kopya create_new_item: Yeni bir %{item} oluşturun @@ -52,8 +54,11 @@ tr: filters: Filtreler go_back: Geri dön grid_view: Grid görünümü + heading: heading hide_content: İçeriği gizle home: Anasayfa + image: image + italic: italic key_value_field: add_row: Satır ekle delete_row: Satır sil @@ -61,6 +66,7 @@ tr: reorder_row: Satırı yeniden sırala value: Değer less_content: Daha az içerik + link: link list_is_empty: Boş liste loading: Yükleniyor more: Daha fazla @@ -85,8 +91,11 @@ tr: reorder_record: Kaydı yeniden sırala to_bottom: Kaydı en alta taşı to_top: Kaydı en üste taşı + ordered_list: ordered list per_page: Sayfa başına prev_page: Önceki sayfa + preview: önizleme + quote: quote records_selected_from_all_pages_html: Tüm sayfalardan seçilen tüm kayıtlar remove_selection: Seçimi sil reset: sıfırlama @@ -110,16 +119,19 @@ tr: sort_reset: Sıralamayı sıfırla switch_to_view: "%{view_type} görünümüne kay" table_view: Tablo görünümü + task_list: task list this_field_has_attachments_disabled: Bu alanın ekleri devre dışı bırakıldı. tools: Araçlar type_to_search: Aramak için yazın. unauthorized: Yetkisiz undo: geri al + unordered_list: unordered list view: Görünüm view_item: "%{item} öğresini görüntüle" visit_record_on_external_path: Harici bağlantı yoluyla kaydı ziyaret et was_successfully_created: başarıyla oluşturuldu was_successfully_updated: başarıyla güncellendi + write: yaz x_items_more: one: bir öğe daha other: "%{count} öğe daha" diff --git a/lib/generators/avo/templates/locales/avo.uk.yml b/lib/generators/avo/templates/locales/avo.uk.yml index f3bbb8f73f..e2d362515f 100644 --- a/lib/generators/avo/templates/locales/avo.uk.yml +++ b/lib/generators/avo/templates/locales/avo.uk.yml @@ -16,6 +16,7 @@ uk: attachment_class_detached: "%{attachment_class} відкріплено." attachment_destroyed: Вкладення знищено attachment_failed: Не вдалося прикріпити %{attachment_class} + bold: bold cancel: Скасувати choose_a_country: Виберіть країну choose_an_option: Виберіть опцію @@ -23,6 +24,7 @@ uk: clear_value: Очистити значення click_to_reveal_filters: Натисніть, щоб показати фільтри close_modal: Закрити вікно + code: code confirm: Підтвердити copy: Копіювати create_new_item: Створити новий %{item} @@ -52,8 +54,11 @@ uk: filters: Фільтри go_back: Назад grid_view: Плитка + heading: heading hide_content: Приховати вміст home: Головна + image: image + italic: italic key_value_field: add_row: Додати рядок delete_row: Видалити рядок @@ -61,6 +66,7 @@ uk: reorder_row: Змінити порядок рядка value: Значення less_content: Менше вмісту + link: link list_is_empty: Список порожній loading: Завантаження more: Ще @@ -85,8 +91,11 @@ uk: reorder_record: Перепорядкувати запис to_bottom: Перемістити запис вниз to_top: Перемістити запис вгору + ordered_list: ordered list per_page: На сторінці prev_page: Попередня сторінка + preview: перегляд + quote: quote records_selected_from_all_pages_html: Вибрані всі записи з усіх сторінок remove_selection: Видалити вибір reset: Скинути @@ -110,16 +119,19 @@ uk: sort_reset: Atstatyti rūšiavimą switch_to_view: Перейти до виду %{view_type} table_view: Таблиця + task_list: task list this_field_has_attachments_disabled: Прикріплення для цього поля вимкнено. tools: Інструменти type_to_search: Введіть для пошуку. unauthorized: Не авторизовано undo: Скасувати + unordered_list: unordered list view: Перегляд view_item: Перегляд %{item} visit_record_on_external_path: Перейти до запису через зовнішнє посилання was_successfully_created: успішно створено was_successfully_updated: успішно оновлено + write: написати x_items_more: one: ще один елемент other: "%{count} інших елементів" diff --git a/lib/generators/avo/templates/locales/avo.zh.yml b/lib/generators/avo/templates/locales/avo.zh.yml index 9e6b8b4070..37075b917a 100644 --- a/lib/generators/avo/templates/locales/avo.zh.yml +++ b/lib/generators/avo/templates/locales/avo.zh.yml @@ -16,6 +16,7 @@ zh: attachment_class_detached: "%{attachment_class} 已分离。" attachment_destroyed: 附件已删除 attachment_failed: 无法附加 %{attachment_class} + bold: bold cancel: 取消 choose_a_country: 选择一个国家 choose_an_option: 选择一个选项 @@ -23,6 +24,7 @@ zh: clear_value: 清除值 click_to_reveal_filters: 点击以显示筛选器 close_modal: 关闭模态框 + code: code confirm: 确认 copy: 复制 create_new_item: 创建新的 %{item} @@ -50,8 +52,11 @@ zh: filters: 筛选器 go_back: 返回 grid_view: 网格视图 + heading: heading hide_content: 隐藏内容 home: 主页 + image: image + italic: italic key_value_field: add_row: 添加行 delete_row: 删除行 @@ -59,6 +64,7 @@ zh: reorder_row: 重新排序行 value: 值 less_content: 内容较少 + link: link list_is_empty: 列表为空 loading: 加载中... more: 更多 @@ -83,8 +89,11 @@ zh: reorder_record: 重新排序记录 to_bottom: 将记录移至底部 to_top: 将记录移至顶部 + ordered_list: ordered list per_page: 每页显示 prev_page: 上一页 + preview: 预览 + quote: quote records_selected_from_all_pages_html: 所有页面中选中的记录 remove_selection: 清除选择 reset: 重置 @@ -108,16 +117,19 @@ zh: sort_reset: 重置排序 switch_to_view: 切换到 %{view_type} 视图 table_view: 表格视图 + task_list: task list this_field_has_attachments_disabled: 此字段已禁用附件。 tools: 工具 type_to_search: 输入以搜索。 unauthorized: 未经授权 undo: 撤销 + unordered_list: unordered list view: 查看 view_item: 查看 %{item} visit_record_on_external_path: 通过外部链接访问记录 was_successfully_created: 创建成功 was_successfully_updated: 更新成功 + write: 撰写 x_items_more: one: 另外一个项目 other: "%{count} 个其他项目" From 49e0a108d920a0d270cb5a1c5ca84b15230cdb4f Mon Sep 17 00:00:00 2001 From: Paul Bob Date: Wed, 15 Jan 2025 12:20:06 +0200 Subject: [PATCH 10/13] lint --- lib/avo/fields/markdown_field.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/avo/fields/markdown_field.rb b/lib/avo/fields/markdown_field.rb index 7ea3d53024..5db4d0e8d1 100644 --- a/lib/avo/fields/markdown_field.rb +++ b/lib/avo/fields/markdown_field.rb @@ -11,7 +11,8 @@ def initialize(id, **args, &block) end def self.parser - ::Redcarpet::Markdown.new(::Redcarpet::Render::HTML, + ::Redcarpet::Markdown.new( + ::Redcarpet::Render::HTML, tables: true, lax_spacing: true, fenced_code_blocks: true, From da66d900473d6d15b6492f2c04ed3cf46e93d786 Mon Sep 17 00:00:00 2001 From: Paul Bob Date: Wed, 15 Jan 2025 14:58:02 +0200 Subject: [PATCH 11/13] complexity --- lib/avo/fields/easy_mde_field.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/avo/fields/easy_mde_field.rb b/lib/avo/fields/easy_mde_field.rb index 2dc572fa79..5d1f87e98b 100644 --- a/lib/avo/fields/easy_mde_field.rb +++ b/lib/avo/fields/easy_mde_field.rb @@ -8,13 +8,10 @@ def initialize(id, **args, &block) hide_on :index - @always_show = args[:always_show].present? ? args[:always_show] : false - @height = args[:height].present? ? args[:height].to_s : "auto" - @spell_checker = args[:spell_checker].present? ? args[:spell_checker] : false @options = { - spell_checker: @spell_checker, - always_show: @always_show, - height: @height + spell_checker:args[:spell_checker] || false, + always_show: args[:always_show] || false, + height: args[:height]&.to_s || "auto" } end end From 3cecb6fc913f59940f86fde80da0e16abf5ed7e4 Mon Sep 17 00:00:00 2001 From: Paul Bob Date: Wed, 15 Jan 2025 15:50:04 +0200 Subject: [PATCH 12/13] lint --- lib/avo/fields/easy_mde_field.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/avo/fields/easy_mde_field.rb b/lib/avo/fields/easy_mde_field.rb index 5d1f87e98b..3a6b927748 100644 --- a/lib/avo/fields/easy_mde_field.rb +++ b/lib/avo/fields/easy_mde_field.rb @@ -9,7 +9,7 @@ def initialize(id, **args, &block) hide_on :index @options = { - spell_checker:args[:spell_checker] || false, + spell_checker: args[:spell_checker] || false, always_show: args[:always_show] || false, height: args[:height]&.to_s || "auto" } From ffb046a5bc8e0ee227d0b67ddc4daf62acdabef7 Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Thu, 16 Jan 2025 16:09:10 +0200 Subject: [PATCH 13/13] wip --- .../markdown_field/rendered_content_component.html.erb | 3 +++ .../avo/fields/markdown_field/rendered_content_component.rb | 5 +++++ .../avo/fields/markdown_field/show_component.html.erb | 2 +- app/views/avo/markdown_previews/create.turbo_stream.erb | 4 ++-- lib/avo/fields/markdown_field.rb | 3 ++- 5 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 app/components/avo/fields/markdown_field/rendered_content_component.html.erb create mode 100644 app/components/avo/fields/markdown_field/rendered_content_component.rb diff --git a/app/components/avo/fields/markdown_field/rendered_content_component.html.erb b/app/components/avo/fields/markdown_field/rendered_content_component.html.erb new file mode 100644 index 0000000000..f0cdb4a1d7 --- /dev/null +++ b/app/components/avo/fields/markdown_field/rendered_content_component.html.erb @@ -0,0 +1,3 @@ +<%= content_tag :div, class: "prose prose-zinc Xmarkdown-content" do %> + <%= sanitize(@body, tags: %w(table th tr td span) + ActionView::Helpers::SanitizeHelper.sanitizer_vendor.safe_list_sanitizer.allowed_tags.to_a) %> +<% end %> diff --git a/app/components/avo/fields/markdown_field/rendered_content_component.rb b/app/components/avo/fields/markdown_field/rendered_content_component.rb new file mode 100644 index 0000000000..631bd961f1 --- /dev/null +++ b/app/components/avo/fields/markdown_field/rendered_content_component.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class Avo::Fields::MarkdownField::RenderedContentComponent < Avo::BaseComponent + prop :body +end diff --git a/app/components/avo/fields/markdown_field/show_component.html.erb b/app/components/avo/fields/markdown_field/show_component.html.erb index 57c2819fa9..528a406978 100644 --- a/app/components/avo/fields/markdown_field/show_component.html.erb +++ b/app/components/avo/fields/markdown_field/show_component.html.erb @@ -1,3 +1,3 @@ <%= field_wrapper **field_wrapper_args, full_width: true do %> - <%= content_tag :div, sanitize(parsed_body), class: "markdown-content" %> + <%= render Avo::Fields::MarkdownField::RenderedContentComponent.new(body: parsed_body) %> <% end %> diff --git a/app/views/avo/markdown_previews/create.turbo_stream.erb b/app/views/avo/markdown_previews/create.turbo_stream.erb index 7caedf058a..92af476e8c 100644 --- a/app/views/avo/markdown_previews/create.turbo_stream.erb +++ b/app/views/avo/markdown_previews/create.turbo_stream.erb @@ -1,5 +1,5 @@ <%= turbo_stream.update params[:element_id] do %> -
- <%= sanitize(@result) %> +
+ <%= render Avo::Fields::MarkdownField::RenderedContentComponent.new(body: @result) %>
<% end %> diff --git a/lib/avo/fields/markdown_field.rb b/lib/avo/fields/markdown_field.rb index 7ea3d53024..2d672c943d 100644 --- a/lib/avo/fields/markdown_field.rb +++ b/lib/avo/fields/markdown_field.rb @@ -11,7 +11,8 @@ def initialize(id, **args, &block) end def self.parser - ::Redcarpet::Markdown.new(::Redcarpet::Render::HTML, + renderer = ::Redcarpet::Render::HTML.new(hard_wrap: true) + ::Redcarpet::Markdown.new(renderer, tables: true, lax_spacing: true, fenced_code_blocks: true,