Quill link 处理程序不工作

Quill link handler not working

我正在尝试为 link 输入值编写自定义处理程序。如果用户输入没有自定义协议的 link,我希望在输入值之前添加一个 http:。这是因为如果 link 值缺少 http:,则不会解释 link,而是显示 about:blank。 (https://github.com/quilljs/quill/issues/1268#issuecomment-272959998)

下面是我写的(类似于官方的例子here):

toolbar.addHandler("link", function sanitizeLinkInput(linkValueInput) {
    console.log(linkValueInput); // debugging

    if (linkValueInput === "")
        this.quill.format(false);

    // do nothing, since it implies user has just clicked the icon
    // for link, hasn't entered url yet
    else if (linkValueInput == true);

    // do nothing, since this implies user's already using a custom protocol
    else if (/^\w+:/.test(linkValueInput));

    else if (!/^https?:/.test(linkValueInput)) {
        linkValueInput = "http:" + linkValueInput;
        this.quill.format("link", linkValueInput);
    }
});

每次用户单击 link 图标时,没有任何反应,并且 true 会记录到控制台。我实际上希望当人们在按下 link 图标后显示的工具提示上单击 "save" 时执行此处理程序。

知道怎么做吗?也欢迎提示或建议。

谢谢!

据我所知,创建和更新 links 的处理有点分散在 Quill 的源代码中。默认的 Snow 主题在某种程度上处理编辑 links:它跟踪用户选择和内部最后选择的 link。因此,我认为仅使用自定义处理程序不可能在 Quill 中实现您当前想要的。

你可能想打开一个问题来报告这个,作者可能愿意添加这样的处理程序。

与此同时,我想出了一种更新 link 的方法,只需监听导致编辑工具提示关闭的事件。有一些复杂性,因为可以编辑 link,然后主题依赖于其内部跟踪来更新它。但是,总而言之,我认为这个解决方案还不错。您可能想在这里和那里添加一些错误检查,但总的来说它似乎工作得很好并且可以做您想做的事。我创建了一个 Fiddle 来证明这一点。为了完整起见,我也将其作为代码片段包含在此处。

var quill = new Quill('#editor', {
    modules: {
      toolbar: true
    },
    theme: 'snow'
  }),
  editor = document.getElementById('editor'),
  lastLinkRange = null;

/**
 * Add protocol to link if it is missing. Considers the current selection in Quill.
 */
function updateLink() {
  var selection = quill.getSelection(),
    selectionChanged = false;
  if (selection === null) {
    var tooltip = quill.theme.tooltip;
    if (tooltip.hasOwnProperty('linkRange')) {
      // user started to edit a link
      lastLinkRange = tooltip.linkRange;
      return;
    } else {
      // user finished editing a link
      var format = quill.getFormat(lastLinkRange),
        link = format.link;
      quill.setSelection(lastLinkRange.index, lastLinkRange.length, 'silent');
      selectionChanged = true;
    }
  } else {
    var format = quill.getFormat();
    if (!format.hasOwnProperty('link')) {
      return; // not a link after all
    }
    var link = format.link;
  }
  // add protocol if not there yet
  if (!/^https?:/.test(link)) {
    link = 'http:' + link;
    quill.format('link', link);
    // reset selection if we changed it
    if (selectionChanged) {
      if (selection === null) {
        quill.setSelection(selection, 0, 'silent');
      } else {
        quill.setSelection(selection.index, selection.length, 'silent');
      }
    }
  }
}

// listen for clicking 'save' button
editor.addEventListener('click', function(event) {
  // only respond to clicks on link save action
  if (event.target === editor.querySelector('.ql-tooltip[data-mode="link"] .ql-action')) {
    updateLink();
  }
});

// listen for 'enter' button to save URL
editor.addEventListener('keydown', function(event) {
  // only respond to clicks on link save action
  var key = (event.which || event.keyCode);
  if (key === 13 && event.target === editor.querySelector('.ql-tooltip[data-mode="link"] input')) {
    updateLink();
  }
});
<link href="https://cdn.quilljs.com/1.1.10/quill.snow.css" rel="stylesheet" />
<script src="https://cdn.quilljs.com/1.1.10/quill.min.js"></script>
<div id="editor"></div>

如果您有任何问题,请告诉我。

单击工具栏中的按钮时,工具栏处理程序将调用您给定的函数。传入的 value 取决于该格式在用户选择中的状态。因此,如果用户只突出显示纯文本,并单击 link 按钮,您将得到 false。如果用户突出显示 link,您将获得 link 的值,默认情况下为 url。这里用一个例子来解释:http://quilljs.com/docs/modules/toolbar/#handlers.

雪花主题使用工具栏的 addHandler 本身来显示工具提示,看起来您正在尝试连接到此,目前无法实现。

看起来您真正想做的是控制 link 的清理逻辑。清理存在于 Quill 的较低级别,因为有许多方法可以插入 link,例如从工具提示 UI、粘贴、不同的 API 等等。因此,为了涵盖它们,所有逻辑都在 link 格式本身中。 link 的自定义格式的示例具体包含在 http://quilljs.com/guides/cloning-medium-with-parchment/#links 中。您也可以只修改 Quill 自己的 sanitize 方法,但不推荐这样做,因为它没有记录也没有被 semver 涵盖。

let Link = Quill.import('formats/link');
Link.sanitize = function(value) {
  return 'customsanitizedvalue';
}

汇总所有信息

雪花主题本身使用工具栏的 addHandler 来显示工具提示,因此无法使用 addHandler 方法来实现我们想要的。

因此,我们可以执行以下操作:

var Link = Quill.import('formats/link');
var builtInFunc = Link.sanitize;
Link.sanitize = function customSanitizeLinkInput(linkValueInput) {
    var val = linkValueInput;

    // do nothing, since this implies user's already using a custom protocol
    if (/^\w+:/.test(val));
    else if (!/^https?:/.test(val))
        val = "http:" + val;

    return builtInFunc.call(this, val); // retain the built-in logic
};

此方法不会挂接到处理程序,而是会修改 built-in 清理逻辑本身。我们还保留了清理的原始行为,因此不会修改编辑器的原始行为。

或者,我们实际上可以使用 钩住工具提示的保存按钮。但与上面的方法相比,它是一种太长的方法。

半小时后

找到这个解决方案

htmlEditorModuleConfig = {
    toolbar: [
        ['link']                        
    ],    
        bounds: document.body   
}

在配置中添加'bounds: document.body'

我必须做同样的事情,(在发送到服务器之前验证 url)所以我最终得到了这样的东西。

 const editor = new DOMParser().parseFromString(value, 
'text/html');
const body = qlEditor.getElementsByTagName('body');    
const data = document.createElement('div');
data.innerHTML = body[0].innerHTML;
Array.from(data.querySelectorAll('a')).forEach((ele) => {
  let href  = ele.getAttribute('href');
  if (!href.includes('http') && !href.includes('https')) {
    href = `https://${href}`;
    ele.setAttribute('href', href);
  }
});
body[0].innerHTML = data.innerHTML;

也许这是一个老问题,但这是我让它工作的方式。

首先,它将其他自定义协议列入白名单以作为有效协议接受。 然后,我们 运行 已经包含在 Quill 核心中的 sanitize 方法,并且基于自定义协议列表它将 return URL 或 about:blank . 然后,如果这是一个 about:blank 是因为它没有通过消毒方法。如果我们得到 URL 然后我们验证它是否有列表中的协议,如果没有,那么我们附加 http:// 这样我们就不会得到相对 URL 或空白除非它没有被列入白名单:

  • https://your-site.com/www.apple.com
  • about:blank

希望它能帮助遇到同样问题的其他人。

const Link = Quill.import('formats/link')
// Override the existing property on the Quill global object and add custom protocols
Link.PROTOCOL_WHITELIST = ['http', 'https', 'mailto', 'tel', 'radar', 'rdar', 'smb', 'sms']

class CustomLinkSanitizer extends Link {
  static sanitize(url) {
    // Run default sanitize method from Quill
    const sanitizedUrl = super.sanitize(url)

    // Not whitelisted URL based on protocol so, let's return `blank`
    if (!sanitizedUrl || sanitizedUrl === 'about:blank') return sanitizedUrl

    // Verify if the URL already have a whitelisted protocol
    const hasWhitelistedProtocol = this.PROTOCOL_WHITELIST.some(function(protocol) {
      return sanitizedUrl.startsWith(protocol)
    })

    if (hasWhitelistedProtocol) return sanitizedUrl

    // if not, then append only 'http' to not to be a relative URL
    return `http://${sanitizedUrl}`
  }
}

Quill.register(CustomLinkSanitizer, true)