Markdown格式化工具

在toolhelper.cn的Markdown编辑器中添加格式化功能按钮和快捷键(ctrl+shift+F)

// ==UserScript==
// @name         Markdown格式化工具
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  在toolhelper.cn的Markdown编辑器中添加格式化功能按钮和快捷键(ctrl+shift+F)
// @author       damu
// @match        https://www.toolhelper.cn/Code/Markdown
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 等待编辑器加载完成
    const waitForEditor = setInterval(() => {
        const toolbar = document.querySelector('.editormd-toolbar-container ul');
        if (!toolbar) return;

        clearInterval(waitForEditor);

        // 创建格式化按钮
        const formatBtn = document.createElement('li');
        formatBtn.innerHTML = `<a href="javascript:;" title="格式化表格 (Alt+Shift+F)"><i class="fa fa-align-center" name="format-table"></i></a>`;
        toolbar.insertBefore(formatBtn, toolbar.querySelector('.divider'));

        // 获取编辑器内容
        const getEditorContent = () => {
            const cmEditor = document.querySelector('.CodeMirror')?.CodeMirror;
            if (cmEditor) return cmEditor.getValue();

            const editor = document.querySelector('.editormd-markdown-textarea');
            return editor ? editor.value : '';
        };

        // 设置编辑器内容
        const setEditorContent = (content) => {
            const cmEditor = document.querySelector('.CodeMirror')?.CodeMirror;
            if (cmEditor) {
                cmEditor.setValue(content);
                return;
            }

            const editor = document.querySelector('.editormd-markdown-textarea');
            if (editor) {
                editor.value = content;
                editor.dispatchEvent(new Event('input'));
            }
        };

        // 格式化表格行
        const formatTableLine = (line) => {
            const cells = line.split('|').map(cell => cell.trim());
            let result = '|';

            for (let i = 1; i < cells.length - 1; i++) {
                const content = cells[i] === '' ? '  ' : ` ${cells[i]} `;
                result += content + '|';
            }

            return result;
        };

        // 格式化分隔线
        const formatSeparatorLine = (line) => {
            const cells = line.split('|').map(cell => cell.trim());
            let result = '|';

            for (let i = 1; i < cells.length - 1; i++) {
                result += ' --- |';
            }

            return result;
        };

        // 主格式化函数
        const formatTable = () => {
            const content = getEditorContent();
            if (!content) return;

            const lines = content.split('\n');
            let tableStart = -1;
            let tableEnd = -1;
            const tables = [];

            // 识别表格范围
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i].trim();
                if (line.startsWith('|') && line.endsWith('|')) {
                    if (tableStart === -1) {
                        tableStart = i;
                    }
                    tableEnd = i;
                } else if (tableStart !== -1) {
                    // 检查是否是分隔线
                    if (i === tableStart + 1 && line.includes('|') && line.replace(/[^|-]/g, '').length > 0) {
                        tableEnd = i;
                    } else {
                        // 表格结束
                        if (tableEnd - tableStart >= 1) {
                            tables.push({start: tableStart, end: tableEnd});
                        }
                        tableStart = -1;
                        tableEnd = -1;
                    }
                }
            }

            // 捕获最后一个表格
            if (tableStart !== -1 && tableEnd - tableStart >= 1) {
                tables.push({start: tableStart, end: tableEnd});
            }

            if (tables.length === 0) {
                return alert('未检测到有效的Markdown表格\n表格应由两行或更多行组成,以|开头');
            }

            // 格式化每个表格
            const newLines = [...lines];
            tables.forEach(({start, end}) => {
                // 处理表头
                newLines[start] = formatTableLine(newLines[start]);

                // 处理分隔线
                if (start + 1 <= end) {
                    newLines[start + 1] = formatSeparatorLine(newLines[start + 1]);
                }

                // 处理表格内容
                for (let i = start + 2; i <= end; i++) {
                    newLines[i] = formatTableLine(newLines[i]);
                }
            });

            setEditorContent(newLines.join('\n'));
        };

        // 按钮点击事件
        formatBtn.querySelector('a').addEventListener('click', formatTable);

        // 添加快捷键 Alt+Shift+F
        document.addEventListener('keydown', e => {
            if (e.altKey && e.shiftKey && e.key === 'F') {
                e.preventDefault();
                formatTable();
            }
        });
    }, 100);
})();