p-hatan/ mirror

pub repository

mirror.p-hatan.ir

characters

1.1.0-nullsafety.4

String replacement with operations that are Unicode/grapheme cluster aware.

Download archive

Readme

pub package Build Status

Characters are strings viewed as sequences of user-perceived characters, also known as Unicode (extended) grapheme clusters.

The Characters class allows access to the individual characters of a string, and a way to navigate back and forth between them using a CharacterRange.

Unicode characters and representations

There is no such thing as plain text.

Computers only know numbers, so any "text" on a computer is represented by numbers, which are again stored as bytes in memory.

The meaning of those bytes are provided by layers of interpretation, building up to the glyphs that the computer displays on the screen.

Abstraction Dart Type Usage Example
Bytes ByteBuffer,Uint8List Physical layout: Memory or network communication. file.readAsBytesSync()
Code units Uint8List (UTF‑8)Uint16List, String (UTF‑16) Standard formats for encoding code points in memory.Stored in memory using one (UTF‑8) or more (UTF‑16) bytes. One or more code units encode a code point. string.codeUnitsstring.codeUnitAt(index)utf8.encode(string)
Code points Runes The Unicode unit of meaning. string.runes
Grapheme Clusters Characters Human perceived character. One or more code points. string.characters
Glyphs Visual rendering of grapheme clusters. print(string)

A Dart String is a sequence of UTF-16 code units, just like strings in JavaScript and Java. The runtime system decides on the underlying physical representation.

That makes plain strings inadequate when needing to manipulate the text that a user is viewing, or entering, because string operations are not working at the grapheme cluster level.

For example, to abbreviate a text to, say, the 15 first characters or glyphs, an string like "A 🇬🇧 text in English" should abbreviate to "A 🇬🇧 text in Eng… when counting characters, but will become "A 🇬🇧 text in …" if counting code units using String operations.

Whenever you need to manipulate strings at the character level, you should be using the Characters type, not the methods of the String class.

The Characters class

The Characters class exposes a string as a sequence of grapheme clusters. All operations on Characters operate on entire grapheme clusters, so it removes the risk of splitting combined characters or emojis that are inherent in the code-unit based String operations.

You can get a Characters object for a string using either the constructor Characters(string) or the extension getter string.characters.

At its core, the class is an Iterable<String> where the element strings are single grapheme clusters. This allows sequential access to the individual grapheme clusters of the original string.

On top of that, there are operations mirroring the operations of String that are not index, code-unit or code-point based, like startsWith or replaceAll. There are some differences between these and the String operations. For example the replace methods only accept characters as pattern. Regular expressions are not grapheme cluster aware, so they cannot be used safely on a sequence of characters.

Grapheme clusters have varying length in the underlying representation, so operations on a Characters sequence cannot be index based. Instead the CharacterRange iterator provided by Characters.iterator has been greatly enhanced. It can move both forwards and backwards, and it can span a range of grapheme cluster. Most operations that can be performed on a full Characters can also be performed on the grapheme clusters in the range of a CharacterRange. The range can be contracted, expanded or moved in various ways, not restricted to using moveNext, to move to the next grapheme cluster.

Example:

// Using String indices.
String firstTagString(String source) {
  var start = string.indexOf("<") + 1;
  if (start > 0) {
    var end = string.indexOf(">", start);
    if (end >= 0) {
	    return string.substring(start, end);
    }
  }
  return null;
}

// Using CharacterRange operations.
Characters firstTagCharacters(Characters source) =>
  var range = source.findFirst("<".characters);
  if (range != null && range.moveUntil(">".characters)) {
    return range.currentCharacters;
  }
  return null;
}
Changelog

1.1.0-nullsafety.4

  • Allow the 2.12 dev SDKs.

1.1.0-nullsafety.3

  • Added stringBeforeLength and stringAfterLength to CharacterRange.
  • Added CharacterRange.at constructor.
  • Added getRange(start, end) and characterAt(pos) to Characters as alternative to .take(end).skip(start) and getRange(pos, pos + 1).
  • Change some positional parameter names from other to characters.
  • Allow the 2.10 stable SDK.

1.1.0-nullsafety.2

  • Update for the 2.10 dev sdk.

1.1.0-nullsafety.1

  • Allow the <=2.9.10 stable sdks.

1.1.0-nullsafety

  • Make package null safe.

1.0.0

  • Core APIs deemed stable; package version set to 1.0.0.
  • Added split methods on Characters and CharacterRange.

0.5.0

  • Change [codeUnits] getter to [utf16CodeUnits] which returns an iterable. This avoids leaking that the underlying string has efficient UTF-16 code unit access in the API, and allows the same interface to be just as efficiently implemented on top of UTF-8.

0.4.0

  • Added an extension method on String to allow easy access to the Characters of the string:

    print('The first character is: ' + myString.characters.first)
    
  • Updated Dart SDK dependency to Dart 2.6.0

0.3.1

  • Added small example in example/main.dart
  • Enabled pedantic lints and updated code to resolve issues.

0.3.0

  • Updated API which does not expose the underlying string indices.

0.1.0

  • Initial release

Installing

export PUB_HOSTED_URL=https://pub.mirror.p-hatan.ir
flutter pub add characters
pubspec.yaml
name: characters
version: 1.1.0-nullsafety.4
description: String replacement with operations that are Unicode/grapheme cluster aware.
homepage: https://www.github.com/dart-lang/characters

environment:
  # This must remain a tight constraint until nnbd is stable
  sdk: '>=2.10.0-110 <2.12.0'

dev_dependencies:
  test: ^1.16.0-nullsafety
  pedantic: ^1.10.0-nullsafety

Version history

VersionPublishedArchiveSHA-256
0.3.02019-10-22T14:41:52.158371ZDownload6c10f16149700c156101a209692575000a7c817c20bf5417f48d3131be426667
0.3.12019-10-25T12:36:45.024759ZDownloadfdb489af03e0b0a4e6ee7bd3d6206c23301966db356f91a33f71bf5832762972
0.4.02019-11-13T12:54:17.392008ZDownloade1e28342064600ccaef106a329d60a5f7a628b03b8b7e6929d542ee1c37177f2
0.5.02019-12-05T13:35:18.391622ZDownload3f95b5451198500c0290de5906f46d8789c79d7d171d9ffc8d529dd76e524863
1.0.02020-06-09T17:50:33.250666ZDownload8df5ffb52bac8bd9bee7380c9815a74528b07dbb7a8c3dff4e7a3657ad8f5077
1.1.0-nullsafety2020-07-08T19:57:37.041999ZDownload44dadb8331561d0ed4b8b7fd5641abad6969695eccaf9c7556e476ec4207d0ba
1.1.0-nullsafety.12020-07-17T16:46:45.923744ZDownloadd4c5e8e8d70b2382c85dadc1adba50e07c2e290f6bba4e590bce5a064aa278ac
1.1.0-nullsafety.22020-07-22T14:25:10.648861ZDownload0732c7709d6203620d91b7ef90d4b5085453704a8f28eaf836673578608adf16
1.1.0-nullsafety.32020-09-22T17:09:44.119944ZDownload43012c25f170e6547436e0d52dfa012a5951a85c6a7923f003c5cb9b8a8cb4a7
1.1.0-nullsafety.42020-10-22T17:00:58.426891ZDownloadd97fe005f0cbb44b8c0fffcd247631d28f2329d73d704b727eb83a3ec68f2933
1.1.0-nullsafety.52020-11-03T19:13:11.247298ZDownload1bfe74de3851aacdafc0bfa347d71d9943a2a118982c3b861e77ddf25876cdd6
1.1.02021-02-02T19:38:26.068937ZDownload9a462645329872f11cf4709edf4ae7b092bf60d3d6b6a072a39ab18311e04bb7
1.2.02021-09-13T12:49:07.342790ZDownloadd5be1994ae6e849331a4fb182450792ad772f375f973fdfd61d6e008766b65cc
1.2.12022-05-04T16:47:08.918941ZDownloade6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
1.3.02023-02-17T01:00:38.920141ZDownload04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605
1.3.12024-10-16T08:50:03.548590ZDownload81269c8d3f45541082bfbb117bbc962cfc68b5197eb4c705a00db4ddf394e1c1
1.4.02024-12-11T14:43:55.208664ZDownloadf71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
1.4.12025-06-25T15:56:32.563783ZDownloadfaf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b

Dependencies

No direct dependencies declared.