You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript实现[[Tag]]输入自动重复并解决重复触发及标签加粗需求

问题与解决方案

需求概述

  • 表单输入[[标签名]]格式内容时,自动重复为[[标签名]][[标签名]],方便在两个标签间插入内容
  • 支持带空格的标签(如[[Tag 2]]、[[Tag 3]])
  • 标签需要加粗显示
  • 修复现有代码持续重复标签的bug

修复方案

核心思路

  1. 用正则精准匹配未被重复过的[[标签]],避免每次输入都触发重复逻辑
  2. 使用富文本容器(contenteditable)实现原生加粗效果,或在普通输入框中用Markdown加粗语法
  3. 自动将光标定位到两个标签中间,提升输入体验

完整代码实现(富文本版)

HTML部分(替换原输入框)

<div id="note_text" contenteditable="true" style="border:1px solid #ccc; padding:8px; min-height:100px;"></div>
<button id="new_note_button">新建笔记</button>
<div id="new_note_form_container" style="display:none;">
  <!-- 其他表单内容 -->
</div>

JavaScript部分

function newNote() {
    const note_button = document.getElementById("new_note_button");
    const note = document.getElementById("new_note_form_container");
    if (note.style.display === "none") {
        note.style.display = "block";
        note_button.innerHTML = "仅显示笔记";
    } else {
        note.style.display = "none";
        note_button.innerHTML = "新建笔记";
    }
}

document.addEventListener('DOMContentLoaded', function(){
    const input_note = document.getElementById('note_text');
    input_note.addEventListener('input', handleTagDuplication);
});

function handleTagDuplication(ev) {
    const target = ev.target;
    // 匹配未重复的[[标签]]:匹配[[内容]]且后面没有紧跟着相同的[[内容]]
    const tagRegex = /\[\[([^\]]+)\]\](?!\[\[\1\]\])/g;
    let updatedContent = target.innerHTML;
    let match;

    // 遍历所有符合条件的标签
    while ((match = tagRegex.exec(updatedContent)) !== null) {
        const tagContent = match[1];
        const fullTag = match[0];
        // 替换为两个加粗的标签
        const replacement = `<strong>${fullTag}</strong><strong>${fullTag}</strong>`;
        updatedContent = updatedContent.replace(fullTag, replacement);
        // 重置正则索引,避免死循环
        tagRegex.lastIndex = match.index + replacement.length;
    }

    // 仅在内容变化时更新,避免频繁触发
    if (updatedContent !== target.innerHTML) {
        target.innerHTML = updatedContent;
        // 将光标移动到最后一组标签的中间
        const selection = window.getSelection();
        const range = document.createRange();
        const secondTags = target.querySelectorAll('strong:nth-child(even)');
        if (secondTags.length > 0) {
            const lastSecondTag = secondTags[secondTags.length - 1];
            range.setStartBefore(lastSecondTag);
            range.collapse(true);
            selection.removeAllRanges();
            selection.addRange(range);
        }
    }
}

普通文本框版(Markdown加粗)

如果需要使用<textarea>或<input>,可以用Markdown的**语法实现加粗:

function handleTagDuplication(ev) {
    const target = ev.target;
    let value = target.value;
    // 匹配未重复的[[标签]]
    const tagRegex = /\[\[([^\]]+)\]\](?!\[\[\1\]\])/g;
    let updatedValue = value;
    let match;

    while ((match = tagRegex.exec(value)) !== null) {
        const tagContent = match[1];
        const fullTag = match[0];
        // 替换为两个加粗的Markdown标签
        const replacement = `**${fullTag}** **${fullTag}**`;
        updatedValue = updatedValue.replace(fullTag, replacement);
    }

    if (updatedValue !== value) {
        target.value = updatedValue;
        // 定位光标到两个标签中间
        const lastTagPos = updatedValue.lastIndexOf('**[[');
        if (lastTagPos !== -1) {
            const cursorPos = lastTagPos + `**[[${tagContent}]]**`.length;
            target.setSelectionRange(cursorPos, cursorPos);
        }
    }
}

关键说明

  • 正则(?!\[\[\1\]\])是负向预查,确保只处理还没被重复的标签,解决持续重复的bug
  • 富文本版用<strong>标签实现原生加粗,视觉效果更直观
  • 光标自动定位功能让用户无需手动移动光标,直接在标签间输入内容

内容的提问来源于stack exchange,提问作者RoyKeane94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:57:38