1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! `evfmt` is both a command-line formatter and a Rust library for
//! normalizing text/emoji variation selectors.
//!
//! Most callers will want [`format_text`] together with [`Policy`].
//!
//! # Stability
//!
//! This library API is experimental. `evfmt` follows
//! [Cargo's SemVer compatibility conventions][cargo-semver].
//!
//! [cargo-semver]: https://doc.rust-lang.org/cargo/reference/semver.html
//!
//! # Examples
//!
//! Use [`format_text`] for whole-input canonicalization under one [`Policy`].
//! In the example below, `#\u{FE0E}` is NUMBER SIGN followed by VS15, and
//! `\u{00A9}` is a bare COPYRIGHT SIGN. Under the default policy,
//! `#\u{FE0E}` loses the redundant variation selector, while bare `\u{00A9}` is
//! canonicalized to `\u{00A9}\u{FE0E}` because it is text-default.
//!
//! ```rust
//! use evfmt::{FormatResult, Policy, format_text};
//!
//! let policy = Policy::default();
//!
//! assert_eq!(
//! format_text("#\u{FE0E}", &policy),
//! FormatResult::Changed("#".to_owned())
//! );
//! assert_eq!(
//! format_text("\u{00A9}", &policy),
//! FormatResult::Changed("\u{00A9}\u{FE0E}".to_owned())
//! );
//! assert_eq!(format_text("\u{2728}", &policy), FormatResult::Unchanged);
//! ```
//!
//! For interactive repair or editor integrations, scan the input and then work
//! item-by-item. In the next example, `A\u{FE0F}` contains an unsanctioned
//! presentation selector after `A`, and the caller chooses to apply the
//! formatter's fixed canonical replacement.
//! For the built-in `evfmt` decisions, callers can build repaired output from
//! the original scanned items without rescanning after each selected decision.
//! Walk the original items in order, keeping `item.raw` for unchanged items and
//! substituting the selected canonical replacement for findings.
//!
//! ```rust
//! use evfmt::{Policy, ScanKind, scan};
//! use evfmt::analysis::analyze_scan_item;
//!
//! let policy = Policy::default();
//! let input = "A\u{FE0F}";
//!
//! let mut items = scan(input);
//! assert!(matches!(items.next().unwrap().kind, ScanKind::Passthrough));
//! let item = items.next().unwrap();
//! assert!(matches!(
//! item.kind,
//! ScanKind::UnsanctionedPresentationSelectors(_)
//! ));
//!
//! let finding = analyze_scan_item(&item, &policy).unwrap();
//! let non_canonicality = finding.non_canonicality();
//! assert!(!non_canonicality.is_empty());
//! assert_eq!(non_canonicality.unsanctioned_selectors, 1);
//! assert_eq!(finding.default_decisions().len(), 0);
//!
//! let repaired = finding.canonical_replacement_with_decisions(&[]).unwrap();
//! assert_eq!(repaired, "");
//! ```
//!
//! The [`mod@analysis`] API is the usual entry point for interactive fixing.
//! It analyzes scanned items under the supplied [`Policy`] and returns the
//! whole-item canonical replacement available for each non-canonical finding.
//! Ambiguous selector slots are represented as source-order presentation
//! decisions; fixed repairs have no decisions and use the empty decision vector.
//!
//! Custom policies can be built from [`policy_key_set`] policy key sets. In this example,
//! a singleton policy key for `\u{00A9}` allows bare COPYRIGHT SIGN to remain bare.
//!
//! ```rust
//! use evfmt::{Policy, PolicyKeySet, format_text, policy_key_set};
//!
//! let ascii_and_copyright = policy_key_set::ASCII | PolicyKeySet::singleton('\u{00A9}');
//! let policy = Policy::default().with_prefer_bare(ascii_and_copyright);
//!
//! let formatted = format_text("\u{00A9}", &policy);
//! assert_eq!(formatted, evfmt::FormatResult::Unchanged);
//! ```
//!
//! Here "variation-sequence character" means a character listed in Unicode's
//! `emoji-variation-sequences.txt`.
//!
//! Public module boundaries:
//!
//! - the crate root is the high-level API: whole-input formatting and
//! convenience analysis helpers
//! - [`policy`] defines formatter policy configuration
//! - [`formatter`] owns whole-text formatting
//! - [`mod@analysis`] analyzes scanned items under policy and reports
//! non-canonicality plus available replacements
//! - [`presentation`] defines the text/emoji presentation decision shared by
//! scanning and analysis
//! - [`scanner`] owns structural tokenization into singletons, keycaps, ZWJ
//! chains, standalone variation selector runs, and passthrough slices
//! - [`policy_key_set`] defines the typed `PolicyKeySet` model used by the library
//! policy API
pub use ;
pub use ;
pub use Policy;
pub use PolicyKeySet;
pub use Presentation;
pub use ;