mirror of
https://github.com/QuiteAFancyEmerald/Holy-Unblocker.git
synced 2025-05-13 12:00:02 -04:00
Minor Change (oops)
This commit is contained in:
parent
af2ca7e034
commit
6bd7e10c4d
31 changed files with 34771 additions and 1 deletions
226
src/Corrosion/lib/html.js
Normal file
226
src/Corrosion/lib/html.js
Normal file
|
@ -0,0 +1,226 @@
|
|||
const parse5 = require('parse5');
|
||||
|
||||
class HTMLRewriter {
|
||||
constructor(ctx) {
|
||||
this.ctx = ctx;
|
||||
this.attrs = [
|
||||
{
|
||||
tags: ['form', 'object', 'a', 'link', 'area', 'base', 'script', 'img', 'audio', 'video', 'input', 'embed', 'iframe', 'track', 'source', 'html', 'table', 'head'],
|
||||
attrs: ['src', 'href', 'ping', 'data', 'movie', 'action', 'poster', 'profile', 'background'],
|
||||
handler: 'url',
|
||||
},
|
||||
{
|
||||
tags: ['iframe'],
|
||||
attrs: ['srcdoc'],
|
||||
handler: 'html',
|
||||
},
|
||||
{
|
||||
tags: ['img', 'link', 'source'],
|
||||
attrs: ['srcset', 'imagesrcset'],
|
||||
handler: 'srcset',
|
||||
},
|
||||
{
|
||||
tags: '*',
|
||||
attrs: ['style'],
|
||||
handler: 'css',
|
||||
},
|
||||
{
|
||||
tags: '*',
|
||||
attrs: ['http-equiv', 'integrity', 'nonce', 'crossorigin'],
|
||||
handler: 'delete',
|
||||
},
|
||||
];
|
||||
};
|
||||
process(source, config = {}) {
|
||||
const ast = parse5[config.document ? 'parse' : 'parseFragment'](source);
|
||||
const meta = {
|
||||
origin: config.origin,
|
||||
base: new URL(config.base),
|
||||
};
|
||||
iterate(ast, node => {
|
||||
if (!node.tagName) return;
|
||||
switch(node.tagName) {
|
||||
case 'STYLE':
|
||||
if (node.textContent) node.textContent = this.ctx.css.process(node.textContent, meta);
|
||||
break;
|
||||
case 'TITLE':
|
||||
if (node.textContent && this.ctx.config.title) node.textContent = this.ctx.config.title;
|
||||
break;
|
||||
case 'SCRIPT':
|
||||
if (node.getAttribute('type') != 'application/json' && node.textContent) node.textContent = this.ctx.js.process(node.textContent);
|
||||
break;
|
||||
case 'BASE':
|
||||
if (node.hasAttribute('href')) meta.base = new URL(node.getAttribute('href'), config.base);
|
||||
break;
|
||||
};
|
||||
node.attrs.forEach(attr => {
|
||||
const handler = this.attributeRoute({
|
||||
...attr,
|
||||
node,
|
||||
});
|
||||
let flags = [];
|
||||
if (node.tagName == 'SCRIPT' && attr.name == 'src') flags.push('js');
|
||||
if (node.tagName == 'LINK' && node.getAttribute('rel') == 'stylesheet') flags.push('css');
|
||||
switch(handler) {
|
||||
case 'url':
|
||||
node.setAttribute(`corrosion-${attr.name}`, attr.value);
|
||||
attr.value = this.ctx.url.wrap(attr.value, { ...meta, flags });
|
||||
break;
|
||||
case 'srcset':
|
||||
node.setAttribute(`corrosion-${attr.name}`, attr.value);
|
||||
attr.value = this.srcset(attr.value, meta);
|
||||
break;
|
||||
case 'css':
|
||||
attr.value = this.ctx.css.process(attr.value, { ...meta, context: 'declarationList' });
|
||||
break;
|
||||
case 'html':
|
||||
node.setAttribute(`corrosion-${attr.name}`, attr.value);
|
||||
attr.value = this.process(attr.value, { ...config, ...meta });
|
||||
break;
|
||||
case 'delete':
|
||||
node.removeAttribute(attr.name);
|
||||
break;
|
||||
};
|
||||
});
|
||||
});
|
||||
if (config.document) {
|
||||
for (let i in ast.childNodes) if (ast.childNodes[i].tagName == 'html') ast.childNodes[i].childNodes.forEach(node => {
|
||||
if (node.tagName == 'head') {
|
||||
node.childNodes.unshift(...this.injectHead(config.base));
|
||||
};
|
||||
});
|
||||
};
|
||||
return parse5.serialize(ast);
|
||||
};
|
||||
source(processed, config = {}) {
|
||||
const ast = parse5[config.document ? 'parse' : 'parseFragment'](processed);
|
||||
iterate(ast, node => {
|
||||
if (!node.tagName) return;
|
||||
node.attrs.forEach(attr => {
|
||||
if (node.hasAttribute(`corrosion-${attr.name}`)) {
|
||||
attr.value = node.getAttribute(`corrosion-${attr.name}`);
|
||||
node.removeAttribute(`corrosion-${attr.name}`)
|
||||
};
|
||||
});
|
||||
});
|
||||
return parse5.serialize(ast);
|
||||
};
|
||||
injectHead() {
|
||||
return [
|
||||
{
|
||||
nodeName: 'title',
|
||||
tagName: 'title',
|
||||
childNodes: [
|
||||
{
|
||||
nodeName: '#text',
|
||||
value: this.ctx.config.title || '',
|
||||
}
|
||||
],
|
||||
attrs: [],
|
||||
},
|
||||
{
|
||||
nodeName: 'script',
|
||||
tagName: 'script',
|
||||
childNodes: [],
|
||||
attrs: [
|
||||
{
|
||||
name: 'src',
|
||||
value: this.ctx.prefix + 'index.js',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
nodeName: 'script',
|
||||
tagName: 'script',
|
||||
childNodes: [
|
||||
{
|
||||
nodeName: '#text',
|
||||
value: `window.$corrosion = new Corrosion({ window, codec: '${this.ctx.config.codec || 'plain'}', prefix: '${this.ctx.prefix}', ws: ${this.ctx.config.ws}, cookie: ${this.ctx.config.cookie}, title: ${typeof this.ctx.config.title == 'boolean' ? this.ctx.config.title : '\'' + this.ctx.config.title + '\''}, }); $corrosion.init(); document.currentScript.remove();`
|
||||
},
|
||||
],
|
||||
attrs: [],
|
||||
}
|
||||
];
|
||||
}
|
||||
attributeRoute(data) {
|
||||
const match = this.attrs.find(entry => entry.tags == '*' && entry.attrs.includes(data.name) || entry.tags.includes(data.node.tagName.toLowerCase()) && entry.attrs.includes(data.name));
|
||||
return match ? match.handler : false;
|
||||
};
|
||||
srcset(val, config = {}) {
|
||||
return val.split(',').map(src => {
|
||||
const parts = src.trimStart().split(' ');
|
||||
if (parts[0]) parts[0] = this.ctx.url.wrap(parts[0], config);
|
||||
return parts.join(' ');
|
||||
}).join(', ');
|
||||
};
|
||||
unsrcset(val, config = {}) {
|
||||
return val.split(',').map(src => {
|
||||
const parts = src.trimStart().split(' ');
|
||||
if (parts[0]) parts[0] = this.ctx.url.unwrap(parts[0], config);
|
||||
return parts.join(' ');
|
||||
}).join(', ');
|
||||
};
|
||||
};
|
||||
|
||||
class Parse5Wrapper {
|
||||
constructor(node){
|
||||
this.raw = node || {
|
||||
attrs: [],
|
||||
childNodes: [],
|
||||
namespaceURI: '',
|
||||
nodeName: '',
|
||||
parentNode: {},
|
||||
tagName: '',
|
||||
};
|
||||
};
|
||||
hasAttribute(name){
|
||||
return this.raw.attrs.some(attr => attr.name == name);
|
||||
};
|
||||
removeAttribute(name){
|
||||
if (!this.hasAttribute(name)) return;
|
||||
this.raw.attrs.splice(this.raw.attrs.findIndex(attr => attr.name == name), 1);
|
||||
};
|
||||
setAttribute(name, val = ''){
|
||||
if (!name) return;
|
||||
this.removeAttribute(name);
|
||||
this.raw.attrs.push({
|
||||
name: name,
|
||||
value: val,
|
||||
});
|
||||
};
|
||||
getAttribute(name){
|
||||
return (this.raw.attrs.find(attr => attr.name == name) || { value: null }).value;
|
||||
};
|
||||
get textContent(){
|
||||
return (this.raw.childNodes.find(node => node.nodeName == '#text') || { value: '', }).value
|
||||
};
|
||||
set textContent(val){
|
||||
if (this.raw.childNodes.some(node => node.nodeName == '#text')) return this.raw.childNodes[this.raw.childNodes.findIndex(node => node.nodeName == '#text')].value = val;
|
||||
this.raw.childNodes.push({
|
||||
nodeName: '#text',
|
||||
value: val,
|
||||
});
|
||||
};
|
||||
get tagName(){
|
||||
return (this.raw.tagName || '').toUpperCase();
|
||||
};
|
||||
get nodeName(){
|
||||
return this.raw.nodeName;
|
||||
};
|
||||
get parentNode(){
|
||||
return this.raw.parentNode;
|
||||
};
|
||||
get childNodes(){
|
||||
return this.raw.childNodes || [];
|
||||
};
|
||||
get attrs() {
|
||||
return this.raw.attrs || [];
|
||||
};
|
||||
};
|
||||
|
||||
function iterate(ast, fn = (node = Parse5Wrapper.prototype) => null) {
|
||||
fn(new Parse5Wrapper(ast));
|
||||
if (ast.childNodes) for (let i in ast.childNodes) iterate(ast.childNodes[i], fn);
|
||||
};
|
||||
|
||||
module.exports = HTMLRewriter;
|
Loading…
Add table
Add a link
Reference in a new issue