Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkgs/markdown/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## 7.3.1-wip

* Preserve metadata passed to fenced code blocks as
`data-metadata` on the created `pre` element.
* Update the README link to the markdown playground
(https://dart-lang.github.io/tools).
* Update `package:web` API references in the example.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ class FencedCodeBlockSyntax extends BlockSyntax {

@override
Node parse(BlockParser parser) {
final openingFence = _FenceMatch.fromMatch(pattern.firstMatch(
escapePunctuation(parser.current.content),
)!);
final openingFence = _FenceMatch.fromMatch(
pattern.firstMatch(escapePunctuation(parser.current.content))!,
);

var text = parseChildLines(
parser,
Expand All @@ -38,16 +38,27 @@ class FencedCodeBlockSyntax extends BlockSyntax {
text = '$text\n';
}

final (languageString, metadataString) = openingFence.languageAndMetadata;

final code = Element.text('code', text);
if (openingFence.hasLanguage) {
var language = decodeHtmlCharacters(openingFence.language);
if (languageString != null) {
var language = decodeHtmlCharacters(languageString);
if (parser.document.encodeHtml) {
language = escapeHtmlAttribute(language);
}
code.attributes['class'] = 'language-$language';
}

return Element('pre', [code]);
final pre = Element('pre', [code]);
if (metadataString != null) {
var metadata = decodeHtmlCharacters(metadataString);
if (parser.document.encodeHtml) {
metadata = escapeHtmlAttribute(metadata);
}
pre.attributes['data-metadata'] = metadata;
}

return pre;
}

String _removeIndentation(String content, int length) {
Expand Down Expand Up @@ -130,12 +141,30 @@ class _FenceMatch {
// https://spec.commonmark.org/0.30/#info-string.
final String info;

// The first word of the info string is typically used to specify the language
// of the code sample,
// https://spec.commonmark.org/0.30/#example-143.
String get language => info.split(' ').first;
/// Returns the language and remaining metadata from the [info] string.
///
/// The language is the first word of the info string,
/// to match the (unspecified, but typical) behavior of CommonMark parsers,
/// as suggested in https://spec.commonmark.org/0.30/#example-143.
///
/// The metadata is any remaining part of the info string after the language.
(String? language, String? metadata) get languageAndMetadata {
if (info.isEmpty) {
return (null, null);
}

bool get hasInfo => info.isNotEmpty;
// We assume the info string is trimmed already.
final firstSpaceIndex = info.indexOf(' ');
if (firstSpaceIndex == -1) {
// If there is no space, the whole string is the language.
return (info, null);
}

return (
info.substring(0, firstSpaceIndex),
info.substring(firstSpaceIndex + 1),
);
}

bool get hasLanguage => language.isNotEmpty;
bool get hasInfo => info.isNotEmpty;
}
4 changes: 2 additions & 2 deletions pkgs/markdown/test/common_mark/fenced_code_blocks.unit
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def foo(x)
end
~~~~~~~
<<<
<pre><code class="language-ruby">def foo(x)
<pre data-metadata="startline=3 $%@#$"><code class="language-ruby">def foo(x)
return 3
end
</code></pre>
Expand All @@ -234,7 +234,7 @@ foo</p>
foo
~~~
<<<
<pre><code class="language-aa">foo
<pre data-metadata="``` ~~~"><code class="language-aa">foo
</code></pre>
>>> Fenced code blocks - 147
```
Expand Down
4 changes: 2 additions & 2 deletions pkgs/markdown/test/gfm/fenced_code_blocks.unit
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def foo(x)
end
~~~~~~~
<<<
<pre><code class="language-ruby">def foo(x)
<pre data-metadata="startline=3 $%@#$"><code class="language-ruby">def foo(x)
return 3
end
</code></pre>
Expand All @@ -234,7 +234,7 @@ foo</p>
foo
~~~
<<<
<pre><code class="language-aa">foo
<pre data-metadata="``` ~~~"><code class="language-aa">foo
</code></pre>
>>> Fenced code blocks - 117
```
Expand Down
24 changes: 24 additions & 0 deletions pkgs/markdown/test/original/fenced_code_block.unit
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,27 @@
<<<
<pre><code>'foo'
</code></pre>
>>> with basic metadata string
```dart meta
code
```

<<<
<pre data-metadata="meta"><code class="language-dart">code
</code></pre>
>>> with characters to escape
```dart title="main.dart"
code
```

<<<
<pre data-metadata="title=&quot;main.dart&quot;"><code class="language-dart">code
</code></pre>
>>> with HTML character reference
```dart &#124;
code
```

<<<
<pre data-metadata="|"><code class="language-dart">code
</code></pre>