Как отфильтровать текстовое содержимое при операции копирования/вставки в редактируемом компоненте (vue)

Я реализовал компонент, который использует contenteditable="true", чтобы получить возможность редактирования содержимого в этом div (например, текстовое поле).

Следуйте фрагменту из моего кода:

export default {
  name: 'divArea',
  props: ['value'],
  mounted() {
    this.$el.innerHTML = this.value;
  },
  methods: {
    updateHTML(e) {
      const html = e.target.innerHTML;
      this.$emit('input', html);
    },
  },
}
<template>
  <div contenteditable = "true"
    v-once
    v-html = "value"
    @input = "updateHTML"
    @paste = "onPaste"
    class = "txtArea"></div>
</template>

Я пытаюсь реализовать функцию вставки в этой области, чтобы скопировать блок контента с html-страницы, но я хотел бы иметь только текстовую версию после операции вставки (без html).

В настоящее время я использую атрибут v-html с поддержкой моего компонента, потому что мне нужно добавить пользовательский тег html во вставленный текст, но только если пользователь нажимает кнопку.

Как я могу реализовать это поведение?

Возможно, вы захотите изучить уценку Vue, вот пример.

Yom T. 22.02.2019 09:27

Спасибо @jom, но в этом примере используется библиотека (marked.js)

sergioska 22.02.2019 09:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
2 721
2

Ответы 2

but I would like to have only text version after paste operation (no html).

Вы можете создать элемент DOM или использовать DOMParser(), чтобы установить value элемента <textarea> и получить .textContent элемента.

const textarea = document.querySelector("textarea");
let parser = new DOMParser();
let parsedHTML = parser.parseFromString(textarea.value, "text/html");
console.info(parsedHTML.body.textContent);
<textarea style = "width:240px;height:50px;">
  <div>a<span>b</span><b>c</b></div>
</textarea>

Во-первых contenteditable это настоящий Дьявол и я рекомендую не использовать его, но в любом случае это было мое решение

        let contenteditable = document.querySelector('[contenteditable]')
        contenteditable.addEventListener('paste', function(e){           
            // Prevent the default pasting event and stop bubbling            
            e.preventDefault()
            e.stopPropagation()
            // Get the clipboard data
            let paste = (e.clipboardData || window.clipboardData).getData('text/plain')

            // Do something with paste like remove non-UTF-8 characters            
            paste = paste.replace(/\x0D/gi, "\n")          
            e.target.textContent += paste
        })

вторая часть, если вы хотите добавить пасту, где был cursor

  instead of 
            e.target.textContent += paste

вы можете использовать Selection()

       // Find the cursor location or highlighted area
        const selection = window.getSelection()
        // Cancel the paste operation if the cursor or highlighted area isn't found
        // if (!selection.rangeCount) return false
        // Paste the modified clipboard content where it was intended to go            
        if (selection.getRangeAt(0).collapsed){
            // TextareaManager.AddToCursor(document.createTextNode(paste))
            if (selection.getRangeAt(0).endContainer.nodeName != "DIV"){
                selection.getRangeAt(0).insertNode(document.createTextNode(paste))
            }else {
                e.target.childNodes[0].textContent += paste
            }
            selection.getRangeAt(0).collapse(false)
        }else {
           e.target.appendChild(document.createTextNode(paste))
        }

Спасибо @mooga, кажется, это отличная отправная точка для моей проблемы. Мне не нравится, что текстовый контент потерял возврат каретки, но я могу над этим поработать. Что вы можете предложить мне использовать в безопасности contenteditable? санировать, что полосатых html-тегов недостаточно?

sergioska 22.02.2019 10:03

@sergioska, вы не теряете возврат каретки, просто замените каждый \n на <br/> вместо этого

mooga 22.02.2019 10:09

вы не можете защитить contenteditable, но что вы должны сделать, чтобы защитить его с внутренней стороны, отфильтровав входные данные

mooga 22.02.2019 10:45

Хорошо, @mooga, с этой стороны я в безопасности, потому что в этом приложении нет серверной части :)

sergioska 22.02.2019 11:54

Другие вопросы по теме