lz_string
Ruby port of lz-string, the LZ-based compression for JavaScript.
It gives the same results as the JavaScript library, for every input: any text, emoji too, and even broken data. So you can compress in the browser and decompress in Ruby, or the other way round.
- Every format of lz-string: raw, Base64, URI-safe, UTF-16, Uint8Array and your own alphabet.
- Tested against JavaScript: it passes the test suite of lz-string itself (70 of 70 checks), and its specs check it against results of the JavaScript library.
- The same command line tool as lz-string 2, with the same options.
- No dependencies. Ruby 2.7 or newer.
Install
$ gem install lz_stringOr add it to your Gemfile:
gem "lz_string"Use
require "lz_string"
compressed = LZString.compress_to_base64("Hello, 🎶 world!")
# => "BIUwNmD2A0AEg8G4Nv3YHdICcwBMCEQ="
LZString.decompress_from_base64(compressed)
# => "Hello, 🎶 world!"The methods have the same names as in JavaScript:
| JavaScript | Ruby | Gives |
|---|---|---|
compressToBase64 / decompressFromBase64
|
LZString.compress_to_base64 / LZString.decompress_from_base64
|
Base64 |
compressToEncodedURIComponent / decompressFromEncodedURIComponent
|
LZString.compress_to_encoded_uri_component / .decompress_from_encoded_uri_component
|
text that is safe in a URL |
compressToUTF16 / decompressFromUTF16
|
LZString.compress_to_utf16 / .decompress_from_utf16
|
valid UTF-16 text, for localStorage |
compressToUint8Array / decompressFromUint8Array
|
LZString.compress_to_uint8_array / .decompress_from_uint8_array
|
bytes |
compressToCustom / decompressFromCustom
|
LZString.compress_to_custom(text, alphabet) / .decompress_from_custom(data, alphabet)
|
text from your own alphabet |
compress / decompress
|
LZString.compress / LZString.decompress
|
raw: a UTF-16LE string (see below) |
Each format also has its own class, as in older versions of this gem: LZString::Base64, LZString::UriSafe,
LZString::UTF16, LZString::Uint8Array and LZString::Custom. Each has compress and decompress.
LZString::UriSafe.compress('{"page": 2, "search": "café ☕"}')
# => "N4IgDghg5gpiBcACATAGkSAzjCAnAxgBYIb4QBmAl4oKhkIAvkA"
LZString.compress_to_uint8_array("🎶")
# => "\x8F\x06\xE3o\xDA\x00"
LZString.decompress_from_uint8_array([143, 6, 227, 111, 218, 0])
# => "🎶"
LZString.compress_to_custom("Hello world!", "0123456789abcdef")
# => "0485303660f60040ee90273004c08440"Strings in and out
- In: any Ruby string. It is read as text in its own encoding (UTF-8, Latin-1, …), like a JavaScript string.
-
Out of
decompress: a UTF-8 string, ornilwhen JavaScript givesnull(broken data). -
Raw
compressgives a UTF-16LE string. Like in JavaScript, this result is often not valid UTF-16 (it has lone surrogates), and UTF-8 can't hold it. To store or send it, use one of the other formats. -
Uint8Array gives a binary string.
decompress_from_uint8_arraytakes a binary string or a list of numbers. - A JavaScript string can hold half of an emoji (a lone surrogate). UTF-8 can't, so
decompresswrites"�"for it. If you need the result exactly as JavaScript has it, usedecompress_to_utf16le(every format has it).
Command line
$ lz_string -h
Usage: lz_string [options] [input-file]
Use lz-string to compress or decompress a file
Arguments:
input-file file to process, if no file then read from stdin
Options:
-V, --version output the version number
-d, --decompress if unset then this will compress
-e, --encoder TYPE character encoding to use (choices: base64, custom, encodeduri, raw, uint8array, utf16, default: raw)
-c, --custom DICTIONARY dictionary for custom encoder
-v, --verify verify before returning
-o, --output OUTPUT_FILE output file, otherwise write to stdout
-q, --quiet don't print any error messages
-h, --help display help for command
$ lz_string -e base64 photo.jpg -o photo.lz
$ lz_string -d -e base64 photo.lz -o photo.jpgLike the lz-string 2 tool, it works on the bytes of a file (2 bytes are one UTF-16 code unit), not on text. So it can compress any file and give it back the same. It writes the same bytes as the JavaScript tool.
Check it with the tests of lz-string
$ git clone https://github.com/pieroxy/lz-string && cd lz-string/test
$ cat > profiles/lz_string.sh <<'EOF'
optDescription="The lz_string Ruby gem"
optCommand=lz_string
optDecompress="-d"
optEncoder="-e"
optEncoders="base64,encodeduri,raw,uint8array,utf16"
optOutput="-o"
optQuiet="-q"
EOF
$ ./test.sh lz_stringUpgrade from 0.x
Emoji now work, and all results are the same as in JavaScript. Some things changed, see the changelog:
-
LZString.compress(raw) returns a UTF-16LE string, not UTF-8. -
LZString.decompress("")returnsnil, like in JavaScript. - Data that starts with code 3 (lz-string never writes that) raises
ArgumentError, like lz-string 2. - A binary string with bytes above 127 raises an error. Use
force_encodingto say what the bytes are.
Development
$ bundle install
$ rakeThe specs compare the gem with results of the JavaScript library, kept in spec/fixtures/js_results.json.
To make that file again, see spec/fixtures/js_results.js.
License
MIT