MediaWiki:Gadget-freezeAPNG.js: различия между версиями
Pok (обсуждение | вклад) мНет описания правки |
Pok (обсуждение | вклад) мНет описания правки Метка: отменено |
||
| Строка 1: | Строка 1: | ||
(function($, mw){ | ( function ( $, mw ) { | ||
function | function parseChunks( buf ) { | ||
const dv = new DataView( buf ); | |||
let pos = 8; | |||
const chunks = []; | |||
while ( pos < buf.byteLength ) { | |||
const length = dv.getUint32( pos ); | |||
const typeBytes = new Uint8Array( buf, pos + 4, 4 ); | |||
const type = String.fromCharCode.apply( null, typeBytes ); | |||
const dataStart = pos + 8; | |||
const dataEnd = dataStart + length; | |||
const crcEnd = dataEnd + 4; | |||
chunks.push({ | |||
type, | |||
start: pos, | |||
end: crcEnd | |||
}); | |||
} | pos = crcEnd; | ||
} | |||
} | return chunks; | ||
} | } | ||
function | async function detectAndStrip( img ) { | ||
try { | try { | ||
img.src = | const resp = await fetch( img.src ); | ||
if ( | if ( !resp.ok ) return; | ||
if ( | const buf = await resp.arrayBuffer(); | ||
} catch(e){} | const chunks = parseChunks( buf ); | ||
if ( !chunks.some( c => c.type === 'acTL' ) ) return; | |||
const keep = []; | |||
keep.push( buf.slice( 0, 8 ) ); | |||
for ( const c of chunks ) { | |||
if ( c.type === 'acTL' || c.type === 'fcTL' ) continue; | |||
keep.push( buf.slice( c.start, c.end ) ); | |||
} | |||
const blob = new Blob( keep, { type: 'image/png' } ); | |||
const url = URL.createObjectURL( blob ); | |||
img.src = url; | |||
} catch ( e ) { | |||
console.error( 'freezeAPNG error:', e ); | |||
} | |||
} | } | ||
$( | $( () => { | ||
$('.freezeAPNG img[src$=".png"]').each( | $( '.freezeAPNG img[src$=".png"]' ).each( ( _, img ) => { | ||
if ( | if ( img.complete ) { | ||
detectAndStrip( img ); | |||
} else { | } else { | ||
img.addEventListener( 'load', () => detectAndStrip( img ), { once: true } ); | |||
} | } | ||
}); | } ); | ||
}); | } ); | ||
})(jQuery, mediaWiki); | } )( jQuery, mediaWiki ); | ||