Native JS реализует преобразование HTML в Markdown, html2md.js.
Native JS реализует преобразование HTML в Markdown, html2md.js.

Раньше по каким-то причинам мне нужно было преобразовать некоторые HTML-теги в формат уценки, но я по незнанию довел это до относительно полной функции.

Затем я инкапсулировал его в файл и разместил на github, а также просто сделал две пробные веб-страницы.

  1. HTML Конвертировать -- https://kohunglee.github.io/html2md/example/conversion.html
  2. Вставьте его прямо в markdown Формат -- https://kohunglee.github.io/html2md/example/Paste_and_convert.html

Кодовый адрес находится по адресу html2md

Код очень простой и использует собственный js. Он содержит множество простых регулярных правил и не использует дополнительных функций для оптимизации структуры. Однако позже я сделал на его основе плагин. в, я надеюсь, что это будет полезно для некоторых людей.

Адрес плагина https://www.emlog.net/plugin/detail/445

Тогда мне лень его дальше оптимизировать, поэтому я просто выложу здесь исходный код, а потом расскажу о том, как я реализовал эту функцию, надеюсь, некоторым она будет интересна.

Всего в исходном коде более 200 строк, но я знаю, что его можно написать проще.

Язык кода:javascript
копировать
/**
 * Пучок html Контент изменен преобразован в markdown Формат V1.0
 * 
 * @author kohunglee
 * @param {string} htmlData Конвертироватьбывший html 
 * @return {string} изменить markdown Исходный код
 */
function html2md(htmlData){
    codeContent     = new Array  // данные тега кода
    preContent      = new Array  // данные предварительной этикетки
    tableContent    = new Array  // данные метки таблицы
    olContent       = new Array  // старые данные этикетки
    imgContent      = new Array  // данные тега img
    aContent        = new Array  // данные тега
    let pureHtml    = htmlData

    // исходный код
    console.log("Конвертироватьбывший Исходный код:" + pureHtml)

    // Функция: удалить html-тег
    function clearHtmlTag(sourceData = ''){  
        return sourceData.replace(/\<[\s\S]*?\>/g,'')
    }

    // восстановить старый тег
    function olRecover(olData = ''){  
        let result = olData
        let num = olData.match(/\<li\>/ig).length
        for(let i = 1; i <= num; i++){
            let line = '[~wrap]'
            if(i == 1) line = '[~wrap][~wrap]'
            result = result.replace(/\<li\>/i, line + i + '. ')
        }
        result = result.replace(/\<\/li\>/, '')
        return result
    }

    // Функция: восстановить тег img
    function imgRecover(imgHtml = ''){  
        let imgSrc,imgTit,imgAlt,result
        imgSrc     = imgHtml.match(/(?<=src=['"])[\s\S]*?(?=['"])/i)
        imgTit     = imgHtml.match(/(?<=title=['"])[\s\S]*?(?=['"])/i)
        imgAlt     = imgHtml.match(/(?<=alt=['"])[\s\S]*?(?=['"])/i)

        imgTit = (imgTit != null) ? ` "${imgTit}"` : ' '
        imgAlt = (imgAlt != 'null') ? imgAlt : " "
        result = `![${imgAlt}](${imgSrc}${imgTit})`
        return result
    }

    // Функция: восстановить тег
    function aRecover(aData = ''){  
        let aHref = '' + aData.match(/(?<=href=['"])[\s\S]*?(?=['"])/i)
        let aTit  = '' + aData.match(/(?<=title=['"])[\s\S]*?(?=['"])/i)
        let aText = '' + aData.match(/(?<=\<a\s*[^\>]*?\>)[\s\S]*?(?=<\/a>)/i)

        let aImg = aData.match(/<img\s*[^\>]*?\>[^]*?(<\/img>)?/i)
        let aImgSrc,aImgTit,aImgAlt

        aTit = (aTit != 'null') ? ` "${aTit}"` : ' '
        aText = clearHtmlTag(aText)
        let result = `[${aText}](${aHref}${aTit})`

        if(aImg != null){  // Функция: если изображение найдено, перейдите в режим отображения изображения.
            aImgSrc     = aImg[0].match(/(?<=src=['"])[\s\S]*?(?=['"])/i)
            aImgTit     = aImg[0].match(/(?<=title=['"])[\s\S]*?(?=['"])/i)
            aImgAlt     = aImg[0].match(/(?<=alt=['"])[\s\S]*?(?=['"])/i)

            aImgTit = (aImgTit != null) ? ` "${aImgTit}"` : ' '
            aImgAlt = (aImgAlt != 'null') ? aImgAlt : " "
            result = `[![${aImgAlt}](${aImgSrc}${aImgTit})](${aHref}${aTit})`
        }
        return result
    }

    // Функция: восстановить метку таблицы
    function tableRecover(tableData = null){  
        if(tableData[0] == null){  // если не существует th метка, таблица по умолчанию представляет собой один слой
            let result = ''
            let colNum = tableData[1].length

            for(let i = 0; i < colNum; i++){
            result += `|${clearHtmlTag(tableData[1][i])}`
            }
            result += `|[~wrap]`
            for(let j = 0; j < colNum; j++){
                result += `| :------------: `
            }
            result += `|[~wrap]`
            return result
        }
        let colNum = tableData[0].length  // если существует th этикетка, нажмите th количество ячеек для построения всей таблицы
        let result = ''

        for(let i = 0; i < colNum; i++){
            result += `|${clearHtmlTag(tableData[0][i])}`
        }
        result += `|[~wrap]`
        for(let j = 0; j < colNum; j++){
            result += `| :------------: `
        }
        result += `|[~wrap]`
        for(let k = 0; k < tableData[1].length;){
            for(let z = 0; z < colNum; z++,k++){
                result += `|${clearHtmlTag(tableData[1][k])}`
            }
            result += `|[~wrap]`
        }
        return result+`[~wrap]`
    }
    // Удаление стилей, скриптов и контента
    pureHtml = pureHtml.replace(/<style\s*[^\>]*?\>[^]*?<\/style>/ig,'').replace(/<script\s*[^\>]*?\>[^]*?<\/script>/ig,'')

    //Сохраняем содержимое предварительно,изаменять<pre>содержание в
    preContent = pureHtml.match(/<pre\s*[^\>]*?\>[^]*?<\/pre>/ig)
    pureHtml = pureHtml.replace(/(?<=\<pre\s*[^\>]*?\>)[\s\S]*?(?=<\/pre>)/ig,''#preContent#`')

    //Сохраняем содержимое кода,изаменять<code>содержание в
    codeContent = pureHtml.match(/(?<=\<code\s*[^\>]*?\>)[\s\S]*?(?=<\/code>)/ig)
    pureHtml = pureHtml.replace(/(?<=\<code\s*[^\>]*?\>)[\s\S]*?(?=<\/code>)/ig,''#codeContent#`')

    // Сохраняем содержимое,изаменять<a>содержание в
    aContent = pureHtml.match(/<a\s*[^\>]*?\>[^]*?<\/a>/ig)
    pureHtml = pureHtml.replace(/<a\s*[^\>]*?\>[^]*?<\/a>/ig,'`#aContent#`')

    //Сохраняем содержимое img,изаменять<img>содержание в
    imgContent = pureHtml.match(/<img\s*[^\>]*?\>[^]*?(<\/img>)?/ig)
    pureHtml = pureHtml.replace(/<img\s*[^\>]*?\>[^]*?(<\/img>)?/ig,'`#imgContent#`')

    // Получить чистый (без атрибутов) html
    pureHtml = pureHtml.replace(/(?<=\<[a-zA-Z0-9]*)\s.*?(?=\>)/g,'')  

    // заголовок:целевое приобретение<h1><h2>...данные,изаменять
    pureHtml = pureHtml.replace(/<h1>/ig,'[~wrap]# ').replace(/<\/h1>/ig,'[~wrap][~wrap]')
                        .replace(/<h2>/ig,'[~wrap]## ').replace(/<\/h2>/ig,'[~wrap][~wrap]')
                        .replace(/<h3>/ig,'[~wrap]### ').replace(/<\/h3>/ig,'[~wrap][~wrap]')
                        .replace(/<h4>/ig,'[~wrap]#### ').replace(/<\/h4>/ig,'[~wrap][~wrap]')
                        .replace(/<h5>/ig,'[~wrap]##### ').replace(/<\/h5>/ig,'[~wrap][~wrap]')
                        .replace(/<h6>/ig,'[~wrap]###### ').replace(/<\/h6>/ig,'[~wrap][~wrap]')

    // Абзац: обработка некоторых общих структурных тегов
    pureHtml = pureHtml.replace(/(<br>)/ig,'[~wrap]').replace(/(<\/p>)|(<br\/>)|(<\/div>)/ig,'[~wrap][~wrap]')
                       .replace(/(<meta>)|(<span>)|(<p>)|(<div>)/ig,'').replace(/<\/span>/ig,'')

    // Смелый:заменять<b><strong>
    pureHtml = pureHtml.replace(/(<b>)|(<strong>)/ig,'**').replace(/(<\/b>)|(<\/strong>)/ig,'**')

    // курсив:заменять<i><em><abbr><dfn><cite><address>
    pureHtml = pureHtml.replace(/(<i>)|(<em>)|(<abbr>)|(<dfn>)|(<cite>)|(<address>)/ig,'*').replace(/(<\/i>)|(<\/em>)|(<\/abbr>)|(<\/dfn>)|(<\/cite>)|(<\/address>)/ig,'*')

    // удалить Проволока:заменять<del>
    pureHtml = pureHtml.replace(/\<del\>/ig,'~~').replace(/\<\/del\>/ig,'~~')

    // Цитировать:заменять<blockquote>
    pureHtml = pureHtml.replace(/\<blockquote\>/ig,'[~wrap][~wrap]> ').replace(/\<\/blockquote\>/ig,'[~wrap][~wrap]')

    // уровень Проволока:заменять<hr>
    pureHtml = pureHtml.replace(/\<hr\>/ig,'[~wrap][~wrap]------[~wrap][~wrap]')

    // лист <table>,получить данные,удалить Этикетка,Затемслой за слоемхранилище анализов, наконец-то сгенерированных на основе результатов
    tableContent = pureHtml.match(/(?<=\<table\s*[^\>]*?\>)[\s\S]*?(?=<\/table>)/ig)
    pureHtml = pureHtml.replace(/<table\s*[^\>]*?\>[^]*?<\/table>/ig,'`#tableContent#`')
    if(tableContent !== null){  // хранилище анализов
        tbodyContent = new Array
        for(let i = 0; i < tableContent.length; i++){
            tbodyContent[i] = new Array  // Первые данные tbodyContent[i] — это данные заголовка, а вторые — данные тела.
            tbodyContent[i].push(tableContent[i].match(/(?<=\<th>)[\s\S]*?(?=<\/th?>)/ig))
            tbodyContent[i].push(tableContent[i].match(/(?<=\<td>)[\s\S]*?(?=<\/td?>)/ig))
        }
    }
    if(typeof tbodyContent !== "undefined"){  // заменять
        for(let i = 0; i < tbodyContent.length; i++){
            let tableText = tableRecover(tbodyContent[i])
            pureHtml = pureHtml.replace(/\`\#tableContent\#\`/i,tableText)
        }
    }

    // упорядоченный список<ol>из<li>,Сохранить старый контент,ициклвосстанавливатьсяolсодержание в
    olContent = pureHtml.match(/(?<=\<ol\s*[^\>]*?\>)[\s\S]*?(?=<\/ol>)/ig)
    pureHtml = pureHtml.replace(/(?<=\<ol\s*[^\>]*?\>)[\s\S]*?(?=<\/ol>)/ig,'`#olContent#`')
    if(olContent !== null){
        for(let k = 0; k < olContent.length; k++){
            let olText = olRecover(olContent[k])
            pureHtml = pureHtml.replace(/\`\#olContent\#\`/i,clearHtmlTag(olText))
        }
    }

    // неупорядоченный список<ul>из<li>,а также<dd>,прямойзаменять
    pureHtml = pureHtml.replace(/(<li>)|(<dd>)/ig,'[~wrap] - ').replace(/(<\/li>)|(<\/dd>)/ig,'[~wrap][~wrap]')

    // После обработки списка <lu>、<\lu>、<ol>、<\ol> иметь дело с
    pureHtml = pureHtml.replace(/(<ul>)|(<ol>)/ig,'').replace(/(<\/ul>)|(<\/ol>)/ig,'[~wrap][~wrap]')

    // Сначала восстановите img ,Сновареставрация a
    if(imgContent !== null){
        for(let i = 0; i < imgContent.length; i++){
            let imgText = imgRecover(imgContent[i])
            pureHtml = pureHtml.replace(/\`\#imgContent\#\`/i,imgText)
        }
    }

    // восстанавливаться a
    if(aContent !== null){
        for(let k = 0; k < aContent.length; k++){
            let aText = aRecover(aContent[k])
            pureHtml = pureHtml.replace(/\`\#aContent\#\`/i,aText)
        }
    }

    // Изменять ХОРОШОиметь дело с,1.заменять [~wrap] для ‘\n’   2.голова ХОРОШОИзменять ХОРОШОУдалить。   3. Удалите другие слишком длинные слова-заменители: ХОРОШО.
    pureHtml = pureHtml.replace(/\[\~wrap\]/ig,'\n')
                       .replace(/\n{3,}/g,'\n\n')

    // код <code> ,Согласно вышеизложенномуизмножествовосстанавливатьсяcode,Затем Воляcodeзаменять
    if(codeContent !== null){
        for(let i = 0; i < codeContent.length; i++){
            pureHtml = pureHtml.replace(/\`\#codeContent\#\`/i,clearHtmlTag(codeContent[i]))
        }
    }
    pureHtml = pureHtml.replace(/\<code\>/ig,' ` ').replace(/\<\/code\>/ig,' ` ')

    // код <pre> ,восстанавливатьсяpre,Затем Воляpreзаменять
    if(preContent !== null){
        for(let k = 0; k < preContent.length; k++){
            let preLanguage = preContent[k].match(/(?<=language-).*?(?=[\s'"])/i)
            let preText = clearHtmlTag(preContent[k])
            preText = preText.replace(/^1\n2\n(\d+\n)*/,'')  // Удалить номер ХОРОШО

            preLanguage = (preLanguage != null && preLanguage[0] != 'undefined') ? preLanguage[0] + '\n' : '\n'
            pureHtml = pureHtml.replace(/\`\#preContent\#\`/i,preLanguage + preText)
        }
    }
    pureHtml = pureHtml.replace(/\<pre\>/ig,'```').replace(/\<\/pre\>/ig,'\n```\n')

    // УдалитьостальныеизhtmlЭтикетка,Восстановить предлогкодсерединаиз '<' и '>'
    pureHtml = clearHtmlTag(pureHtml)
    pureHtml = pureHtml.replace(/\&lt\;/ig,'<').replace(/\&gt\;/ig,'>')

    // Уберите пробел в шапке ХОРОШО
    pureHtml = pureHtml.replace(/^\n{1,}/i,'')

    return pureHtml
}

Среди них некоторые переменные массива объявляются вначале для хранения некоторых промежуточных продуктов во время процесса преобразования.

Затем pureHtml Эта переменная является исходным материалом на протяжении всего процесса, вплоть до самого конца.

Во-первых, точка входа для обработки функции начинается со строки 112.

Первый шаг — удалить <style> и <script> Эти два тега и их содержимое.

Второй шаг заключается в том, чтобы pre Содержимое сначала сохраняется в массиве, а затем используется ‘#preContent#’ Этот персонаж заменяет оригинальный pre Для содержимого тега я называю эту операцию защитой. Поскольку в продолжении будет много сложного контента, я pre Если он защищен, его первоначальный вкус может быть гарантирован, потому что pre Это сам код, и его нельзя потрогать.

Шаг 3,и pre Такой же code , почему сначала pre Снова code Шерстяная ткань? Поскольку эти две вещи имеют такую ​​всеобъемлющую взаимосвязь, как правило, pre Там может быть code ,но code но не pre , поэтому, рассмотрев эту логику, я решил сохранить ее вот так.

Четвертый шаг – не pre и code При помехах смело удаляйте в теге другие бесполезные атрибуты и заменяйте их на a и img тегировать содержимое "Защищать" , чтобы облегчить восстановление через некоторое время.

Шаг 5,то естьзаменятьчто-то простоеиз Этикетка,Какой титул?,Курсив,рядом Проволока Ах, подожди(кроме Волякакой-то беспорядокиз Этикеткапрямойудалить).....Последний по порядкуиметь дело слистисписок。

Шестой шаг — следовать определенным спецификациям и добавить вышеуказанное. "Защищать" контент и восстановить его.

Шаг 7,Удалите пробел ХОРОШО вверху. (Помню, я еще проверял лишние пробелы и удалял их.,Я не знаю, чего не хватает),Затем Конвертировать Завершить,Верните результат.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose