Skip to content

Commit

Permalink
Changed linkification on paste to match URL parsing within the linkif…
Browse files Browse the repository at this point in the history
…ication reaction (Resolves #2031) (#2045)
  • Loading branch information
matthew-carroll committed May 28, 2024
1 parent 1d6245b commit c6364ff
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 77 deletions.
19 changes: 14 additions & 5 deletions super_editor/lib/src/default_editor/common_editor_operations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import 'dart:ui';
import 'package:attributed_text/attributed_text.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:linkify/linkify.dart';
import 'package:super_editor/src/core/document.dart';
import 'package:super_editor/src/core/document_composer.dart';
import 'package:super_editor/src/core/document_layout.dart';
import 'package:super_editor/src/core/document_selection.dart';
import 'package:super_editor/src/core/editor.dart';
import 'package:super_editor/src/default_editor/default_document_editor_reactions.dart';
import 'package:super_editor/src/default_editor/list_items.dart';
import 'package:super_editor/src/default_editor/paragraph.dart';
import 'package:super_editor/src/default_editor/selection_upstream_downstream.dart';
Expand Down Expand Up @@ -2381,11 +2383,18 @@ class PasteEditorCommand implements EditCommand {

for (final wordBoundary in wordBoundaries) {
final word = wordBoundary.textInside(pastedText);
final link = Uri.tryParse(word);

if (link != null && link.hasScheme && link.hasAuthority) {
// Valid url. Apply [LinkAttribution] to the url
final linkAttribution = LinkAttribution.fromUri(link);
final extractedLinks = linkify(
word,
options: const LinkifyOptions(
humanize: false,
looseUrl: true,
),
);
final int linkCount = extractedLinks.fold(0, (value, element) => element is UrlElement ? value + 1 : value);
if (linkCount == 1) {
// The word is a single URL. Linkify it.
final uri = parseLink(word);

final startOffset = wordBoundary.start;
// -1 because TextPosition's offset indexes the character after the
Expand All @@ -2394,7 +2403,7 @@ class PasteEditorCommand implements EditCommand {

// Add link attribution.
linkAttributionSpans.addAttribution(
newAttribution: linkAttribution,
newAttribution: LinkAttribution.fromUri(uri),
start: startOffset,
end: endOffset,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ class LinkifyReaction implements EditReaction {
final int linkCount = extractedLinks.fold(0, (value, element) => element is UrlElement ? value + 1 : value);
if (linkCount == 1) {
// The word is a single URL. Linkify it.
final uri = _parseLink(word);
final uri = parseLink(word);

text.addAttribution(
LinkAttribution.fromUri(uri),
Expand Down Expand Up @@ -799,21 +799,24 @@ class LinkifyReaction implements EditReaction {
if (updatePolicy == LinkUpdatePolicy.update) {
changedNodeText.addAttribution(
LinkAttribution.fromUri(
_parseLink(changedNodeText.text.substring(rangeToUpdate.start, rangeToUpdate.end + 1)),
parseLink(changedNodeText.text.substring(rangeToUpdate.start, rangeToUpdate.end + 1)),
),
rangeToUpdate,
);
}
}
}

/// Parses the [text] as [Uri], prepending "https://" if it doesn't start
/// with "http://" or "https://".
Uri _parseLink(String text) {
final uri = text.startsWith("http://") || text.startsWith("https://") //
? Uri.parse(text)
: Uri.parse("https://$text");
return uri;
}
/// Parses the [text] as [Uri], prepending "https://" if it doesn't start
/// with "http://" or "https://".
// TODO: Make this private again. It was private, but we have some split linkification between the reaction
// and the paste behavior in common_editor_operations. Once we create a way for reactions to identify
// paste behaviors, move the paste linkification into the linkify reaction and make this private again.
Uri parseLink(String text) {
final uri = text.startsWith("http://") || text.startsWith("https://") //
? Uri.parse(text)
: Uri.parse("https://$text");
return uri;
}

/// Configuration for the action that should happen when a text containing
Expand Down
Loading

0 comments on commit c6364ff

Please sign in to comment.