Skip to content

Commit

Permalink
Support inline markdown shortcuts
Browse files Browse the repository at this point in the history
Fixes #355
  • Loading branch information
Amir-P committed Jun 10, 2024
1 parent 178d2bb commit 225f476
Showing 1 changed file with 59 additions and 3 deletions.
62 changes: 59 additions & 3 deletions packages/fleather/lib/src/widgets/autoformats.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class AutoFormats {
factory AutoFormats.fallback() {
return AutoFormats(autoFormats: [
const _AutoFormatLinks(),
const _MarkdownShortCuts(),
const _MarkdownInlineShortcuts(),
const _MarkdownLineShortcuts(),
const _AutoTextDirection(),
]);
}
Expand Down Expand Up @@ -165,8 +166,63 @@ class _AutoFormatLinks extends AutoFormat {
}
}

// Replaces certain Markdown shortcuts with actual inline styles.
class _MarkdownInlineShortcuts extends AutoFormat {
static final rules = <String, ParchmentAttribute>{
'**': ParchmentAttribute.bold,
'*': ParchmentAttribute.italic,
'`': ParchmentAttribute.inlineCode,
'~~': ParchmentAttribute.strikethrough,
};

const _MarkdownInlineShortcuts();

@override
AutoFormatResult? apply(
ParchmentDocument document, int position, String data) {
if (data != ' ' && data != '\n') return null;

final documentDelta = document.toDelta();
final iter = DeltaIterator(documentDelta);
final previous = iter.skip(position);
// No previous operation means nothing to analyze.
if (previous == null || previous.data is! String) return null;
final previousText = previous.data as String;
if (previousText.isEmpty) return null;

final candidate = previousText.split('\n').last;

for (final String rule in rules.keys) {
if (candidate.endsWith(rule)) {
final lastOffset = candidate.lastIndexOf(rule);
final startOffset =
candidate.substring(0, lastOffset).lastIndexOf(rule);
final contentLength = lastOffset - startOffset - rule.length;
if (startOffset != -1 && contentLength > 0) {
final change = Delta()
..retain(position - candidate.length + startOffset)
..delete(rule.length)
..retain(contentLength, {...rules[rule]!.toJson()})
..delete(rule.length);
final undo = change.invert(documentDelta);
document.compose(change, ChangeSource.local);
return AutoFormatResult(

Check warning on line 209 in packages/fleather/lib/src/widgets/autoformats.dart

View check run for this annotation

Codecov / codecov/patch

packages/fleather/lib/src/widgets/autoformats.dart#L202-L209

Added lines #L202 - L209 were not covered by tests
change: change,
undo: undo,
undoPositionCandidate: position - (rule.length * 2),
selection: TextSelection.collapsed(offset: position - rule.length),
undoSelection: TextSelection.collapsed(offset: position + 1),

Check warning on line 214 in packages/fleather/lib/src/widgets/autoformats.dart

View check run for this annotation

Codecov / codecov/patch

packages/fleather/lib/src/widgets/autoformats.dart#L212-L214

Added lines #L212 - L214 were not covered by tests
);
}
}
}

return null;
}
}

// Replaces certain Markdown shortcuts with actual line or block styles.
class _MarkdownShortCuts extends AutoFormat {
class _MarkdownLineShortcuts extends AutoFormat {
static final rules = <String, ParchmentAttribute>{
'-': ParchmentAttribute.block.bulletList,
'*': ParchmentAttribute.block.bulletList,
Expand All @@ -180,7 +236,7 @@ class _MarkdownShortCuts extends AutoFormat {
'###': ParchmentAttribute.h3,
};

const _MarkdownShortCuts();
const _MarkdownLineShortcuts();

String? _getLinePrefix(DeltaIterator iter, int index) {
final prefixOps = skipToLineAt(iter, index);
Expand Down

0 comments on commit 225f476

Please sign in to comment.