2 * Convert a byte stream to base64 text.
4 * @deprecated Use mw.deflateAsync
6 * return mw.loader.using( 'mediawiki.deflate' ).then( () => mw.deflate( html ) );
8 * @return {string} Compressed data
10 mw.deflate = function ( data ) {
11 const pako = require( '../../lib/pako/pako_deflate.js' );
12 return 'rawdeflate,' + bytesToBase64( pako.deflateRaw( data, { level: 5 } ) );
16 * Convert a byte stream to base64 text.
18 * Uses browser native CompressionStream if available.
21 * return mw.loader.using( 'mediawiki.deflate' ).then( () => mw.deflateAsync( html ) );
22 * @param {string} data
23 * @return {Promise<string>} Compressed data
25 mw.deflateAsync = function ( data ) {
26 // Support: Chrome < 80, Firefox < 113, Safari < 16.4
27 if ( window.CompressionStream ) {
28 return compress( data ).then( ( buffer ) => 'rawdeflate,' + bytesToBase64( new Uint8Array( buffer ) ) );
30 return Promise.resolve( mw.deflate( data ) );
34 function stripHeaderAndChecksum( buffer ) {
35 // Header is 2 bytes, checksum is the last 4 bytes
36 return buffer.slice( 2, buffer.byteLength - 4 );
39 function compress( string ) {
40 const byteArray = new TextEncoder().encode( string );
42 // Support: Chrome < 103
43 // Not all browsers with CompressionStream support 'deflate-raw'
44 // so fall back to the universally-supported 'deflate' and
45 // remove the header/checksum manually
47 // eslint-disable-next-line compat/compat
48 cs = new CompressionStream( 'deflate-raw' );
51 // eslint-disable-next-line compat/compat
52 cs = new CompressionStream( 'deflate' );
55 const writer = cs.writable.getWriter();
56 writer.write( byteArray );
59 const arrayBuffer = new Response( cs.readable ).arrayBuffer();
63 return arrayBuffer.then( ( buffer ) => stripHeaderAndChecksum( new Uint8Array( buffer ) ) );
68 * Convert a byte stream to base64 text.
70 * As suggested in https://github.com/nodeca/pako/issues/206#issuecomment-744264726
72 * Code from https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727.
74 * Copyright (c) 2020 Egor Nepomnyaschih
79 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
80 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
81 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
82 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
83 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
86 function bytesToBase64( bytes ) {
87 /* eslint-disable no-bitwise */
89 const l = bytes.length;
90 for ( i = 2; i < l; i += 3 ) {
91 result += base64abc[ bytes[ i - 2 ] >> 2 ];
92 result += base64abc[ ( ( bytes[ i - 2 ] & 0x03 ) << 4 ) | ( bytes[ i - 1 ] >> 4 ) ];
93 result += base64abc[ ( ( bytes[ i - 1 ] & 0x0F ) << 2 ) | ( bytes[ i ] >> 6 ) ];
94 result += base64abc[ bytes[ i ] & 0x3F ];
96 if ( i === l + 1 ) { // 1 octet yet to write
97 result += base64abc[ bytes[ i - 2 ] >> 2 ];
98 result += base64abc[ ( bytes[ i - 2 ] & 0x03 ) << 4 ];
101 if ( i === l ) { // 2 octets yet to write
102 result += base64abc[ bytes[ i - 2 ] >> 2 ];
103 result += base64abc[ ( ( bytes[ i - 2 ] & 0x03 ) << 4 ) | ( bytes[ i - 1 ] >> 4 ) ];
104 result += base64abc[ ( bytes[ i - 1 ] & 0x0F ) << 2 ];
108 /* eslint-enable no-bitwise */