diff --git a/app/javascript/application.js b/app/javascript/application.js index af363801..dda88f7a 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -37,6 +37,7 @@ import AppTour from './elements/app_tour' import DashboardDropzone from './elements/dashboard_dropzone' import RequiredCheckboxGroup from './elements/required_checkbox_group' import PageContainer from './elements/page_container' +import EmailEditor from './elements/email_editor' import * as TurboInstantClick from './lib/turbo_instant_click' @@ -109,6 +110,7 @@ safeRegisterElement('dashboard-dropzone', DashboardDropzone) safeRegisterElement('check-on-click', CheckOnClick) safeRegisterElement('required-checkbox-group', RequiredCheckboxGroup) safeRegisterElement('page-container', PageContainer) +safeRegisterElement('email-editor', EmailEditor) safeRegisterElement('template-builder', class extends HTMLElement { connectedCallback () { diff --git a/app/javascript/elements/email_editor.js b/app/javascript/elements/email_editor.js new file mode 100644 index 00000000..38f0d3b4 --- /dev/null +++ b/app/javascript/elements/email_editor.js @@ -0,0 +1,131 @@ +import { target, targetable } from '@github/catalyst/lib/targetable' + +let loaderPromise = null + +function loadCodeMirror () { + if (!loaderPromise) { + loaderPromise = Promise.all([ + import(/* webpackChunkName: "email-editor" */ '@codemirror/view'), + import(/* webpackChunkName: "email-editor" */ '@codemirror/commands'), + import(/* webpackChunkName: "email-editor" */ '@codemirror/language'), + import(/* webpackChunkName: "email-editor" */ '@codemirror/lang-html'), + import(/* webpackChunkName: "email-editor" */ '@specious/htmlflow') + ]).then(([view, commands, language, html, htmlflow]) => { + return { + minimalSetup: [ + commands.history(), + language.syntaxHighlighting(language.defaultHighlightStyle, { fallback: true }), + view.keymap.of([...commands.defaultKeymap, ...commands.historyKeymap]) + ], + EditorView: view.EditorView, + html: html.html, + htmlflow: htmlflow.default || htmlflow + } + }) + } + + return loaderPromise +} + +export default targetable(class extends HTMLElement { + static [target.static] = [ + 'codeViewTab', + 'previewViewTab', + 'editorContainer', + 'previewIframe' + ] + + connectedCallback () { + this.mount() + + if (this.input.value) { + this.showPreviewView() + } else { + this.showCodeView() + } + + this.previewViewTab.addEventListener('click', this.showPreviewView) + this.codeViewTab.addEventListener('click', this.showCodeView) + } + + showCodeView = () => { + this.editorView.dispatch({ + changes: { from: 0, to: this.editorView.state.doc.length, insert: this.input.value } + }) + + this.previewViewTab.classList.remove('tab-active', 'tab-bordered') + this.previewViewTab.classList.add('pb-[3px]') + this.codeViewTab.classList.remove('pb-[3px]') + this.codeViewTab.classList.add('tab-active', 'tab-bordered') + this.editorContainer.classList.remove('hidden') + this.previewIframe.classList.add('hidden') + } + + showPreviewView = () => { + this.previewIframe.srcdoc = this.input.value + + this.codeViewTab.classList.remove('tab-active', 'tab-bordered') + this.codeViewTab.classList.add('pb-[3px]') + this.previewViewTab.classList.remove('pb-[3px]') + this.previewViewTab.classList.add('tab-active', 'tab-bordered') + this.editorContainer.classList.add('hidden') + this.previewIframe.classList.remove('hidden') + } + + async mount () { + this.input = this.querySelector('input[type="hidden"]') + this.input.style.display = 'none' + + const { EditorView, minimalSetup, html, htmlflow } = await loadCodeMirror() + + this.editorView = new EditorView({ + doc: this.input.value, + parent: this.editorContainer, + extensions: [ + html(), + minimalSetup, + EditorView.lineWrapping, + EditorView.updateListener.of(update => { + if (update.docChanged) this.input.value = update.state.doc.toString() + }), + EditorView.theme({ + '&': { + backgroundColor: 'white', + color: 'black', + fontSize: '14px', + fontFamily: 'monospace' + }, + '&.cm-focused': { + outline: 'none' + }, + '&.cm-editor': { + borderRadius: '0.375rem', + border: 'none' + }, + '.cm-gutters': { + display: 'none' + } + }) + ] + }) + + this.previewIframe.srcdoc = this.editorView.state.doc.toString() + + this.previewIframe.onload = () => { + const previewIframeDoc = this.previewIframe.contentDocument + + if (previewIframeDoc.body) { + previewIframeDoc.body.contentEditable = true + } + + const contentDocument = this.previewIframe.contentDocument || this.previewIframe.contentWindow.document + + contentDocument.body.addEventListener('input', async () => { + const html = contentDocument.documentElement.outerHTML.replace(' contenteditable="true"', '') + const prettifiedHtml = await htmlflow(html) + + this.input.value = prettifiedHtml + }) + } + } +}) diff --git a/app/mailers/submitter_mailer.rb b/app/mailers/submitter_mailer.rb index c4627969..145d3756 100644 --- a/app/mailers/submitter_mailer.rb +++ b/app/mailers/submitter_mailer.rb @@ -30,6 +30,7 @@ class SubmitterMailer < ApplicationMailer @submitter.template&.preferences&.dig('request_email_subject').presence @email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY) + @body ||= fetch_config_email_body(@email_config, @submitter) assign_message_metadata('submitter_invitation', @submitter) @@ -71,7 +72,7 @@ class SubmitterMailer < ApplicationMailer @subject ||= @email_config.value['subject'] if @email_config @body = template_preferences['completed_notification_email_body'].presence - @body ||= @email_config.value['body'] if @email_config + @body ||= fetch_config_email_body(@email_config, @submitter) assign_message_metadata('submitter_completed', @submitter) @@ -127,7 +128,7 @@ class SubmitterMailer < ApplicationMailer @subject ||= @email_config.value['subject'] if @email_config @body = template_preferences['documents_copy_email_body'].presence - @body ||= @email_config.value['body'] if @email_config + @body ||= fetch_config_email_body(@email_config, @submitter) assign_message_metadata('submitter_documents_copy', @submitter) reply_to = build_submitter_reply_to(submitter, email_config: @email_config, documents_copy_email: true) @@ -246,4 +247,8 @@ class SubmitterMailer < ApplicationMailer user.friendly_name end end + + def fetch_config_email_body(email_config, _submitter = nil) + email_config ? email_config.value['body'].presence : nil + end end diff --git a/app/views/personalization_settings/_documents_copy_email_form.html.erb b/app/views/personalization_settings/_documents_copy_email_form.html.erb index c5af6c49..e4f777d4 100644 --- a/app/views/personalization_settings/_documents_copy_email_form.html.erb +++ b/app/views/personalization_settings/_documents_copy_email_form.html.erb @@ -13,17 +13,7 @@ <%= ff.label :subject, t('subject'), class: 'label' %> <%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %> -
-
- <%= ff.label :body, t('body'), class: 'label' %> - - <%= svg_icon('info_circle', class: 'w-4 h-4') %> - -
- - <%= ff.text_area :body, required: true, class: 'base-input w-full py-2', dir: 'auto' %> - -
+ <%= render 'personalization_settings/email_body_field', ff:, config: f.object %> <% if can?(:manage, :reply_to) || can?(:manage, :personalization_advanced) %>
<%= ff.label :reply_to, t('reply_to'), class: 'label' %> diff --git a/app/views/personalization_settings/_email_body_field.html.erb b/app/views/personalization_settings/_email_body_field.html.erb new file mode 100644 index 00000000..264a4240 --- /dev/null +++ b/app/views/personalization_settings/_email_body_field.html.erb @@ -0,0 +1,11 @@ +
+
+ <%= ff.label :body, t('body'), class: 'label' %> + + <%= svg_icon('info_circle', class: 'w-4 h-4') %> + +
+ + <%= ff.text_area :body, required: true, class: 'base-input w-full !rounded-2xl py-2', dir: 'auto' %> + +
diff --git a/app/views/personalization_settings/_signature_request_email_form.html.erb b/app/views/personalization_settings/_signature_request_email_form.html.erb index ea529dfe..1b4588ea 100644 --- a/app/views/personalization_settings/_signature_request_email_form.html.erb +++ b/app/views/personalization_settings/_signature_request_email_form.html.erb @@ -13,17 +13,7 @@ <%= ff.label :subject, t('subject'), class: 'label' %> <%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
-
-
- <%= ff.label :body, t('body'), class: 'label' %> - - <%= svg_icon('info_circle', class: 'w-4 h-4') %> - -
- - <%= ff.text_area :body, required: true, class: 'base-input w-full py-2', dir: 'auto' %> - -
+ <%= render 'personalization_settings/email_body_field', ff:, config: f.object %> <% end %>
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %> diff --git a/app/views/personalization_settings/_submitter_completed_email_form.html.erb b/app/views/personalization_settings/_submitter_completed_email_form.html.erb index 28c562dd..11803829 100644 --- a/app/views/personalization_settings/_submitter_completed_email_form.html.erb +++ b/app/views/personalization_settings/_submitter_completed_email_form.html.erb @@ -18,17 +18,7 @@
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %> -
-
- <%= ff.label :body, t('body'), class: 'label' %> - - <%= svg_icon('info_circle', class: 'w-4 h-4') %> - -
- - <%= ff.text_area :body, required: true, class: 'base-input w-full py-2', dir: 'auto' %> - -
+ <%= render 'personalization_settings/email_body_field', ff:, config: f.object %>
<%= t('attach_documents') %> diff --git a/app/views/submitter_mailer/invitation_email.html.erb b/app/views/submitter_mailer/invitation_email.html.erb index 06eaef30..06e38f30 100644 --- a/app/views/submitter_mailer/invitation_email.html.erb +++ b/app/views/submitter_mailer/invitation_email.html.erb @@ -1,14 +1,13 @@ -<% if @email_config || @body.present? %> - <% body = (@body.presence || @email_config.value['body']).to_s %> - <%= render 'custom_content', content: body, submitter: @submitter %> - <% if !body.match?(ReplaceEmailVariables::SUBMITTER_LINK) && !body.match?(ReplaceEmailVariables::SUBMITTER_ID) && !body.match?(ReplaceEmailVariables::SUBMISSION_LINK) && !body.match?(ReplaceEmailVariables::TEMPLATE_ID) && !@submitter.submission.source.in?(%w[api embed]) %> +<% if @body.present? %> + <%= render 'custom_content', content: @body, submitter: @submitter %> + <% if !@body.match?(ReplaceEmailVariables::SUBMITTER_LINK) && !@body.match?(ReplaceEmailVariables::SUBMITTER_ID) && !@body.match?(ReplaceEmailVariables::SUBMISSION_LINK) && !@body.match?(ReplaceEmailVariables::TEMPLATE_ID) && !@submitter.submission.source.in?(%w[api embed]) %>

<%= link_to nil, submit_form_url(slug: @submitter.slug, t: SubmissionEvents.build_tracking_param(@submitter, 'click_email')) %>

<% end %> <% else %>

<%= t('hi_there') %>,

<%= I18n.t(@submitter.with_signature_fields? ? :you_have_been_invited_to_sign_the_name : :you_have_been_invited_to_submit_the_name_form, name: @submitter.submission.name || @submitter.submission.template.name) %>

<%= link_to I18n.t(@submitter.with_signature_fields? ? :review_and_sign : :review_and_submit), submit_form_url(slug: @submitter.slug, t: SubmissionEvents.build_tracking_param(@submitter, 'click_email'), host: ENV.fetch('EMAIL_HOST', Docuseal.default_url_options[:host])) %>

-

<%= t('please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this') %>

+

<%= t('please_contact_us_by_replying_to_this_email_if_you_have_any_questions') %>

<%= t('thanks') %>,
<%= @current_account.name %>

diff --git a/app/views/user_mailer/invitation_email.html.erb b/app/views/user_mailer/invitation_email.html.erb index 23c78b21..1444419f 100644 --- a/app/views/user_mailer/invitation_email.html.erb +++ b/app/views/user_mailer/invitation_email.html.erb @@ -1,7 +1,7 @@

<%= @user.first_name.present? ? t('hello_name', name: @user.first_name) : t('hi_there') %>,

<%= t('you_have_been_invited_to_account_name_product_name_please_sign_up_using_the_link_below_', account_name: @user.account.name, product_name: Docuseal.product_name) %>

<%= link_to t('sign_up'), invitation_url(reset_password_token: @token) %>

-

<%= t('please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this') %>

+

<%= t('please_contact_us_by_replying_to_this_email_if_you_have_any_questions') %>

<%= t('thanks') %>,
<%= @current_account.name %>

diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index 0bd59e7f..29236bc4 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -73,7 +73,7 @@ en: &en awaiting_completion_by_the_other_party: "Awaiting completion by the other party" review_and_sign: Review and Sign review_and_submit: Review and Submit - please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: "Please contact us by replying to this email if you have any questions." + please_contact_us_by_replying_to_this_email_if_you_have_any_questions: "Please contact us by replying to this email if you have any questions." submitter_invitation_sms_body_sign: '{account.name} has invited you to sign a document: {submitter.link}' verification_code_sms_body: 'Verification code: {code}' you_are_invited_to_submit_a_form: 'You are invited to submit a form' @@ -783,6 +783,18 @@ en: &en email_verification: Email verification your_verification_code_to_access_the_name: 'Your verification code to access the "%{name}":' please_reply_to_this_email_if_you_didnt_request_this: Please reply to this email if you didn't request this. + text: Text + code: Code + custom_html_emails: Custom HTML emails + connect_your_email_to_send_html_emails: Connect your email to send HTML emails + connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Connect your Gmail or Oulook account or add SMTP settings to send custom HTML emails. + connect_gmail_or_outlook: Connect Gmail or Outlook + connect_your_email_to_bulk_send: Connect your email to bulk send + connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Connect your Gmail or Oulook account or add SMTP settings to bulk send. + are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Are you sure you want to add recipients without sending? To send emails it requires to connect Gmail or Outlook. + template_name_has_been_completed_by_submitters_html: '"{template.name}" has been completed by {submission.submitters}' + please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Please check the copy of your "{template.name}" in the email attachments.' + you_have_been_invited_to_sign_the_template_name_html: 'You have been invited to sign the "{template.name}".' submission_sources: api: API bulk: Bulk Send @@ -944,7 +956,7 @@ es: &es please_check_the_copy_of_your_name_in_the_email_attachments: 'Por favor, revisa la copia de tu "%{name}" en los archivos adjuntos del correo electrónico.' review_and_sign: Revisar y Firmar review_and_submit: Revisar y Enviar - please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: "Por favor, contáctanos respondiendo a este correo si tienes alguna pregunta." + please_contact_us_by_replying_to_this_email_if_you_have_any_questions: "Por favor, contáctanos respondiendo a este correo si tienes alguna pregunta." submitter_invitation_sms_body_sign: '{account.name} te ha invitado a firmar un documento: {submitter.link}' verification_code_sms_body: 'Código de verificación: {code}' you_are_invited_to_submit_a_form: 'Estás invitado/a a enviar un formulario' @@ -973,7 +985,7 @@ es: &es submitter_documents_copy_email_body: | Hola, - Por favor, revisa la copia de tu "{template.name}" en los archivos adjuntos. + Por favor, revisa la copia de tu "{template.name}" en los archivos adjuntos del correo electrónico. Alternativamente, puedes revisar y descargar tu copia usando el enlace a continuación: [{template.name}]({documents.link}) @@ -1653,6 +1665,18 @@ es: &es email_verification: Verificación por correo electrónico your_verification_code_to_access_the_name: 'Su código de verificación para acceder a "%{name}":' please_reply_to_this_email_if_you_didnt_request_this: Por favor, responda este correo si no solicitó esto. + text: Texto + code: Código + custom_html_emails: Correos electrónicos HTML personalizados + connect_your_email_to_send_html_emails: Conecta tu correo electrónico para enviar correos HTML + connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Conecta tu cuenta de Gmail u Outlook o añade ajustes SMTP para enviar correos HTML personalizados. + connect_gmail_or_outlook: Conectar Gmail u Outlook + connect_your_email_to_bulk_send: Conecta tu correo electrónico para el envío masivo + connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Conecta tu cuenta de Gmail u Outlook o añade ajustes SMTP para el envío masivo. + are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: ¿Estás seguro de que quieres añadir destinatarios sin enviar? Para enviar correos electrónicos necesitas conectar Gmail u Outlook. + template_name_has_been_completed_by_submitters_html: '"{template.name}" ha sido completado por {submission.submitters}' + please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, revisa la copia de tu "{template.name}" en los archivos adjuntos del correo electrónico.' + you_have_been_invited_to_sign_the_template_name_html: 'Has sido invitado a firmar el "{template.name}".' submission_sources: api: API bulk: Envío masivo @@ -1813,7 +1837,7 @@ it: &it please_check_the_copy_of_your_name_in_the_email_attachments: "Per favore, controlla la copia del tuo \"%{name}\" negli allegati dell'email." review_and_sign: Rivedi e Firma review_and_submit: Rivedi e Invia - please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: "Per favore, contattaci rispondendo a questa email se hai domande." + please_contact_us_by_replying_to_this_email_if_you_have_any_questions: "Per favore, contattaci rispondendo a questa email se hai domande." submitter_invitation_sms_body_sign: '{account.name} ti ha invitato a firmare un documento: {submitter.link}' verification_code_sms_body: 'Codice di verifica: {code}' you_are_invited_to_submit_a_form: 'Sei stato invitato a inviare un modulo' @@ -2522,6 +2546,18 @@ it: &it email_verification: Verifica email your_verification_code_to_access_the_name: 'Il tuo codice per accedere a "%{name}":' please_reply_to_this_email_if_you_didnt_request_this: Rispondi a questa email se non hai richiesto questo. + text: Testo + code: Codice + custom_html_emails: Email HTML personalizzate + connect_your_email_to_send_html_emails: Collega la tua email per inviare email HTML + connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Collega il tuo account Gmail o Outlook oppure aggiungi impostazioni SMTP per inviare email HTML personalizzate. + connect_gmail_or_outlook: Collega Gmail o Outlook + connect_your_email_to_bulk_send: Collega la tua email per invio multiplo + connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Collega il tuo account Gmail o Outlook oppure aggiungi impostazioni SMTP per invio multiplo. + are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Sei sicuro di voler aggiungere destinatari senza inviare? Per inviare email devi collegare Gmail o Outlook. + template_name_has_been_completed_by_submitters_html: '"{template.name}" è stato completato da {submission.submitters}' + please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Per favore, controlla la copia del tuo "{template.name}" negli allegati dell''email.' + you_have_been_invited_to_sign_the_template_name_html: 'Sei stato invitato a firmare il "{template.name}".' submission_sources: api: API bulk: Invio massivo @@ -2683,7 +2719,7 @@ fr: &fr please_check_the_copy_of_your_name_in_the_email_attachments: "Veuillez vérifier la copie de votre \"%{name}\" dans les pièces jointes de l'email." review_and_sign: Consulter et signer review_and_submit: Consulter et soumettre - please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: 'Veuillez nous contacter en répondant à cet e-mail si vous avez des questions.' + please_contact_us_by_replying_to_this_email_if_you_have_any_questions: 'Veuillez nous contacter en répondant à cet e-mail si vous avez des questions.' submitter_invitation_sms_body_sign: '{account.name} vous a invité à signer un document: {submitter.link}' verification_code_sms_body: 'Code de vérification: {code}' you_are_invited_to_submit_a_form: Vous êtes invité à soumettre un formulaire @@ -2699,7 +2735,7 @@ fr: &fr [Consulter et signer]({submitter.link}) - Veuillez nous contacter si vous avez des questions. + Veuillez nous contacter en répondant à cet e-mail si vous avez des questions. Merci, {account.name} @@ -2712,7 +2748,7 @@ fr: &fr submitter_documents_copy_email_body: | Bonjour, - Veuillez vérifier la copie de votre "{template.name}" dans les pièces jointes. + Veuillez vérifier la copie de votre "{template.name}" dans les pièces jointes de l'email. Vous pouvez également consulter et télécharger votre copie en utilisant le lien ci-dessous: [{template.name}]({documents.link}) @@ -3394,6 +3430,18 @@ fr: &fr email_verification: Vérification de l'email your_verification_code_to_access_the_name: 'Votre code pour accéder à "%{name}" :' please_reply_to_this_email_if_you_didnt_request_this: Veuillez répondre à cet email si vous n'avez pas fait cette demande. + text: Texte + code: Code + custom_html_emails: E-mails HTML personnalisés + connect_your_email_to_send_html_emails: Connectez votre e-mail pour envoyer des e-mails HTML + connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Connectez votre compte Gmail ou Outlook ou ajoutez des paramètres SMTP pour envoyer des e-mails HTML personnalisés. + connect_gmail_or_outlook: Connecter Gmail ou Outlook + connect_your_email_to_bulk_send: Connectez votre e-mail pour l'envoi groupé + connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Connectez votre compte Gmail ou Outlook ou ajoutez des paramètres SMTP pour l'envoi groupé. + are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Êtes-vous sûr de vouloir ajouter des destinataires sans envoi ? Pour envoyer des e-mails, vous devez connecter Gmail ou Outlook. + template_name_has_been_completed_by_submitters_html: '"{template.name}" a été complété par {submission.submitters}' + please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Veuillez vérifier la copie de votre "{template.name}" dans les pièces jointes de l’e-mail.' + you_have_been_invited_to_sign_the_template_name_html: 'Vous avez été invité à signer le "{template.name}".' submission_sources: api: API bulk: Envoi en masse @@ -3555,7 +3603,7 @@ pt: &pt please_check_the_copy_of_your_name_in_the_email_attachments: 'Por favor, verifique a cópia de "%{name}" nos anexos do e-mail.' review_and_sign: Revisar e assinar review_and_submit: Revisar e submeter - please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: 'Por favor, entre em contato conosco respondendo a este e-mail se você tiver alguma dúvida.' + please_contact_us_by_replying_to_this_email_if_you_have_any_questions: 'Por favor, entre em contato conosco respondendo a este e-mail se você tiver alguma dúvida.' submitter_invitation_sms_body_sign: '{account.name} convidou você para assinar um documento: {submitter.link}' verification_code_sms_body: 'Código de verificação: {code}' you_are_invited_to_submit_a_form: Você foi convidado a submeter um formulário @@ -3567,11 +3615,11 @@ pt: &pt submitter_invitation_email_sign_body: | Olá, - Você foi convidado a assinar o documento "{template.name}". + Você foi convidado a assinar "{template.name}". [Revisar e assinar]({submitter.link}) - Por favor, entre em contato conosco se tiver alguma dúvida. + Por favor, entre em contato conosco respondendo a este e-mail se você tiver alguma dúvida. Obrigado, {account.name} @@ -3584,8 +3632,8 @@ pt: &pt submitter_documents_copy_email_body: | Olá, - Por favor, verifique a cópia de seu "{template.name}" nos anexos do e-mail. - Alternativamente, você pode revisar e baixar sua cópia usando o link abaixo: + Por favor, verifique a cópia de "{template.name}" nos anexos do e-mail. + Você pode revisar e baixar sua cópia usando o link abaixo: [{template.name}]({documents.link}) @@ -4264,6 +4312,18 @@ pt: &pt email_verification: Verificação de e-mail your_verification_code_to_access_the_name: 'Seu código de verificação para acessar "%{name}":' please_reply_to_this_email_if_you_didnt_request_this: Responda a este e-mail se você não solicitou isso. + text: Texto + code: Código + custom_html_emails: E-mails HTML personalizados + connect_your_email_to_send_html_emails: Conecte seu e-mail para enviar e-mails HTML + connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Conecte sua conta Gmail ou Outlook ou adicione configurações SMTP para enviar e-mails HTML personalizados. + connect_gmail_or_outlook: Conectar Gmail ou Outlook + connect_your_email_to_bulk_send: Conecte seu e-mail para envio em massa + connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Conecte sua conta Gmail ou Outlook ou adicione configurações SMTP para envio em massa. + are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Tem certeza de que deseja adicionar destinatários sem enviar? Para enviar e-mails é necessário conectar Gmail ou Outlook. + template_name_has_been_completed_by_submitters_html: '"{template.name}" foi concluído por {submission.submitters}' + please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, verifique a cópia do seu "{template.name}" nos anexos do e-mail.' + you_have_been_invited_to_sign_the_template_name_html: 'Você foi convidado a assinar o "{template.name}".' submission_sources: api: API bulk: Envio em massa @@ -4426,7 +4486,7 @@ de: &de please_check_the_copy_of_your_name_in_the_email_attachments: 'Bitte überprüfe die Kopie von "%{name}" im E-Mail-Anhang.' review_and_sign: Überprüfen und unterschreiben review_and_submit: Überprüfen und einreichen - please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: 'Bitte kontaktiere uns, indem du auf diese E-Mail antwortest, falls du Fragen hast.' + please_contact_us_by_replying_to_this_email_if_you_have_any_questions: 'Bitte kontaktieren Sie uns, indem Sie auf diese E-Mail antworten, falls Sie Fragen haben.' submitter_invitation_sms_body_sign: '{account.name} hat dich eingeladen, ein Dokument zu unterschreiben: {submitter.link}' verification_code_sms_body: 'Verifizierungscode: {code}' you_are_invited_to_submit_a_form: Du wurdest eingeladen, ein Formular einzureichen @@ -4438,11 +4498,11 @@ de: &de submitter_invitation_email_sign_body: | Hallo, - Du wurdest eingeladen, das Dokument "{template.name}" zu unterschreiben. + Du wurdest eingeladen, "{template.name}" zu unterschreiben. [Überprüfen und unterschreiben]({submitter.link}) - Bitte kontaktiere uns, falls du Fragen hast. + Bitte kontaktieren Sie uns, indem Sie auf diese E-Mail antworten, falls Sie Fragen haben. Danke, {account.name} @@ -4455,8 +4515,8 @@ de: &de submitter_documents_copy_email_body: | Hallo, - Bitte überprüfe die Kopie deines "{template.name}" im E-Mail-Anhang. - Alternativ kannst du deine Kopie mit dem untenstehenden Link überprüfen und herunterladen: + Bitte überprüfe die Kopie von "{template.name}" im E-Mail-Anhang. + Du kannst alternativ deine Kopie mit dem untenstehenden Link überprüfen und herunterladen: [{template.name}]({documents.link}) @@ -5135,6 +5195,18 @@ de: &de email_verification: E-Mail-Verifizierung your_verification_code_to_access_the_name: 'Ihr Verifizierungscode für den Zugriff auf "%{name}":' please_reply_to_this_email_if_you_didnt_request_this: Antworten Sie auf diese E-Mail, wenn Sie dies nicht angefordert haben. + text: Text + code: Code + custom_html_emails: Benutzerdefinierte HTML-E-Mails + connect_your_email_to_send_html_emails: Verbinden Sie Ihr E-Mail-Konto, um HTML-E-Mails zu senden + connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Verbinden Sie Ihr Gmail- oder Outlook-Konto oder fügen Sie SMTP-Einstellungen hinzu, um benutzerdefinierte HTML-E-Mails zu senden. + connect_gmail_or_outlook: Gmail oder Outlook verbinden + connect_your_email_to_bulk_send: Verbinden Sie Ihr E-Mail-Konto für Massenversand + connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Verbinden Sie Ihr Gmail- oder Outlook-Konto oder fügen Sie SMTP-Einstellungen für den Massenversand hinzu. + are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Möchten Sie wirklich Empfänger hinzufügen, ohne zu senden? Zum Senden von E-Mails ist eine Verbindung zu Gmail oder Outlook erforderlich. + template_name_has_been_completed_by_submitters_html: '"{template.name}" wurde von {submission.submitters} abgeschlossen' + please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Bitte prüfen Sie die Kopie Ihres "{template.name}" in den E-Mail-Anhängen.' + you_have_been_invited_to_sign_the_template_name_html: 'Du wurdest eingeladen, "{template.name}" zu unterschreiben.' submission_sources: api: API bulk: Massenversand diff --git a/package.json b/package.json index 37978020..547418cb 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,12 @@ "@babel/plugin-transform-runtime": "7.21.4", "@babel/preset-env": "7.21.5", "@babel/runtime": "7.21.5", + "@codemirror/lang-html": "^6.4.9", "@eid-easy/eideasy-widget": "^2.163.4", "@github/catalyst": "^2.0.0-beta", "@hotwired/turbo": "https://github.com/docusealco/turbo#main", "@hotwired/turbo-rails": "^7.3.0", + "@specious/htmlflow": "^1.1.0", "@tabler/icons-vue": "^2.47.0", "autocompleter": "^9.1.0", "autoprefixer": "^10.4.14", @@ -17,6 +19,7 @@ "babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-macros": "^3.1.0", "canvas-confetti": "^1.6.0", + "codemirror": "^6.0.2", "compression-webpack-plugin": "10.0.0", "css-loader": "^6.7.3", "css-minimizer-webpack-plugin": "^5.0.0", diff --git a/yarn.lock b/yarn.lock index 6ba5e8e3..85a72f80 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1030,6 +1030,112 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@codemirror/autocomplete@^6.0.0": + version "6.18.6" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz#de26e864a1ec8192a1b241eb86addbb612964ddb" + integrity sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + +"@codemirror/commands@^6.0.0": + version "6.8.1" + resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.8.1.tgz#639f5559d2f33f2582a2429c58cb0c1b925c7a30" + integrity sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.4.0" + "@codemirror/view" "^6.27.0" + "@lezer/common" "^1.1.0" + +"@codemirror/lang-css@^6.0.0": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-6.3.1.tgz#763ca41aee81bb2431be55e3cfcc7cc8e91421a3" + integrity sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@lezer/common" "^1.0.2" + "@lezer/css" "^1.1.7" + +"@codemirror/lang-html@^6.4.9": + version "6.4.9" + resolved "https://registry.yarnpkg.com/@codemirror/lang-html/-/lang-html-6.4.9.tgz#d586f2cc9c341391ae07d1d7c545990dfa069727" + integrity sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/lang-css" "^6.0.0" + "@codemirror/lang-javascript" "^6.0.0" + "@codemirror/language" "^6.4.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + "@lezer/css" "^1.1.0" + "@lezer/html" "^1.3.0" + +"@codemirror/lang-javascript@^6.0.0": + version "6.2.4" + resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz#eef2227d1892aae762f3a0f212f72bec868a02c5" + integrity sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/language" "^6.6.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + "@lezer/javascript" "^1.0.0" + +"@codemirror/language@^6.0.0", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0": + version "6.11.2" + resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.2.tgz#90d2d094cfbd14263bc5354ebd2445ee4e81bdc3" + integrity sha512-p44TsNArL4IVXDTbapUmEkAlvWs2CFQbcfc0ymDsis1kH2wh0gcY96AS29c/vp2d0y2Tquk1EDSaawpzilUiAw== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.23.0" + "@lezer/common" "^1.1.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + style-mod "^4.0.0" + +"@codemirror/lint@^6.0.0": + version "6.8.5" + resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.8.5.tgz#9edaa808e764e28e07665b015951934c8ec3a418" + integrity sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.35.0" + crelt "^1.0.5" + +"@codemirror/search@^6.0.0": + version "6.5.11" + resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.11.tgz#a324ffee36e032b7f67aa31c4fb9f3e6f9f3ed63" + integrity sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + crelt "^1.0.5" + +"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" + integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== + dependencies: + "@marijn/find-cluster-break" "^1.0.0" + +"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0": + version "6.38.0" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.38.0.tgz#4486062b791a4247793e0953e05ae71a9e172217" + integrity sha512-yvSchUwHOdupXkd7xJ0ob36jdsSR/I+/C+VbY0ffBiL5NiSTEBDfB1ZGWbbIlDd5xgdUkody+lukAdOxYrOBeg== + dependencies: + "@codemirror/state" "^6.5.0" + crelt "^1.0.6" + style-mod "^4.1.0" + w3c-keyname "^2.2.4" + "@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" @@ -1237,6 +1343,57 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== +"@lezer/common@^1.0.0", "@lezer/common@^1.0.2", "@lezer/common@^1.1.0", "@lezer/common@^1.2.0": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd" + integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA== + +"@lezer/css@^1.1.0", "@lezer/css@^1.1.7": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@lezer/css/-/css-1.3.0.tgz#296f298814782c2fad42a936f3510042cdcd2034" + integrity sha512-pBL7hup88KbI7hXnZV3PQsn43DHy6TWyzuyk2AO9UyoXcDltvIdqWKE1dLL/45JVZ+YZkHe1WVHqO6wugZZWcw== + dependencies: + "@lezer/common" "^1.2.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.3.0" + +"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.1.tgz#596fa8f9aeb58a608be0a563e960c373cbf23f8b" + integrity sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA== + dependencies: + "@lezer/common" "^1.0.0" + +"@lezer/html@^1.3.0": + version "1.3.10" + resolved "https://registry.yarnpkg.com/@lezer/html/-/html-1.3.10.tgz#1be9a029a6fe835c823b20a98a449a630416b2af" + integrity sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w== + dependencies: + "@lezer/common" "^1.2.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + +"@lezer/javascript@^1.0.0": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.5.1.tgz#2a424a6ec29f1d4ef3c34cbccc5447e373618ad8" + integrity sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw== + dependencies: + "@lezer/common" "^1.2.0" + "@lezer/highlight" "^1.1.3" + "@lezer/lr" "^1.3.0" + +"@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.2.tgz#931ea3dea8e9de84e90781001dae30dea9ff1727" + integrity sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA== + dependencies: + "@lezer/common" "^1.0.0" + +"@marijn/find-cluster-break@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" + integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -1280,6 +1437,13 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== +"@specious/htmlflow@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@specious/htmlflow/-/htmlflow-1.1.0.tgz#cc8319c2cc6b5e2e309fa213d5a1f54cc093d9eb" + integrity sha512-g41FgN5kfuGkOrWhhmVvFes2BzQ3msU5oR/8KPdXbkBt8UIHtwL+by9maItDIhu+BR7pxshABtaB/FqpESa9Mg== + dependencies: + htmlparser2 "^8.0.1" + "@tabler/icons-vue@^2.47.0": version "2.47.0" resolved "https://registry.yarnpkg.com/@tabler/icons-vue/-/icons-vue-2.47.0.tgz#604608a6df673d035c0e8e33f0565eeffa3adf36" @@ -2172,6 +2336,19 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +codemirror@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.2.tgz#4d3fea1ad60b6753f97ca835f2f48c6936a8946e" + integrity sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/commands" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/search" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2351,6 +2528,11 @@ cosmiconfig@^8.1.3: parse-json "^5.0.0" path-type "^4.0.0" +crelt@^1.0.5, crelt@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" + integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g== + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2711,7 +2893,7 @@ enhanced-resolve@^5.17.1: graceful-fs "^4.2.4" tapable "^2.2.0" -entities@^4.2.0: +entities@^4.2.0, entities@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -3511,6 +3693,16 @@ html-entities@^2.3.2: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== +htmlparser2@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -5438,6 +5630,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +style-mod@^4.0.0, style-mod@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67" + integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw== + stylehacks@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.0.tgz#9fdd7c217660dae0f62e14d51c89f6c01b3cb738" @@ -5845,6 +6042,11 @@ vue@^3.3.2: "@vue/server-renderer" "3.3.4" "@vue/shared" "3.3.4" +w3c-keyname@^2.2.4: + version "2.2.8" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" + integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== + watchpack@^2.4.0, watchpack@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da"