FV - BBCode Editor

Adds a BBCode formatting toolbar to Furvilla text editors.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         FV - BBCode Editor
// @namespace    https://greasyfork.org/en/users/1535374-necroam
// @version      1.6
// @description  Adds a BBCode formatting toolbar to Furvilla text editors.
// @match        https://www.furvilla.com/*
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    GM_addStyle(`
        /* Inherit */
        .bbcode-toolbar button {
            padding: 6px 8px;
            background: inherit;
            border: 1px solid currentColor;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            min-width: 32px;
            height: 32px;
            color: inherit;
            transition: all 0.2s ease;
            display: flex;
            align-items: center;
            justify-content: center;
            opacity: 0.8;
        }

        .bbcode-toolbar button:hover {
            background: inherit;
            border-color: currentColor;
            transform: translateY(-1px);
            opacity: 1;
        }

        .bbcode-toolbar button:active {
            transform: translateY(0);
            opacity: 0.9;
            box-shadow: none;
        }

        .bbcode-toolbar button:focus {
            outline: 2px solid currentColor;
            outline-offset: 2px;
        }

        /* Dark mode support - inherit from parent */
        .theme-dark .bbcode-toolbar button,
        body.dark-mode .bbcode-toolbar button,
        .dark .bbcode-toolbar button {
            background: inherit;
            border-color: currentColor;
            color: inherit;
            opacity: 0.7;
        }

        .theme-dark .bbcode-toolbar button:hover,
        body.dark-mode .bbcode-toolbar button:hover,
        .dark .bbcode-toolbar button:hover {
            background: inherit;
            border-color: currentColor;
            color: inherit;
            opacity: 1;
        }

        /* SVG icon styles */
        .bbcode-toolbar button svg {
            width: 14px;
            height: 14px;
            fill: currentColor;
            stroke: currentColor;
        }

        /* Tooltip styles - inherit from Furvilla */
        .bbcode-toolbar button::after {
            content: attr(title);
            position: absolute;
            bottom: 100%;
            left: 50%;
            transform: translateX(-50%);
            padding: 4px 8px;
            background: inherit;
            color: inherit;
            font-size: 12px;
            border-radius: 4px;
            white-space: nowrap;
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.2s;
            z-index: 1000;
            pointer-events: none;
            border: 1px solid currentColor;
        }

        .theme-dark .bbcode-toolbar button::after,
        body.dark-mode .bbcode-toolbar button::after,
        .dark .bbcode-toolbar button::after {
            background: inherit;
            color: inherit;
            border-color: currentColor;
        }

        .bbcode-toolbar {
            margin-bottom: 10px;
            padding: 8px;
            background: inherit;
            border: 1px solid currentColor;
            border-radius: 5px;
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            justify-content: center;

        }

        .theme-dark .bbcode-toolbar,
        body.dark-mode .bbcode-toolbar,
        .dark .bbcode-toolbar {
            background: inherit;
            border-color: currentColor;
        }

        /* Ensure proper inheritance chain */
        .bbcode-toolbar,
        .bbcode-toolbar button,
        .bbcode-toolbar button svg {
            color: inherit;
            background-color: inherit;
            border-color: inherit;
        }
    `);

    // SVG conversion
    const icons = {
        bold: '<svg viewBox="0 0 384 512"><path d="M304.793 243.891c33.639-18.537 53.657-54.16 53.657-95.693 0-48.236-26.25-87.626-68.626-104.179C265.138 34.01 240.849 32 209.661 32H24c-8.837 0-16 7.163-16 16v33.049c0 8.837 7.163 16 16 16h33.113v318.53H24c-8.837 0-16 7.163-16 16V464c0 8.837 7.163 16 16 16h195.69c24.203 0 44.834-1.289 66.866-7.584C337.52 457.193 376 410.647 376 350.014c0-52.168-26.573-91.684-71.207-106.123zM142.217 100.809h67.444c16.294 0 27.536 2.019 37.525 6.717 15.828 8.479 24.906 26.502 24.906 49.446 0 35.029-20.32 56.79-53.029 56.79h-76.846V100.809zm112.642 305.475c-10.14 4.056-22.677 4.907-31.409 4.907h-81.233V281.943h84.367c39.645 0 72.18 19.187 72.18 54.973 0 24.848-18.591 42.035-44.905 49.368z"/></svg>',
        italic: '<svg viewBox="0 0 384 512"><path d="M176 48h-48V16c0-8.837-7.163-16-16-16H80c-8.837 0-16 7.163-16 16v32H16C7.163 48 0 55.163 0 64v32c0 8.837 7.163 16 16 16h48v320H16c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h48v32c0 8.837 7.163 16 16 16h32c8.837 0 16-7.163 16-16v-32h48c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-48V112h48c8.837 0 16-7.163 16-16V64c0-8.837-7.163-16-16-16z"/></svg>',
        underline: '<svg viewBox="0 0 448 512"><path d="M32 64h32v160c0 88.22 71.78 160 160 160s160-71.78 160-160V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H288a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h32v160a96 96 0 0 1-192 0V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H32a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16zm400 384H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"/></svg>',
        strikethrough: '<svg viewBox="0 0 512 512"><path d="M496 288H16c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h480c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16zm-214.666 16c27.258 12.937 46.524 28.683 46.524 56.243 0 33.108-28.977 53.676-75.621 53.676-32.325 0-76.874-12.08-76.874-44.271V368c0-8.837-7.164-16-16-16H113.75c-8.836 0-16 7.163-16 16v19.204c0 66.845 77.717 101.82 154.487 101.82 88.578 0 162.013-45.438 162.013-134.424 0-19.815-3.618-36.417-10.143-50.6H281.334zm-30.952-96c-32.422-13.505-56.836-28.946-56.836-59.683 0-33.92 30.901-47.406 64.962-47.406 42.647 0 64.962 16.593 64.962 32.985V136c0 8.837 7.163 16 16 16h45.613c8.836 0 16-7.163 16-16v-30.318c0-52.438-71.725-79.875-142.575-79.875-85.203 0-150.726 40.972-150.726 125.646 0 22.71 4.665 41.176 12.777 56.547h129.823z"/></svg>',
        'align-center': '<svg viewBox="0 0 448 512"><path d="M108.1 96h231.81A12.09 12.09 0 0 0 352 83.9V44.09A12.09 12.09 0 0 0 339.91 32H108.1A12.09 12.09 0 0 0 96 44.09V83.9A12.1 12.1 0 0 0 108.1 96zM432 192H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0 256H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM108.1 416h231.81A12.09 12.09 0 0 0 352 403.9v-39.81A12.09 12.09 0 0 0 339.91 352H108.1A12.09 12.09 0 0 0 96 364.09v39.81a12.1 12.1 0 0 0 12.1 12.1z"/></svg>',
        'align-right': '<svg viewBox="0 0 448 512"><path d="M16 224h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16zm416 192H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm3.17-384H172.83A12.82 12.82 0 0 0 160 44.83v38.34A12.82 12.82 0 0 0 172.83 96h262.34A12.82 12.82 0 0 0 448 83.17V44.83A12.82 12.82 0 0 0 435.17 32zm0 256H172.83A12.82 12.82 0 0 0 160 300.83v38.34A12.82 12.82 0 0 0 172.83 352h262.34A12.82 12.82 0 0 0 448 339.17v-38.34A12.82 12.82 0 0 0 435.17 288z"/></svg>',
        'quote-right': '<svg viewBox="0 0 512 512"><path d="M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z"/></svg>',
        code: '<svg viewBox="0 0 640 512"><path d="M278.9 511.5l-61-17.7c-6.4-1.8-10-8.5-8.2-14.9L346.2 8.7c1.8-6.4 8.5-10 14.9-8.2l61 17.7c6.4 1.8 10 8.5 8.2 14.9L293.8 503.3c-1.9 6.4-8.5 10.1-14.9 8.2zm-114-112.2l43.5-46.4c4.6-4.9 4.3-12.7-.8-17.2L117 256l90.6-79.7c5.1-4.5 5.5-12.3.8-17.2l-43.5-46.4c-4.5-4.8-12.1-5.1-17-.5L3.8 247.2c-5.1 4.7-5.1 12.8 0 17.5l144.1 135.1c4.9 4.6 12.5 4.4 17-.5zm327.2.6l144.1-135.1c5.1-4.7 5.1-12.8 0-17.5L492.1 112.1c-4.8-4.5-12.4-4.3-17 .5L431.6 159c-4.6 4.9-4.3 12.7.8 17.2L523 256l-90.6 79.7c-5.1 4.5-5.5 12.3-.8 17.2l43.5 46.4c4.5 4.9 12.1 5.1 17 .6z"/></svg>',
        'eye-slash': '<svg viewBox="0 0 640 512"><path d="M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z"/></svg>',
        link: '<svg viewBox="0 0 640 512"><path d="M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z"/></svg>',
        image: '<svg viewBox="0 0 512 512"><path d="M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-6 336H54a6 6 0 0 1-6-6V118a6 6 0 0 1 6-6h404a6 6 0 0 1 6 6v276a6 6 0 0 1-6 6zM128 152c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zM96 352h320v-80l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L192 304l-39.515-39.515c-4.686-4.686-12.284-4.686-16.971 0L96 304v48z"/></svg>',
        'list-ul': '<svg viewBox="0 0 512 512"><path d="M48 48a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm0 160a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm0 160a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm448 16H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"/></svg>',
        'list-ol': '<svg viewBox="0 0 512 512"><path d="M24 368h24v48a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16H16a16 16 0 0 0-16 16v16a16 16 0 0 0 16 16zm0-224h24v48a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16H16A16 16 0 0 0 0 96v16a16 16 0 0 0 16 16zm0 112h24v48a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16H16a16 16 0 0 0-16 16v16a16 16 0 0 0 16 16zm472-224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"/></svg>',
        'text-height': '<svg viewBox="0 0 576 512"><path d="M304 32H16A16 16 0 0 0 0 48v96a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16v-32h88v304H80a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h160a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-56V112h88v32a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zm256 336h-48V144h48c14.31 0 21.33-17.31 11.31-27.31l-80-80a16 16 0 0 0-22.62 0l-80 80C379.36 126 384.36 144 400 144h48v224h-48c-14.31 0-21.32 17.31-11.31 27.31l80 80a16 16 0 0 0 22.62 0l80-80C580.64 386 575.64 368 560 368z"/></svg>',
        'arrow-right': '<svg viewBox="0 0 448 512"><path d="M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"/></svg>',
        'arrow-left': '<svg viewBox="0 0 448 512"><path d="M257.5 445.1l-22.2 22.2c-9.4 9.4-24.6 9.4-33.9 0L7 273c-9.4-9.4-9.4-24.6 0-33.9L201.4 44.7c9.4-9.4 24.6-9.4 33.9 0l22.2 22.2c9.5 9.5 9.3 25-.4 34.3L136.6 216H424c13.3 0 24 10.7 24 24v32c0 13.3-10.7 24-24 24H136.6l120.5 114.8c9.8 9.3 10 24.8.4 34.3z"/></svg>',
        table: '<svg viewBox="0 0 512 512"><path d="M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64v-96h160v96zm0-160H64v-96h160v96zm224 160H288v-96h160v96zm0-160H288v-96h160v96z"/></svg>',
        youtube: '<svg viewBox="0 0 576 512"><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>'
    };

    window.addEventListener('load', function() {
        addBBCodeToolbars();

        const observer = new MutationObserver(addBBCodeToolbars);
        observer.observe(document.body, { childList: true, subtree: true });

        watchForThemeChanges();
    });

    function watchForThemeChanges() {
        const themeObserver = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.attributeName === 'class') {
                    updateToolbarStyles();
                }
            });
        });

        themeObserver.observe(document.body, { attributes: true });

        const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
        darkModeMediaQuery.addEventListener('change', updateToolbarStyles);
    }

    function updateToolbarStyles() {
        const toolbars = document.querySelectorAll('.bbcode-toolbar');
        toolbars.forEach(toolbar => {
            toolbar.style.display = 'none';
            toolbar.offsetHeight;
            toolbar.style.display = 'flex';
        });
    }

    function addBBCodeToolbars() {
        const textareas = document.querySelectorAll('textarea:not([data-bbcode-toolbar])');

        textareas.forEach(textarea => {
            if (textarea.offsetWidth < 100 || textarea.offsetHeight < 20) return;

            textarea.dataset.bbcodeToolbar = 'added';

            const toolbar = document.createElement('div');
            toolbar.className = 'bbcode-toolbar';

            const buttons = [
                { title: 'Bold', tag: 'b', icon: 'bold', desc: 'Bold Text' },
                { title: 'Italic', tag: 'i', icon: 'italic', desc: 'Italic Text' },
                { title: 'Underline', tag: 'u', icon: 'underline', desc: 'Underlined Text' },
                { title: 'Strikethrough', tag: 's', icon: 'strikethrough', desc: 'Strikethrough Text' },
                { title: 'Center Align', tag: 'center', icon: 'align-center', desc: 'Center Align' },
                { title: 'Right Align', tag: 'right', icon: 'align-right', desc: 'Right Align' },
                { title: 'Quote', tag: 'quote', icon: 'quote-right', desc: 'Add Quote' },
                { title: 'Code', tag: 'code', icon: 'code', desc: 'Code block' },
                { title: 'Spoiler', tag: 'spoiler', icon: 'eye-slash', desc: 'Spoiler Text' },
                { title: 'Link', tag: 'url', icon: 'link', desc: 'Insert lLink' },
                { title: 'Image', tag: 'img', icon: 'image', desc: 'Insert Image' },
                { title: 'YouTube', tag: 'youtube', icon: 'youtube', desc: 'YouTube Video' },
                { title: 'List', tag: 'list', icon: 'list-ul', desc: 'Bullet List' },
                { title: 'Numbered List', tag: 'list=1', icon: 'list-ol', desc: 'Numbered List' },
                { title: 'Size', tag: 'size', icon: 'text-height', desc: 'Text Size' },
                { title: 'Float Right', tag: 'floatright', icon: 'arrow-right', desc: 'Float Right' },
                { title: 'Float Left', tag: 'floatleft', icon: 'arrow-left', desc: 'Float Left' },
                { title: 'Table', tag: 'table', icon: 'table', desc: 'Create Table' }
            ];

            buttons.forEach(btn => {
                const button = document.createElement('button');
                button.type = 'button';
                button.title = btn.desc;
                button.innerHTML = icons[btn.icon];

                button.addEventListener('click', (e) => {
                    e.preventDefault();
                    insertBBCode(textarea, btn.tag);
                });

                button.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter' || e.key === ' ') {
                        e.preventDefault();
                        insertBBCode(textarea, btn.tag);
                    }
                });

                toolbar.appendChild(button);
            });

            textarea.parentNode.insertBefore(toolbar, textarea);

            if (textarea.previousElementSibling &&
                textarea.previousElementSibling.classList.contains('bbcode-toolbar')) {
                const separator = document.createElement('div');
                separator.style.cssText = 'height: 8px; width: 100%;';
                textarea.parentNode.insertBefore(separator, textarea);
            }
        });
    }

    function insertBBCode(textarea, tag) {
        const start = textarea.selectionStart;
        const end = textarea.selectionEnd;
        const selectedText = textarea.value.substring(start, end);

        let newText = '';
        let cursorPosition = start;

        switch(tag) {
            case 'url':
                if (selectedText) {
                    if (selectedText.match(/^https?:\/\//)) {
                        newText = `[url]${selectedText}[/url]`;
                    } else {
                        newText = `[url=${selectedText}]${selectedText}[/url]`;
                    }
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[url]https://example.com[/url]`;
                    cursorPosition = start + 6;
                }
                break;

            case 'img':
                if (selectedText) {
                    newText = `[img]${selectedText}[/img]`;
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[img]https://example.com/image.jpg[/img]`;
                    cursorPosition = start + 6;
                }
                break;

            case 'youtube':
                if (selectedText) {
                    newText = `[youtube]${selectedText}[/youtube]`;
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[youtube]RuV3YMEhAB8[/youtube]`;
                    cursorPosition = start + 11;
                }
                break;

            case 'quote':
                if (selectedText) {
                    newText = `[quote]${selectedText}[/quote]`;
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[quote][/quote]`;
                    cursorPosition = start + 7;
                }
                break;

            case 'size':
                if (selectedText) {
                    newText = `[size=4]${selectedText}[/size]`;
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[size=3][/size]`;
                    cursorPosition = start + 8;
                }
                break;

            case 'list':
            case 'list=1':
                if (selectedText) {
                    const lines = selectedText.split('\n');
                    const listItems = lines.map(line => line.trim() ? `[*]${line}` : '').join('\n');
                    newText = `[${tag}]\n${listItems}\n[/list]`;
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[${tag}]\n[*]\n[/list]`;
                    cursorPosition = start + tag.length + 4;
                }
                break;

            case 'table':
                if (selectedText) {
                    newText = selectedText;
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[table][tr][td][/td][td][/td][/tr][tr][td][/td][td][/td][/tr][/table]`;
                    cursorPosition = start + 17;
                }
                break;

            default:
                if (selectedText) {
                    newText = `[${tag}]${selectedText}[/${tag}]`;
                    cursorPosition = start + newText.length;
                } else {
                    newText = `[${tag}][/${tag}]`;
                    cursorPosition = start + tag.length + 2;
                }
        }

        textarea.value = textarea.value.substring(0, start) + newText + textarea.value.substring(end);

        textarea.focus();

        requestAnimationFrame(() => {
            textarea.setSelectionRange(cursorPosition, cursorPosition);

            const lineHeight = parseInt(getComputedStyle(textarea).lineHeight) || 20;
            const cursorLine = Math.floor(cursorPosition / 80);
            textarea.scrollTop = cursorLine * lineHeight;
        });

        const inputEvent = new Event('input', { bubbles: true });
        textarea.dispatchEvent(inputEvent);

        const changeEvent = new Event('change', { bubbles: true });
        textarea.dispatchEvent(changeEvent);
    }
})();