6d892629c526e92d131c559c8e465aafc4503c1d
[string-lerp.git] / README.md
1 # String Lerp
2
3 This is a library to linearly interpolate between two string values,
4 that is, progressively turn one string into another. It implements
5 several ways to do this, and can automatically pick the best one based
6 on the strings given to it.
7
8 For example, it knows:
9
10 * "explore" is between "implore" and "explode".
11 * Or conversely, "implode" between "explode" and "implore".
12 * "chicken wing" and "buffalo wing" are actually the same "wing".
13 * Likewise, "apple core" and "core dump" can keep the "core".
14 * 1/3 of the way from "0%" to "100%" is "33%".
15 * Halfway between rgb(255, 0, 0) and rgb(0, 0, 255) is rgb(128, 0, 128).
16 (Well, it's good at strings, not color science.)
17
18 To try more, open up [demo.html] in your browser.
19
20 ## Setting Up
21
22 Include the following in your HTML:
23
24 <script type="text/javascript" src="string-lerp.js"></script>
25
26 Then, you can use `window.stringLerp` (or just `stringLerp`).
27
28 Or if you're using Node or some other non-browser whatever,
29
30 var stringLerp = require("./string-lerp");
31
32 If you want a minified version, at a shell run
33
34 $ make ugly
35
36 If you think something's wrong, or make changes, run
37
38 $ make check
39
40 (Running these will also download modules from [NPM].)
41
42 ## API
43
44 ### stringLerp.lerp(a, b, p)
45
46 Interpolate between strings a and b, given a parameter p.
47
48 This automatically picks the best interpolator based on the strings
49 provided. If the strings are identical aside from numbers in them,
50 they are passed through `numericLerp`.
51
52 If the strings are not numbers and short, they are passed through
53 `diffLerp`.
54
55 Otherwise, they are passed through `fastLerp`.
56
57
58 ### stringLerp.numericLerp(a, b, p)
59
60 Lerp all the numbers in the string from their values in `a` to their
61 values in `b`.
62
63 Numbers may have a leading `-` and a single `.` to mark the decimal
64 point, but something must be after the `.`. If both of the numbers in
65 a pair are integers, the result is clamped to an integer.
66
67 For example, `numericLerp("0.0", "100", 0.123) === "12.3"` because the
68 `.` in `0.0` is interpreted as a decimal point.
69
70 But `numericLerp("0.", "100.", 0.123) === "12."` because the strings
71 are interpreted as integers followed by a full stop.
72
73 Calling this functions on strings that differ in more than numerals
74 gives undefined results.
75
76
77 ### stringLerp.diffLerp(a, b, p)
78
79 Lerp from `a` to `b` based on edit operations.
80
81 This interpolation algorithm applys a partial edit of one string into
82 the other. This produces nice looking results, but can take a
83 significant amount of time and memory to compute the edits. It is not
84 recommended for strings longer than a few hundred characters.
85
86
87 ### stringLerp.fastLerp(a, b, p)
88
89 Lerp from `a` to `b` using a simple algorithm based on length.
90
91 This interpolation algorithm progressively replaces the front of one
92 string with another. This approach is fast but does not look good when
93 the strings are similar.
94
95
96 ### stringLerp.diff(s, t) and stringLerp.patch(edits, s)
97
98 These are the functions used to implement `diffLerp`. `diff`
99 calculates an array of edit operations - substitutions, insertions,
100 and deletions - to turn `s` into `t`.
101
102 The type of the edit operations is unspecified. What is guaranteed is:
103
104 * There's an Array of them.
105 * The array can be cut up and applied in-order but piecemeal.
106 * They are simple objects, i.e. can be (de)serialized via JSON and fed
107 into the same version of `patch` later.
108
109 Do not rely on edit operations to be exactly the same type (or same
110 operations) between versions / installations.
111
112
113 ### stringLerp.levenshteinMatrix(s, t, ins, del, sub)
114
115 Calculate the edit distance between the source and target sequences,
116 and return a matrix representing the possible edits and their
117 costs. The matrix returned is a flat typed array.
118
119 Because stringLerp needs to be able to reconstruct the edit path, this
120 is not an optimal algorithm if you only need the Levenshtein distance.
121
122
123 ## Unicode Concerns
124
125 String Lerp handles Unicode reasonably well. Surrogate pairs are
126 recognized and not split, and combining characters stay attached to
127 the character they started with. All algorithms will be notably
128 slower, and memory-intensive, when given such strings.
129
130 Some scripts, such as Hangul and Tamil, do not work ideally.
131 Multi-glyph graphemes will be split up, and potentially rejoined,
132 during interpolation. The intermediate string is always a valid
133 Unicode string containing only glyphs present in one string or the
134 other, but the glyphs may be arranged very differently.
135
136 A similar problem occurs when switching between LTR and RTL in the
137 same string. The codepoints indicating bidi switches may move around
138 the string capturing glyphs in ways that are not visually appealing.
139
140
141 [NPM]: https://www.npmjs.org/