Rich text editor for Flutter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.0 KiB

2 years ago
import 'package:charcode/charcode.dart';
import 'package:markdown/markdown.dart';
import '../../../flutter_quill.dart' hide Node;
2 years ago
/// Parses markdown table and saves the table markdown content into the element attributes.
class EmbeddableTableSyntax extends BlockSyntax {
/// @nodoc
const EmbeddableTableSyntax();
static const _base = TableSyntax();
@override
bool canEndBlock(BlockParser parser) => false;
@override
RegExp get pattern => _base.pattern;
@override
bool canParse(BlockParser parser) => _base.canParse(parser);
/// Parses a table into its three parts:
///
/// * a head row of head cells (`<th>` cells)
/// * a divider of hyphens and pipes (not rendered)
/// * many body rows of body cells (`<td>` cells)
@override
Node? parse(BlockParser parser) {
final columnCount = _columnCount(parser.next!.content);
final headCells = _columnCount(parser.current.content);
final valBuf =
StringBuffer('${parser.current.content}\n${parser.next!.content}');
parser.advance();
if (columnCount != headCells) {
return null;
}
// advance header and divider of hyphens.
parser.advance();
while (!parser.isDone && !BlockSyntax.isAtBlockEnd(parser)) {
valBuf.write('\n${parser.current.content}');
parser.advance();
}
return Element.empty(EmbeddableTable.tableType)
..attributes['data'] = valBuf.toString();
}
int _columnCount(String line) {
final startIndex = _walkPastOpeningPipe(line);
var endIndex = line.length - 1;
while (endIndex > 0) {
final ch = line.codeUnitAt(endIndex);
if (ch == $pipe) {
endIndex--;
break;
}
if (ch != $space && ch != $tab) {
break;
}
endIndex--;
}
return line.substring(startIndex, endIndex + 1).split('|').length;
}
int _walkPastWhitespace(String line, int index) {
while (index < line.length) {
final ch = line.codeUnitAt(index);
if (ch != $space && ch != $tab) {
break;
}
//ignore: parameter_assignments
index++;
}
return index;
}
int _walkPastOpeningPipe(String line) {
var index = 0;
while (index < line.length) {
final ch = line.codeUnitAt(index);
if (ch == $pipe) {
index++;
index = _walkPastWhitespace(line, index);
}
if (ch != $space && ch != $tab) {
// No leading pipe.
break;
}
index++;
}
return index;
}
}
/// An [Embeddable] table that can used to render a table in quill_editor
class EmbeddableTable extends BlockEmbed {
/// @nodoc
EmbeddableTable(String data) : super(tableType, data);
/// [Embeddable] type
static const tableType = 'x-embed-table';
/// Create from markdown.
//ignore: prefer_constructors_over_static_methods
static EmbeddableTable fromMdSyntax(Map<String, String> attributes) =>
EmbeddableTable(attributes['data']!);
/// Outputs table markdown to output.
static void toMdSyntax(Embed embed, StringSink out) {
out
..writeln(embed.value.data)
..writeln();
}
}