Add an `enableTagfilter` option to `HtmlRenderer` to eanble GFM `tagfilter` extension (dart-lang/markdown#447)
* Add GFM Disallowed Raw HTML support
* Fix errors caused by rebase.
* Update CHANGELOG.md
diff --git a/pkgs/markdown/CHANGELOG.md b/pkgs/markdown/CHANGELOG.md
index 47cb1a5..469bf8b 100644
--- a/pkgs/markdown/CHANGELOG.md
+++ b/pkgs/markdown/CHANGELOG.md
@@ -10,6 +10,8 @@
* **Breaking change**: Change the `lines` properties of type `List<String>` to
`List<Line>`.
* Add a new syntax `HtmlBlockSyntax` to parse HTML blocks.
+* Add an `enableTagfilter` option to `HtmlRenderer` to eanble GFM `tagfilter`
+ extension.
* Add a new syntax `DecodeHtmlSyntax` to decode HTML entity and numeric
character references.
* Add a new syntax `SoftLineBreakSyntax` to remove the single space before the
diff --git a/pkgs/markdown/lib/src/html_renderer.dart b/pkgs/markdown/lib/src/html_renderer.dart
index 6ff803d..404d870 100644
--- a/pkgs/markdown/lib/src/html_renderer.dart
+++ b/pkgs/markdown/lib/src/html_renderer.dart
@@ -20,6 +20,7 @@
Resolver? imageLinkResolver,
bool inlineOnly = false,
bool encodeHtml = true,
+ bool enableTagfilter = false,
bool withDefaultBlockSyntaxes = true,
bool withDefaultInlineSyntaxes = true,
}) {
@@ -38,11 +39,14 @@
final nodes = document.parse(markdown);
- return '${renderToHtml(nodes)}\n';
+ return '${renderToHtml(nodes, enableTagfilter: enableTagfilter)}\n';
}
/// Renders [nodes] to HTML.
-String renderToHtml(List<Node> nodes) => HtmlRenderer().render(nodes);
+String renderToHtml(List<Node> nodes, {bool enableTagfilter = false}) =>
+ HtmlRenderer(
+ enableTagfilter: enableTagfilter,
+ ).render(nodes);
const _blockTags = [
'blockquote',
@@ -89,8 +93,11 @@
final _elementStack = <Element>[];
String? _lastVisitedTag;
+ final bool _tagfilterEnabled;
- HtmlRenderer();
+ HtmlRenderer({
+ bool enableTagfilter = false,
+ }) : _tagfilterEnabled = enableTagfilter;
String render(List<Node> nodes) {
buffer = StringBuffer();
@@ -106,6 +113,10 @@
@override
void visitText(Text text) {
var content = text.textContent;
+
+ if (_tagfilterEnabled) {
+ content = _filterTags(content);
+ }
if (const ['br', 'p', 'li'].contains(_lastVisitedTag)) {
final lines = LineSplitter.split(content);
content = content.contains('<pre>')
@@ -190,4 +201,18 @@
uniqueIds.add(suffixedId);
return suffixedId;
}
+
+ /// Filters some particular tags, see:
+ /// https://github.github.com/gfm/#disallowed-raw-html-extension-
+ // As said in the specification, this process should happen when rendering
+ // HTML output, so there should not be a dedicated syntax for this extension.
+ String _filterTags(String content) => content.replaceAll(
+ RegExp(
+ '<(?=(?:'
+ 'title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext'
+ ')>)',
+ caseSensitive: false,
+ multiLine: true,
+ ),
+ '<');
}
diff --git a/pkgs/markdown/test/gfm/disallowed_raw_html_extension.unit b/pkgs/markdown/test/gfm/disallowed_raw_html_extension.unit
index cef4e62..f39b4b7 100644
--- a/pkgs/markdown/test/gfm/disallowed_raw_html_extension.unit
+++ b/pkgs/markdown/test/gfm/disallowed_raw_html_extension.unit
@@ -5,6 +5,6 @@
<xmp> is disallowed. <XMP> is also disallowed.
</blockquote>
<<<
-<p><strong> <title> <style> <em></p><blockquote>
-<xmp> is disallowed. <XMP> is also disallowed.
+<p><strong> <title> <style> <em></p><blockquote>
+<xmp> is disallowed. <XMP> is also disallowed.
</blockquote>
diff --git a/pkgs/markdown/test/util.dart b/pkgs/markdown/test/util.dart
index fba598d..2c2cb88 100644
--- a/pkgs/markdown/test/util.dart
+++ b/pkgs/markdown/test/util.dart
@@ -17,6 +17,7 @@
final inlineSyntaxes = <InlineSyntax>[];
final blockSyntaxes = <BlockSyntax>[];
+ var enableTagfilter = false;
if (dataCase.file.endsWith('_extension')) {
final extension = dataCase.file.substring(
@@ -34,7 +35,7 @@
blockSyntaxes.add(const TableSyntax());
break;
case 'disallowed_raw_html':
- // TODO(Zhiguang): https://github.com/dart-lang/markdown/pull/447
+ enableTagfilter = true;
break;
default:
throw UnimplementedError('Unimplemented extension "$extension"');
@@ -48,6 +49,7 @@
extensionSet: extensionSet,
inlineSyntaxes: inlineSyntaxes,
blockSyntaxes: blockSyntaxes,
+ enableTagfilter: enableTagfilter,
);
}
}
@@ -81,6 +83,7 @@
Resolver? linkResolver,
Resolver? imageLinkResolver,
bool inlineOnly = false,
+ bool enableTagfilter = false,
}) {
test(description, () {
final result = markdownToHtml(
@@ -91,6 +94,7 @@
linkResolver: linkResolver,
imageLinkResolver: imageLinkResolver,
inlineOnly: inlineOnly,
+ enableTagfilter: enableTagfilter,
);
markdownPrintOnFailure(markdown, html, result);
diff --git a/pkgs/markdown/tool/stats_lib.dart b/pkgs/markdown/tool/stats_lib.dart
index c1298f1..a747216 100644
--- a/pkgs/markdown/tool/stats_lib.dart
+++ b/pkgs/markdown/tool/stats_lib.dart
@@ -128,6 +128,8 @@
bool verboseLooseMatch = false,
Set<String> extensions = const {},
}) {
+ var enabletagfilter = false;
+
String output;
final inlineSyntaxes = <InlineSyntax>[];
final blockSyntaxes = <BlockSyntax>[];
@@ -144,7 +146,7 @@
blockSyntaxes.add(const TableSyntax());
break;
case 'tagfilter':
- // TODO(Zhiguang): https://github.com/dart-lang/markdown/pull/447
+ enabletagfilter = true;
break;
default:
throw UnimplementedError('Unimplemented extension "$extension"');
@@ -156,6 +158,7 @@
testCase.markdown,
inlineSyntaxes: inlineSyntaxes,
blockSyntaxes: blockSyntaxes,
+ enableTagfilter: enabletagfilter,
);
} catch (err, stackTrace) {
if (throwOnError) {