Localisation updates from https://translatewiki.net.
[mediawiki.git] / resources / src / mediawiki.deflate / mw.deflate.js
blobc77868d8b134c84a25fd6cce6a7eded73383106c
1 /**
2  * Convert a byte stream to base64 text.
3  *
4  * @deprecated Use mw.deflateAsync
5  * @example
6  * return mw.loader.using( 'mediawiki.deflate' ).then( () => mw.deflate( html ) );
7  * @param {string} data
8  * @return {string} Compressed data
9  */
10 mw.deflate = function ( data ) {
11         const pako = require( '../../lib/pako/pako_deflate.js' );
12         return 'rawdeflate,' + bytesToBase64( pako.deflateRaw( data, { level: 5 } ) );
15 /**
16  * Convert a byte stream to base64 text.
17  *
18  * Uses browser native CompressionStream if available.
19  *
20  * @example
21  * return mw.loader.using( 'mediawiki.deflate' ).then( () => mw.deflateAsync( html ) );
22  * @param {string} data
23  * @return {Promise<string>} Compressed data
24  */
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 ) ) );
29         } else {
30                 return Promise.resolve( mw.deflate( data ) );
31         }
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 );
41         let cs, isRaw;
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
46         try {
47                 // eslint-disable-next-line compat/compat
48                 cs = new CompressionStream( 'deflate-raw' );
49                 isRaw = true;
50         } catch ( e ) {
51                 // eslint-disable-next-line compat/compat
52                 cs = new CompressionStream( 'deflate' );
53                 isRaw = false;
54         }
55         const writer = cs.writable.getWriter();
56         writer.write( byteArray );
57         writer.close();
59         const arrayBuffer = new Response( cs.readable ).arrayBuffer();
60         if ( isRaw ) {
61                 return arrayBuffer;
62         } else {
63                 return arrayBuffer.then( ( buffer ) => stripHeaderAndChecksum( new Uint8Array( buffer ) ) );
64         }
68  * Convert a byte stream to base64 text.
69  *
70  * As suggested in https://github.com/nodeca/pako/issues/206#issuecomment-744264726
71  *
72  * Code from https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727.
73  * MIT License
74  * Copyright (c) 2020 Egor Nepomnyaschih
75  *
76  * @type {Array}
77  */
78 const base64abc = [
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 */
88         let result = '', i;
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 ];
95         }
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 ];
99                 result += '==';
100         }
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 ];
105                 result += '=';
106         }
107         return result;
108         /* eslint-enable no-bitwise */