Coder Social home page Coder Social logo

jarontai / html2md Goto Github PK

View Code? Open in Web Editor NEW
58.0 4.0 25.0 113 KB

A library for converting HTML to Markdown in Dart. It supports CommonMark, simple table and custom converting rules. 将html转换为markdown的Dart库,支持CommonMark、简单表格以及自定义转换规则。

Home Page: https://pub.dev/packages/html2md

License: BSD 2-Clause "Simplified" License

Dart 100.00%
dart html markdown converter

html2md's Introduction

English | 简体中文

html2md

Pub Build status

A library for converting HTML to Markdown in Dart. It supports CommonMark, simple table and custom converting rules.

Usage

A simple usage example:

import 'package:html2md/html2md.dart' as html2md;

main() {
    var html = '<h1>HTML2MD Demo</h1>';
    print(html2md.convert(html));
}

In flutter, you can use the flutter_markdown for rendering:

import 'package:html2md/html2md.dart' as html2md;
import 'package:flutter_markdown/flutter_markdown.dart';

build(BuildContext context) {
    // Caution!
    // This is not best practice, you should not call convert in build
    // and the converted markdown should put in state.
    var html = '<h1>HTML2MD Demo</h1>';
    var markdown = html2md.convert(html);
    return Markdown(data: markdown);
}

Config

You can config convert style by passing styleOptions to convert, elements that should be ignored also can be set with ignore. If you want to customize element converting, use custom rules!

html2md.convert(html,
    styleOptions: {'headingStyle': 'atx'},
    ignore: ['script'],
    rules: [Rule('custom')]);

The default and available style options:

Name Default Options
headingStyle "setext" "setext", "atx"
hr "* * *" "* * *", "- - -", "_ _ _"
bulletListMarker "*" "*", "-", "_"
codeBlockStyle "indented" "indented", "fenced"
fence "```" "```", "~~~"
emDelimiter "_" "_", "*"
strongDelimiter "**" "**", "__"
linkStyle "inlined" "inlined", "referenced"
linkReferenceStyle "full" "full", "collapsed", "shortcut"

Table support

Basic table converting is supported!

Html table source:

<table>
    <tr>
        <th>First Header</th>
        <th>First Header</th> 
    </tr>
    <tr>
        <td>Content Cell</td>
        <td>Content Cell</td>
    </tr>
    <tr>
        <td>Content Cell</td>
        <td>Content Cell</td>
    </tr>
</table>

The converted markdown source:

| First Header  | Second Header |
| ----- | ----- |
| Content Cell  | Content Cell  |
| Content Cell  | Content Cell  |

The converted markdown table:

First Header Second Header
Content Cell Content Cell
Content Cell Content Cell

Custom Rules

Want to customize element converting? Write your rules!

Rule fields explaination

final String name; // unique rule name
final List<String>? filters; // simple element name filters, e.g. ['aside']
final FilterFn? filterFn; // function for building complex element filter logic
final Replacement? replacement; // function for doing the replacing
final Append? append; // function for appending content

Rule example - Convert the onebox section of discourse post to a link

<aside class="onebox">
  <header class="source">
      <img src="https://discoursesite/uploads/default/original/1X/test.png" class="site-icon" width="32" height="32">
      <a href="https://events.google.com/io/program/content?4=topic_flutter&amp;lng=zh-CN" target="_blank" rel="noopener">Google I/O 2021</a>
  </header>
</aside>
Rule(
  'discourse-onebox',
  filterFn: (node) {
    // Find aside with onebox class
    if (node.nodeName == 'aside' &&
        node.className.contains('onebox')) {
        return true;
    }
    return false;
  },
  replacement: (content, node) {
    // find the first a element under header
    var header = node.firstChild;
    var link = header!
        .childNodes()
        .firstWhere((element) => element.nodeName == 'a');
    var href = link.getAttribute('href');
    if (href != null && href.isNotEmpty) {
      return '[$href]($href)'; // build the link
    }
    return '';
  },
)

Test

dart run test

Features and bugs

Please file feature requests and bugs at the issue tracker.

Inspiration

html2md is basicly a simplify version of Node's turndown

License

Created from templates made available by Stagehand under a BSD-style license.

html2md's People

Contributors

doflatango avatar geertjohan avatar jarontai avatar joostory avatar kubaprzetakiewicz avatar leynier avatar lindeer avatar scribetw avatar tadejkan avatar tomyeh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

html2md's Issues

listItem parse start error Invalid argument(s): The source must not be null

I'm getting this error all of a sudden when parsing HTML. I'm still trying to analyze the source code to see why, but maybe the library can account for the error? I'm attaching a link to a sample project. all you have to do is run it in debug mode and enable the breakpoints to see the error. It seems to render fine, I believe, but I can't say for certain that something isn't left out/
https://github.com/ThinkDigitalSoftware/html2markdown_error_example

Titles in links don't convert properly

Links aren't converted properly if title is provided.

How to reproduce

final linkWithTitle = html2md.convert("<a href="https://example.com" title="Example title">Example content</a>");

What is returned:

[Example content](https://example.comExample title)

What is expected (verifiable via https://domchristie.github.io/turndown/):

[Example content](https://example.com "Example title")

Environment

flutter doctor -v
➜ flutter doctor -v
[✓] Flutter (Channel beta, 2.0.1, on macOS 11.0.1 20B50 darwin-x64, locale en-GB)
    • Flutter version 2.0.1 at /Users/kubcio/.flutter
    • Framework revision c5a4b4029c (12 days ago), 2021-03-04 09:47:48 -0800
    • Engine revision 40441def69
    • Dart version 2.12.0

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/kubcio/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] IntelliJ IDEA Ultimate Edition (version 2020.3.2)
    • IntelliJ at /Applications/IntelliJ IDEA.app
    • Flutter plugin version 54.0.3
    • Dart plugin version 203.7759

[✓] VS Code (version 1.54.3)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.20.0

[✓] Connected device (3 available)
    • iPhone 11 (mobile) • 5081BDDF-BBB7-4110-A773-2B2F2AB9A700 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-4 (simulator)
    • macOS (desktop)    • macos                                • darwin-x64     • macOS 11.0.1 20B50 darwin-x64
    • Chrome (web)       • chrome                               • web-javascript • Google Chrome 89.0.4389.82

• No issues found!

html2md ^0.3.1 requires html ^0.13.3.

Updating the pubspec to the lastest versions of html package cause pug get to fail.

html2md ^0.3.1 requires html ^0.13.3.
So, because XXXX depends on both html ^0.14.0+2 and html2md ^0.3.1, version solving failed.

Exception with blockquote

Whenever I use the blockquote tag I get an exception:

Another exception was thrown: 'package:flutter/src/widgets/container.dart': Failed assertion: line 59 pos 15: 'decoration != null': is not true.

Example code:
String markdown = html2md.convert('<blockquote>Lorem ipsum...</blockquote>');

text-align did not convert

I have this html
<h1 style="margin-left:0px;text-align:center;">Personal Data Protection Policy&nbsp;<br>of&nbsp;<br>Public Company Limited and&nbsp;<br>Group of companies</h1>
it should be like this
Screenshot 2566-09-26 at 17 25 41
but the result is
Screenshot 2566-09-26 at 17 25 58

content in <script> tags are not filtered out

This snippet:

final html = """
<!DOCTYPE html>
<head>
	<script>
    console.log("test");
	</script>
</head>
<body>
Hello
</body>
""";
final md = html2md.convert(html);
print(md);

prints out a string that contains 'console.log("test");'. I would have expected only Hello to be included.

Table support for loose html

The html was generated by Outlook.

The table markdown is invalid if <th> is not added. Also the <br> should be ignored in cells.

final html = '''
<table style="border-collapse:collapse; box-sizing:border-box; height:64px" cellspacing="0" cellpadding="1">
  <tbody>
    <tr>
      <td scope="" style="width:123px; border-color:rgb(171,171,171); border-style:solid; border-width:1px; background-color:transparent; box-sizing:border-box; height:22px">Name<br aria-hidden="true"></td>
      <td scope="" style="width:200px; border-color:rgb(171,171,171); border-style:solid; border-width:1px; background-color:transparent; box-sizing:border-box; height:22px; word-break:break-word; white-space:normal">Value<br aria-hidden="true"></td>
    </tr>
    <tr>
      <td scope="" style="width:123px; border-color:rgb(171,171,171); border-style:solid; border-width:1px; background-color:transparent; box-sizing:border-box; height:41px">Hello,<br aria-hidden="true"></td>
      <td style="width:200px; border-color:rgb(171,171,171); border-style:solid; border-width:1px; background-color:transparent; box-sizing:border-box; height:41px; word-break:break-word; white-space:normal">world from MS 365!<br aria-hidden="true"></td>
    </tr>
  </tbody>
</table>
''';
print(html2md.convert(html));

Actual

| Name  
 | Value  
 |
| Hello,  
 | world from MS 365!  
 |

Expected

| Name    | Value    |
| --- | --- |
| Hello,    | world from MS 365!    |

Compared with Turndown (+ GFM Plugin)
https://guyplusplus.github.io/turndown-plugin-gfm/

Tables are not being converted properly

This is slightly complex, but I've narrowed it down to this package.
I'm using this lib to convert html to markdown and then render it in Flutter.
The original Markdown source is here. https://github.com/flutterchina/dio/blob/master/README.md
for comparison.
This is the actual HTML page that's being passed to html2md https://pub.dev/packages/dio
You can see the table in the screenshot
Screen Shot 2019-11-13 at 10 39 00 AM

But when it's rendered, it shows like this.
Simulator Screen Shot - iPhone 11 Pro Max - 2019-11-13 at 10 36 09

To make a long story short, the table should be rendered like this,
https://github.com/flutterchina/dio/blob/master/README.md

Copy of markdown rendered by html2md

Exception when using inside ListView(Builder)

When this widget is used inside of a ListView or a ListViewBuilder, the following exception is thrown:
Vertical viewport was given unbounded height.
Some more info:
Viewports expand in the scrolling direction to fill their container.In this case, a vertical I/flutter ( 9925): viewport was given an unlimited amount of vertical space in which to expand. This situation I/flutter ( 9925): typically happens when a scrollable widget is nested inside another scrollable widget. I/flutter ( 9925): If this widget is always nested in a scrollable widget there is no need to use a viewport because I/flutter ( 9925): there will always be enough vertical space for the children. In this case, consider using a Column I/flutter ( 9925): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size I/flutter ( 9925): the height of the viewport to the sum of the heights of its children.

Using shrinkWrap, or wrapping the HTML view widget inside a Container, Flexible, or Expanded does not help.

Warnings printed during the usage of html2md

Thank you for your great package.

If I use it, I see the following warnings:

../../.pub-cache/hosted/pub.dev/html2md-1.3.1/lib/src/converter.dart:108:41: Warning: Operand of null-aware operation '!' has type 'Node' which excludes null.
 - 'Node' is from 'package:html/dom.dart' ('../../.pub-cache/hosted/pub.dev/html-0.15.4/lib/dom.dart').
    sibling = util.previousSibling(node.node!);
                                        ^
../../.pub-cache/hosted/pub.dev/html2md-1.3.1/lib/src/converter.dart:111:37: Warning: Operand of null-aware operation '!' has type 'Node' which excludes null.
 - 'Node' is from 'package:html/dom.dart' ('../../.pub-cache/hosted/pub.dev/html-0.15.4/lib/dom.dart').
    sibling = util.nextSibling(node.node!);

Converter still works but maybe you want to silence these warnings.

Ignore Markdown on String

Hi, I am trying to convert HTML with markdown together
String example: ## Heading level 2 <p>html p<p>

ApPpV9.png

blockquote text style not applying

When trying to apply a text style to a blockquote, I am not seeing anything change.

return MarkdownBody(
      styleSheet: MarkdownStyleSheet(
        blockquote: TextStyle(color: Colors.blue),
        blockquoteDecoration: BoxDecoration(
          border: Border(
            left: BorderSide(
              width: 2.0,
            ),
          ),
        ),
        blockquotePadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      ),
      data: convert('<blockquote>this is a blockquote</blockquote>'),
);

I see the padding & the decoration, but not the text style.

Redirect on link click

Hello, I want to redirect when the user clicks on a link like '<a href=""></a>'. How can I track user click on link?

I will be glad if you help.

Edit:
I was able to do this with MarkdownBody. #close

                `MarkdownBody(
                  selectable: true,
                  data: html2md.convert(data),
                  onTapLink: (text, href, title) {
                    try {
                      launch(href ?? "");
                    } catch (e) {
                      print(e);
                    }
                  },
                ),

`

New lines added with lists

I have the following HTML code:
<p>List title:</p><ul><li>Item one</li></ul>

This produces:

List title:

- Item one

With the extra line break between the title and the item.

How can we avoid this? I don't want a line break added unless there explicitly is a <br />.

Thanks!

Links for TOC - Spaces are replaced with _ insted of -

Hi,

after converting a wikipage to markdown using html2md the links of the table of content do not work for me because the spaces are being replaced with _ (underscores) instead of - (hyphens).
Is there a way to change this?

BR, Jennifer

Warning when compiling into native code (dart compile exe)

.pub-cache/hosted/pub.dev/html2md-1.3.1/lib/src/converter.dart:111:37: Warning: Operand of null-aware operation '!' has type 'Node' which excludes null.
 - 'Node' is from 'package:html/dom.dart' ('.pub-cache/hosted/pub.dev/html-0.15.4/lib/dom.dart').
    sibling = util.nextSibling(node.node!);

Issue with special characters

Hello! first of all thank you for your work on this library.

I am having an issue transforming an html file with characters like for example: è or when is a space and then a dot.
It shows weird characters like for example  instead è.

Another case is when I have the symbol ". It shows instead â followed by two boxes.

I hope my problem is more or less clear.

Thank you again!

The getter 'localName' was called on null.

String html = ''''<div class="postArticle-content js-postField js-notesSource js-trackedPost" data-post-id="ac7a012b7a25" data-source="post_page" data-tracking-context="postPage" data-scroll="native"><section name="1ef3" class="section section--body section--first"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><h1 name="0b3a" id="0b3a" class="graf graf--h3 graf--leading graf--title">Rtmp Player Android using Exo-Media Player</h1><p name="12c9" id="12c9" class="graf graf--p graf-after--h3">Hello Reader’s, before we start</p><h3 name="e452" id="e452" class="graf graf--h3 graf-after--p">Lets see What is RTMP&nbsp;?</h3><p name="61c0" id="61c0" class="graf graf--p graf-after--h3">RTMP stands for <strong class="markup--strong markup--p-strong">real-time messaging protocol</strong>. It provides for high-performance transmission of audio, video, and data from an encoder to a server, which distributes the signal across the Internet. Many streaming providers and encoder developers support RTMP streaming, including Livestream.</p><p name="54ad" id="54ad" class="graf graf--p graf-after--p">read more about rtmp <a href="https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol" data-href="https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol" class="markup--anchor markup--p-anchor" rel="nofollow noopener" target="_blank">here</a>.</p><p name="72b6" id="72b6" class="graf graf--p graf-after--p">No more Theory lets start coding&nbsp;:-)</p><h4 name="8eb6" id="8eb6" class="graf graf--h4 graf-after--p">Step 1:</h4><p name="b87c" id="b87c" class="graf graf--p graf-after--h4">change minimum SDK version</p><pre name="5d83" id="5d83" class="graf graf--pre graf-after--p">defaultConfig{<br>...<br>minSdkVersion 15<br>...<br>}</pre><p name="48bb" id="48bb" class="graf graf--p graf-after--pre">because in order to use this extension-rtmp library the minimum sdk needed is 15</p><p name="fc41" id="fc41" class="graf graf--p graf-after--p">edit your <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">build.gradle</em></strong> file and add the following two dependencies</p><pre name="6919" id="6919" class="graf graf--pre graf-after--p"><span class="markup--quote markup--pre-quote is-other" name="9a0b2939de14" data-creator-ids="c1efa5b3e3d9">compile 'com.google.android.exoplayer:exoplayer:r2.5.1' compile 'com.google.android.exoplayer:extension-rtmp:r2.5.1'</span></pre><p name="6218" id="6218" class="graf graf--p graf-after--pre">then sync your project</p><h4 name="a3ca" id="a3ca" class="graf graf--h4 graf-after--p">Step 2:</h4><p name="738c" id="738c" class="graf graf--p graf-after--h4">Create a simple exoplayer view in your layout file</p><pre name="b4b2" id="b4b2" class="graf graf--pre graf-after--p">&lt;com.google.android.exoplayer2.ui.SimpleExoPlayerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/simple_player"&gt; &lt;/com.google.android.exoplayer2.ui.SimpleExoPlayerView&gt;</pre><h4 name="ddc0" id="ddc0" class="graf graf--h4 graf-after--pre">Step 3:</h4><p name="3682" id="3682" class="graf graf--p graf-after--h4">Now in your player activity add the lines to prepare the player</p><figure name="7f2e" id="7f2e" class="graf graf--figure graf--iframe graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 77.286%;"></div><div class="progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded" data-scroll="native"><img src="https://i.embed.ly/1/display/resize?url=https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F19759716%3Fv%3D4%26s%3D400&amp;key=4fce0568f2ce49e8b54624ef71a8a5bd&amp;width=40" crossorigin="anonymous" class="progressiveMedia-thumbnail js-progressiveMedia-thumbnail"><canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="75" height="75"></canvas><div class="iframeContainer"><iframe data-src="/media/4e35a514ae391514736c81a899e52ac6?postId=ac7a012b7a25" data-media-id="4e35a514ae391514736c81a899e52ac6" data-thumbnail="https://i.embed.ly/1/image?url=https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F19759716%3Fv%3D4%26s%3D400&amp;key=4fce0568f2ce49e8b54624ef71a8a5bd" class="progressiveMedia-iframe js-progressiveMedia-iframe" allowfullscreen="" src="/media/4e35a514ae391514736c81a899e52ac6?postId=ac7a012b7a25" __idm_frm__="10737418307" width="700" height="250" frameborder="0"></iframe></div><noscript class="js-progressiveMedia-inner"><div class="iframeContainer"><IFRAME width="700" height="250" src="/media/4e35a514ae391514736c81a899e52ac6?postId=ac7a012b7a25" data-media-id="4e35a514ae391514736c81a899e52ac6" data-thumbnail="https://i.embed.ly/1/image?url=https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F19759716%3Fv%3D4%26s%3D400&amp;key=4fce0568f2ce49e8b54624ef71a8a5bd" allowfullscreen frameborder="0"></IFRAME></div></noscript></div></div></figure><p name="2e47" id="2e47" class="graf graf--p graf-after--figure">Run your code and the rtmp stream will be playing in your app and the size of is approx ~2.5Mb</p><p name="e2ae" id="e2ae" class="graf graf--p graf-after--p graf--trailing">download the project <a href="https://github.com/PonnamKarthik/RTMP-Exo-Player-Demo" data-href="https://github.com/PonnamKarthik/RTMP-Exo-Player-Demo" class="markup--anchor markup--p-anchor" rel="nofollow noopener" target="_blank">here</a>.</p></div></div></section><section name="49a5" class="section section--body section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><blockquote name="a575" id="a575" class="graf graf--pullquote graf--leading graf--trailing">If you find this article useful please recommend and&nbsp;share.</blockquote></div></div></section></div>''';

i got the below error when i am trying with the above html code

I/flutter (24544): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (24544): The following NoSuchMethodError was thrown building PostDetails(dirty, state:
I/flutter (24544): _PostDetailsState#fb885):
I/flutter (24544): The getter 'localName' was called on null.
I/flutter (24544): Receiver: null
I/flutter (24544): Tried calling: localName
I/flutter (24544): 
I/flutter (24544): When the exception was thrown, this was the stack:
I/flutter (24544): #0      Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:46:5)
I/flutter (24544): #1      Node.nodeName (package:html2md/src/node.dart:58:30)
I/flutter (24544): #2      Rules.indentedCodeBlock.<anonymous closure> (package:html2md/src/rules.dart:165:25)
I/flutter (24544): #3      Rule._check (package:html2md/src/rules.dart:49:61)
I/flutter (24544): #4      Rule.findRule.<anonymous closure> (package:html2md/src/rules.dart:59:55)
I/flutter (24544): #5      _ListBase&Object&ListMixin.firstWhere (dart:collection/list.dart:142:15)
I/flutter (24544): #6      Rule.findRule (package:html2md/src/rules.dart:59:29)
I/flutter (24544): #7      _replacementForNode (package:html2md/src/converter.dart:79:19)
I/flutter (24544): #8      _process (package:html2md/src/converter.dart:71:21)
I/flutter (24544): #9      _replacementForNode (package:html2md/src/converter.dart:83:17)
I/flutter (24544): #10     _process (package:html2md/src/converter.dart:71:21)
I/flutter (24544): #11     convert (package:html2md/src/converter.dart:44:16)
I/flutter (24544): #12     _PostDetailsState.getPostContent (package:bloggerapp/screens/post_details.dart:129:23)
I/flutter (24544): #13     _PostDetailsState.build (package:bloggerapp/screens/post_details.dart:96:19)
I/flutter (24544): #14     StatefulElement.build (package:flutter/src/widgets/framework.dart:3713:27)
I/flutter (24544): #15     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3625:15)
I/flutter (24544): #16     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #17     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #18     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
I/flutter (24544): #19     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #20     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #21     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #22     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #23     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #24     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #25     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #26     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #27     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #28     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
I/flutter (24544): #29     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #30     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #31     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
I/flutter (24544): #32     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #33     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #34     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
I/flutter (24544): #35     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #36     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #37     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
I/flutter (24544): #38     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #39     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #40     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #41     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #42     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #43     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
I/flutter (24544): #44     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #45     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #46     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #47     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #48     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #49     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #50     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #51     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #52     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #53     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #54     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #55     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #56     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
I/flutter (24544): #57     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #58     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #59     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #60     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
I/flutter (24544): #61     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #62     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #63     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #64     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #65     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #66     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #67     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #68     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #69     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
I/flutter (24544): #70     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #71     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #72     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #73     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #74     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #75     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
I/flutter (24544): #76     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #77     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #78     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #79     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #80     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #81     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #82     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #83     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #84     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #85     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
I/flutter (24544): #86     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #87     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #88     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #89     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #90     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #91     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #92     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #93     Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #94     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #95     Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #96     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #97     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
I/flutter (24544): #98     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #99     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #100    Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #101    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #102    Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #103    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
I/flutter (24544): #104    StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
I/flutter (24544): #105    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
I/flutter (24544): #106    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
I/flutter (24544): #107    Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
I/flutter (24544): #108    RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4420:32)
I/flutter (24544): #109    MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4752:17)
I/flutter (24544): #110    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #111    _TheatreElement.update (package:flutter/src/widgets/overlay.dart:507:16)
I/flutter (24544): #112    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #113    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #114    Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #115    StatefulElement.update (package:flutter/src/widgets/framework.dart:3782:5)
I/flutter (24544): #116    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #117    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #118    Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #119    ProxyElement.update (package:flutter/src/widgets/framework.dart:3892:5)
I/flutter (24544): #120    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #121    SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4644:14)
I/flutter (24544): #122    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #123    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #124    Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #125    StatefulElement.update (package:flutter/src/widgets/framework.dart:3782:5)
I/flutter (24544): #126    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #127    SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4644:14)
I/flutter (24544): #128    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #129    SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4644:14)
I/flutter (24544): #130    Element.updateChild (package:flutter/src/widgets/framework.dart:2682:15)
I/flutter (24544): #131    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
I/flutter (24544): #132    Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
I/flutter (24544): #133    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2225:33)
I/flutter (24544): #134    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:621:20)
I/flutter (24544): #135    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:208:5)
I/flutter (24544): #136    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter (24544): #137    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter (24544): #138    _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter (24544): [{ID: 1, url: https://android-developers.googleblog.com, blogid: 6755709643044947179, blogname: Android Developers Blog}]
I/flutter (24544): #139    _invoke (dart:ui/hooks.dart:120:13)
I/flutter (24544): #140    _drawFrame (dart:ui/hooks.dart:109:3)
I/flutter (24544): ════════════════════════════════════════════════════════════════════════════════════════════════════

[proposal] `convert` accept `dom.Node` parameter

add another convert function like:

String from(
  String Dom.Node, {
  String? rootTag,
  String? imageBaseUrl,
  Map<String, String>? styleOptions,
  List<String>? ignore,
  List<Rule>? rules,
}) 

In some cases, we have to modify html DOM tree before we pass it to html2md, the new function could avoid extra parsing operations.

<pre> element not converted to Markdown code

Hi, I'm using your library to convert Wiki pages to Markdown, for example :https://wiki.eclipse.org/Version_Numbering

If a <pre> block is found, it is not converted into a Markdown code block. Example:

<pre>
First development stream
 - 1.0.0

Second development stream
 - 1.0.100 (indicates a bug fix)
 - 1.1.0 (a new API has been introduced)
 The plug-in ships as 1.1.0
</pre> 

Do I need to use a code rule for this, or is this a missing feature / configuration?

Converting an <img> to md style

When trying to use this package for images, it always gives me a text instead of rendering the image,

For example:

If the markdown data was:
"![Sample Image](https://github.githubassets.com/images/modules/logos_page/GitHub-Logo.png)", It will perfectly show an image

but when trying to use an or even converting an already markdown style,

Example: html2md.convert("![Sample Image](https://github.githubassets.com/images/modules/logos_page/GitHub-Logo.png)")<

It will just show it as a text instead of loading the image

Error result if <br> tag is contained

<i>Tu regere imperio populos, Romane, memento:<br/>
        Hae tibi erunt artes, pacisque imponere morem,<br/>
        Parcere subiectis, et debellare superbos.</i>

result:

_Tu regere imperio populos, Romane, memento:  
Hae tibi erunt artes, pacisque imponere morem,  
Parcere subiectis, et debellare superbos._

expect:

_Tu regere imperio populos, Romane, memento:  _
_Hae tibi erunt artes, pacisque imponere morem,  _
_Parcere subiectis, et debellare superbos._

Fenced code blocks with multiple children (spans from highligters) not converted

Hi, first of all many thanks for your work, I'm using this library in my android app and it's working really well!

Unfortunately, a user of the app opened an issue because some code blocks in a webpage don't get converted: only the first line is displayed.

That specific webpage was created with Jekyll from a markdown source, so I'm expecting that many other websites could be affected.

This is an excerpt from the page:

<div class="language-python highlighter-rouge">
  <div class="highlight">
<pre class="highlight"><code><span class="c1">#! /usr/bin/env python3
</span>
<span class="kn">import</span> <span class="nn">tika</span>
<span class="kn">from</span> <span class="nn">tika</span> <span class="kn">import</span> <span class="n">parser</span>

<span class="n">fileIn</span> <span class="o">=</span> <span class="s">"berk011veel01_01.epub"</span>
<span class="n">fileOut</span> <span class="o">=</span> <span class="s">"berk011veel01_01.txt"</span>

<span class="n">parsed</span> <span class="o">=</span> <span class="n">parser</span><span class="p">.</span><span class="n">from_file</span><span class="p">(</span><span class="n">fileIn</span><span class="p">)</span>
<span class="n">content</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s">"content"</span><span class="p">]</span>

<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fileOut</span><span class="p">,</span> <span class="s">'w'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s">'utf-8'</span><span class="p">)</span> <span class="k">as</span> <span class="n">fout</span><span class="p">:</span>
    <span class="n">fout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</code></pre>
  </div>
</div>

The issue is at this line: only the first child of the code tag is read.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.