Module: DiffMatchPatchES::JsString
- Defined in:
- lib/diff_match_patch_es/js_string.rb,
sig/diff_match_patch_es/js_string.rbs
Overview
Helpers that reproduce JavaScript string semantics exactly.
Defined Under Namespace
Classes: UriError
Constant Summary collapse
- JS_PARSE_INT =
JS Number.parseInt(str, 10): optional leading whitespace and sign, JS StrWhiteSpace: ASCII whitespace, NBSP, BOM, and Unicode space separators.
/\A[\t\n\v\f\r \u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*([+-]?\d+)/- ENCODE_URI_UNESCAPED =
Characters encodeURI leaves unescaped.
/\A[A-Za-z0-9;,\/?:@&=+$\-_.!~*'()#]\z/- DECODE_URI_RESERVED =
Characters whose escape sequences decodeURI refuses to decode (uriReserved plus '#').
";/?:@&=+$,#"
Class Method Summary collapse
-
.char_at(str, index) ⇒ Object
JS String.prototype.charAt: '' when out of range.
-
.decode_uri(str) ⇒ Object
JS decodeURI: decodes %XX escape sequences as strict UTF-8 (rejecting malformed, overlong, surrogate, and out-of-range sequences) while leaving escapes of reserved characters (";/?:@&=+$,#") untouched.
-
.encode_uri(str) ⇒ Object
JS encodeURI: percent-encodes the UTF-8 bytes of every character outside the unescaped set, using uppercase hex.
-
.index_of(str, pattern, from = 0) ⇒ Object
JS String.prototype.indexOf.
-
.last_index_of(str, pattern, from) ⇒ Object
JS String.prototype.lastIndexOf: the match may start at or before
from. -
.parse_int(str) ⇒ Object
then as many digits as possible.
- .read_escaped_byte(str, index) ⇒ Object
-
.substring(str, start_index, end_index = nil) ⇒ Object
JS String.prototype.substring: negative/overflowing indices clamp to [0, length] and the arguments swap when start > end.
Instance Method Summary collapse
-
#self?.char_at ⇒ String
JS String.prototype.charAt: '' when out of range.
-
#self?.decode_uri ⇒ String
JS decodeURI.
-
#self?.encode_uri ⇒ String
JS encodeURI.
-
#self?.index_of ⇒ Integer
JS String.prototype.indexOf.
-
#self?.last_index_of ⇒ Integer
JS String.prototype.lastIndexOf: the match may start at or before
from. -
#self?.parse_int ⇒ Integer?
JS Number.parseInt(str, 10).
- #self?.read_escaped_byte ⇒ Integer
-
#self?.substring ⇒ String
JS String.prototype.substring: negative/overflowing indices clamp to [0, length] and the arguments swap when start > end.
Class Method Details
.char_at(str, index) ⇒ Object
JS String.prototype.charAt: '' when out of range.
18 19 20 21 22 |
# File 'lib/diff_match_patch_es/js_string.rb', line 18 def char_at(str, index) return '' if index.negative? || index >= str.length str[index] end |
.decode_uri(str) ⇒ Object
JS decodeURI: decodes %XX escape sequences as strict UTF-8 (rejecting malformed, overlong, surrogate, and out-of-range sequences) while leaving escapes of reserved characters (";/?:@&=+$,#") untouched.
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 |
# File 'lib/diff_match_patch_es/js_string.rb', line 71 def decode_uri(str) out = +'' i = 0 n = str.length while i < n ch = str[i] unless ch == '%' out << ch i += 1 next end start = i b0 = read_escaped_byte(str, i) i += 3 if b0 < 0x80 decoded = b0.chr if DECODE_URI_RESERVED.include?(decoded) out << str[start, 3] else out << decoded end else extra = case b0 when 0xC2..0xDF then 1 when 0xE0..0xEF then 2 when 0xF0..0xF4 then 3 else raise UriError, 'URI malformed' end codepoint = b0 & (0x3F >> extra) extra.times do raise UriError, 'URI malformed' unless str[i] == '%' byte = read_escaped_byte(str, i) raise UriError, 'URI malformed' unless (byte & 0xC0) == 0x80 codepoint = (codepoint << 6) | (byte & 0x3F) i += 3 end minimum = [0x80, 0x800, 0x10000][extra - 1] if codepoint < minimum || codepoint > 0x10FFFF || (0xD800..0xDFFF).cover?(codepoint) raise UriError, 'URI malformed' end out << codepoint.chr(Encoding::UTF_8) end end out end |
.encode_uri(str) ⇒ Object
JS encodeURI: percent-encodes the UTF-8 bytes of every character outside the unescaped set, using uppercase hex.
54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/diff_match_patch_es/js_string.rb', line 54 def encode_uri(str) out = +'' str.each_char do |ch| if ENCODE_URI_UNESCAPED.match?(ch) out << ch else ch.each_byte { |b| out << format('%%%02X', b) } end end out end |
.index_of(str, pattern, from = 0) ⇒ Object
JS String.prototype.indexOf.
25 26 27 28 |
# File 'lib/diff_match_patch_es/js_string.rb', line 25 def index_of(str, pattern, from = 0) from = from.clamp(0, str.length) str.index(pattern, from) || -1 end |
.last_index_of(str, pattern, from) ⇒ Object
JS String.prototype.lastIndexOf: the match may start at or before from.
31 32 33 34 |
# File 'lib/diff_match_patch_es/js_string.rb', line 31 def last_index_of(str, pattern, from) from = from.clamp(0, str.length) str.rindex(pattern, from) || -1 end |
.parse_int(str) ⇒ Object
then as many digits as possible. Returns nil where JS returns NaN.
41 42 43 44 |
# File 'lib/diff_match_patch_es/js_string.rb', line 41 def parse_int(str) match = JS_PARSE_INT.match(str) match && match[1].to_i end |
.read_escaped_byte(str, index) ⇒ Object
121 122 123 124 125 126 |
# File 'lib/diff_match_patch_es/js_string.rb', line 121 def read_escaped_byte(str, index) hex = str[index + 1, 2] raise UriError, 'URI malformed' unless hex&.length == 2 && /\A\h\h\z/.match?(hex) hex.to_i(16) end |
.substring(str, start_index, end_index = nil) ⇒ Object
JS String.prototype.substring: negative/overflowing indices clamp to [0, length] and the arguments swap when start > end.
9 10 11 12 13 14 15 |
# File 'lib/diff_match_patch_es/js_string.rb', line 9 def substring(str, start_index, end_index = nil) len = str.length a = start_index.clamp(0, len) b = end_index.nil? ? len : end_index.clamp(0, len) a, b = b, a if a > b str[a...b] end |
Instance Method Details
#self?.char_at ⇒ String
JS String.prototype.charAt: '' when out of range.
18 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 18
def self?.char_at: (String str, Integer index) -> String
|
#self?.decode_uri ⇒ String
JS decodeURI. Raises UriError where JS throws URIError.
33 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 33
def self?.decode_uri: (String str) -> String
|
#self?.encode_uri ⇒ String
JS encodeURI.
30 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 30
def self?.encode_uri: (String str) -> String
|
#self?.index_of ⇒ Integer
JS String.prototype.indexOf.
21 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 21
def self?.index_of: (String str, String pattern, ?Integer from) -> Integer
|
#self?.last_index_of ⇒ Integer
JS String.prototype.lastIndexOf: the match may start at or before from.
24 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 24
def self?.last_index_of: (String str, String pattern, Integer from) -> Integer
|
#self?.parse_int ⇒ Integer?
JS Number.parseInt(str, 10). Returns nil where JS returns NaN.
27 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 27
def self?.parse_int: (String str) -> Integer?
|
#self?.read_escaped_byte ⇒ Integer
35 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 35
def self?.read_escaped_byte: (String str, Integer index) -> Integer
|
#self?.substring ⇒ String
JS String.prototype.substring: negative/overflowing indices clamp to [0, length] and the arguments swap when start > end.
15 |
# File 'sig/diff_match_patch_es/js_string.rbs', line 15
def self?.substring: (String str, Integer start_index, ?Integer? end_index) -> String
|