Fix inlining/previewing of archive links like quote links. #5

This commit is contained in:
Tuxedo Takodachi 2023-07-22 17:54:11 +02:00
parent 3f34c5fb75
commit 144143e2b0
9 changed files with 23246 additions and 23262 deletions

View File

@ -3,6 +3,10 @@
4chan XT uses a different user script namespace, so to migrate you need to export settings from 4chan X, and import them 4chan XT uses a different user script namespace, so to migrate you need to export settings from 4chan X, and import them
in XT. in XT.
### XT v2.1.2 (2023-07-22)
- Fix inlining/previewing of archive links like quote links. [#5](https://github.com/TuxedoTako/4chan-xt/issues/5)
### XT v2.1.1 (2023-07-16) ### XT v2.1.1 (2023-07-16)
- Time formatting now falls back to browser locale instead of giving an error when the locale is not set. - Time formatting now falls back to browser locale instead of giving an error when the locale is not set.

View File

@ -1,6 +1,6 @@
// ==UserScript== // ==UserScript==
// @name 4chan XT // @name 4chan XT
// @version XT 2.1.1 // @version XT 2.1.2
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 74 // @minFFVer 74
// @namespace 4chan-XT // @namespace 4chan-XT
@ -190,8 +190,8 @@
'use strict'; 'use strict';
var version = { var version = {
"version": "XT 2.1.1", "version": "XT 2.1.2",
"date": "2023-07-16T08:49:02.722Z" "date": "2023-07-22T15:46:24.103Z"
}; };
var meta = { var meta = {
@ -6938,6 +6938,61 @@ https://*.hcaptcha.com
}; };
var ThreadWatcher$1 = ThreadWatcher; var ThreadWatcher$1 = ThreadWatcher;
/*
* This file has the code for the jsx to { innerHTML: "safe string" }
*
* Usage: import h from this file.
* Attributes are stringified raw, so the names must be like html text: eg class and not className.
* Boolean values are stringified as followed: true will mean the attribute is there, false means it will be omitted.
* Strings bound to attributes and children will be escaped automatically.
* It returns interface EscapedHtml { innerHTML: "safe string", [isEscaped]: true }
*
* For strings that don't have a parent element you can use fragments: <></>.
* Note that you need to import hFragment, which for some reason isn't auto imported on "add all missing imports"
*/
/**
* The symbol indicating that a string is safely escaped.
* This is a symbol so it can't be faked by a json blob from the internet.
*/
const isEscaped = Symbol('isEscaped');
const voidElements = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr',]);
const hFragment = Symbol('hFragment');
/** Function that jsx/tsx will be compiled to. */
function h(tag, attributes, ...children) {
let innerHTML = tag === hFragment ? '' : `<${tag}`;
if (attributes) {
for (const [attribute, value] of Object.entries(attributes)) {
if (!value && value !== 0)
continue;
innerHTML += ` ${attribute}`;
if (value === true)
continue;
innerHTML += `="${E(value.toString())}"`;
}
}
if (tag !== hFragment)
innerHTML += '>';
const isVoid = tag !== hFragment && voidElements.has(tag);
if (isVoid) {
if (children.length)
throw new TypeError(`${tag} is a void html element and can't have child elements`);
}
else {
for (const child of children) {
if (child === null || child === undefined || child === '')
continue;
if (child instanceof Object && "innerHTML" in child && child[isEscaped]) {
innerHTML += child.innerHTML;
continue;
}
innerHTML += E(child.toString());
}
}
if (!isVoid && tag !== hFragment)
innerHTML += `</${tag}>`;
return { innerHTML, [isEscaped]: true };
}
/* /*
* decaffeinate suggestions: * decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns * DS102: Remove unnecessary code created because of implicit returns
@ -6947,32 +7002,30 @@ https://*.hcaptcha.com
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/ */
class Fetcher { class Fetcher {
static initClass() { static archiveTags = {
'\n': {innerHTML: "<br>"},
'[b]': {innerHTML: "<b>"},
'[/b]': {innerHTML: "</b>"},
'[spoiler]': {innerHTML: "<s>"},
'[/spoiler]': {innerHTML: "</s>"},
'[code]': {innerHTML: "<pre class=\"prettyprint\">"},
'[/code]': {innerHTML: "</pre>"},
'[moot]': {innerHTML: "<div style=\"padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px\">"},
'[/moot]': {innerHTML: "</div>"},
'[banned]': {innerHTML: "<strong style=\"color: red;\">"},
'[/banned]': {innerHTML: "</strong>"},
'[fortune]'(text) { return {innerHTML: "<span class=\"fortune\" style=\"color:" + E(text.match(/#\w+|$/)[0]) + "\"><b>"}; },
'[/fortune]': {innerHTML: "</b></span>"},
'[i]': {innerHTML: "<span class=\"mu-i\">"},
'[/i]': {innerHTML: "</span>"},
'[red]': {innerHTML: "<span class=\"mu-r\">"},
'[/red]': {innerHTML: "</span>"},
'[green]': {innerHTML: "<span class=\"mu-g\">"},
'[/green]': {innerHTML: "</span>"},
'[blue]': {innerHTML: "<span class=\"mu-b\">"},
'[/blue]': {innerHTML: "</span>"}
};
this.prototype.archiveTags = {
'\n': {innerHTML: "<br>"},
'[b]': {innerHTML: "<b>"},
'[/b]': {innerHTML: "</b>"},
'[spoiler]': {innerHTML: "<s>"},
'[/spoiler]': {innerHTML: "</s>"},
'[code]': {innerHTML: "<pre class=\"prettyprint\">"},
'[/code]': {innerHTML: "</pre>"},
'[moot]': {innerHTML: "<div style=\"padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px\">"},
'[/moot]': {innerHTML: "</div>"},
'[banned]': {innerHTML: "<strong style=\"color: red;\">"},
'[/banned]': {innerHTML: "</strong>"},
'[fortune]'(text) { return {innerHTML: "<span class=\"fortune\" style=\"color:" + E(text.match(/#\w+|$/)[0]) + "\"><b>"}; },
'[/fortune]': {innerHTML: "</b></span>"},
'[i]': {innerHTML: "<span class=\"mu-i\">"},
'[/i]': {innerHTML: "</span>"},
'[red]': {innerHTML: "<span class=\"mu-r\">"},
'[/red]': {innerHTML: "</span>"},
'[green]': {innerHTML: "<span class=\"mu-g\">"},
'[/green]': {innerHTML: "</span>"},
'[blue]': {innerHTML: "<span class=\"mu-b\">"},
'[/blue]': {innerHTML: "</span>"}
};
}
constructor(boardID, threadID, postID, root, quoter) { constructor(boardID, threadID, postID, root, quoter) {
let post, thread; let post, thread;
this.boardID = boardID; this.boardID = boardID;
@ -7153,25 +7206,21 @@ https://*.hcaptcha.com
// https://github.com/FoolCode/FoolFuuka/blob/800bd090835489e7e24371186db6e336f04b85c0/src/Model/Comment.php#L368-L428 // https://github.com/FoolCode/FoolFuuka/blob/800bd090835489e7e24371186db6e336f04b85c0/src/Model/Comment.php#L368-L428
// https://github.com/bstats/b-stats/blob/6abe7bffaf6e5f523498d760e54b110df5331fbb/inc/classes/Yotsuba.php#L157-L168 // https://github.com/bstats/b-stats/blob/6abe7bffaf6e5f523498d760e54b110df5331fbb/inc/classes/Yotsuba.php#L157-L168
let comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/); let comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/);
comment = (() => { comment = comment.map((text, i) => {
const result = []; if ((i % 2) === 1) {
for (let i = 0; i < comment.length; i++) { var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')];
var text = comment[i]; return (typeof tag === 'function') ? tag(text) : tag;
if ((i % 2) === 1) { } else {
var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')]; var greentext = text[0] === '>';
if (typeof tag === 'function') { result.push(tag(text)); } else { result.push(tag); } text = text
} else { .replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2')
var greentext = text[0] === '>'; .split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g)
text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); .map((text2, j) => ((j % 2) ? `<span class="deadlink">${E(text2)}</span>`: E(text2)))
text = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g).map((text2, j) => .join('');
{((j % 2) ? "<span class=\"deadlink\">" + E(text2) + "</span>" : E(text2));}); return {innerHTML: (greentext ? `<span class="quote">${text}</span>` : text)};
text = {innerHTML: ((greentext) ? "<span class=\"quote\">" + E.cat(text) + "</span>" : E.cat(text))};
result.push(text);
}
} }
return result; });
})(); comment = { innerHTML: E.cat(comment), [isEscaped]: true };
comment = {innerHTML: E.cat(comment)};
this.threadID = +data.thread_num; this.threadID = +data.thread_num;
const o = { const o = {
@ -7244,7 +7293,6 @@ https://*.hcaptcha.com
return this.insert(post); return this.insert(post);
} }
} }
Fetcher.initClass();
/* /*
* decaffeinate suggestions: * decaffeinate suggestions:
@ -7283,7 +7331,7 @@ https://*.hcaptcha.com
mouseover(e) { mouseover(e) {
let origin; let origin;
if (($$1.hasClass(this, 'inlined') && !$$1.hasClass(doc, 'catalog-mode')) || !d$1.contains(this)) { return; } if (($$1.hasClass(this, 'inlined') && !$$1.hasClass(doc$1, 'catalog-mode')) || !d$1.contains(this)) { return; }
const {boardID, threadID, postID} = Get$1.postDataFromLink(this); const {boardID, threadID, postID} = Get$1.postDataFromLink(this);
@ -8868,61 +8916,6 @@ https://*.hcaptcha.com
} }
}; };
/*
* This file has the code for the jsx to { innerHTML: "safe string" }
*
* Usage: import h from this file.
* Attributes are stringified raw, so the names must be like html text: eg class and not className.
* Boolean values are stringified as followed: true will mean the attribute is there, false means it will be omitted.
* Strings bound to attributes and children will be escaped automatically.
* It returns interface EscapedHtml { innerHTML: "safe string", [isEscaped]: true }
*
* For strings that don't have a parent element you can use fragments: <></>.
* Note that you need to import hFragment, which for some reason isn't auto imported on "add all missing imports"
*/
/**
* The symbol indicating that a string is safely escaped.
* This is a symbol so it can't be faked by a json blob from the internet.
*/
const isEscaped = Symbol('isEscaped');
const voidElements = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr',]);
const hFragment = Symbol('hFragment');
/** Function that jsx/tsx will be compiled to. */
function h(tag, attributes, ...children) {
let innerHTML = tag === hFragment ? '' : `<${tag}`;
if (attributes) {
for (const [attribute, value] of Object.entries(attributes)) {
if (!value && value !== 0)
continue;
innerHTML += ` ${attribute}`;
if (value === true)
continue;
innerHTML += `="${E(value.toString())}"`;
}
}
if (tag !== hFragment)
innerHTML += '>';
const isVoid = tag !== hFragment && voidElements.has(tag);
if (isVoid) {
if (children.length)
throw new TypeError(`${tag} is a void html element and can't have child elements`);
}
else {
for (const child of children) {
if (child === null || child === undefined || child === '')
continue;
if (child instanceof Object && "innerHTML" in child && child[isEscaped]) {
innerHTML += child.innerHTML;
continue;
}
innerHTML += E(child.toString());
}
}
if (!isVoid && tag !== hFragment)
innerHTML += `</${tag}>`;
return { innerHTML, [isEscaped]: true };
}
// \u00A0 is non breaking space // \u00A0 is non breaking space
const separator = '\u00A0|\u00A0'; const separator = '\u00A0|\u00A0';
const settingsHtml = h("div", { id: "fourchanx-settings", class: "dialog" }, const settingsHtml = h("div", { id: "fourchanx-settings", class: "dialog" },

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{ {
"name": "4chan XT", "name": "4chan XT",
"version": "XT 2.1.1", "version": "XT 2.1.2",
"manifest_version": 2, "manifest_version": 2,
"description": "4chan XT is a script that adds various features to anonymous imageboards.", "description": "4chan XT is a script that adds various features to anonymous imageboards.",
"icons": { "icons": {

View File

@ -79,8 +79,8 @@
'use strict'; 'use strict';
var version = { var version = {
"version": "XT 2.1.1", "version": "XT 2.1.2",
"date": "2023-07-16T08:49:02.722Z" "date": "2023-07-22T15:46:24.103Z"
}; };
var meta = { var meta = {
@ -6827,6 +6827,61 @@ https://*.hcaptcha.com
}; };
var ThreadWatcher$1 = ThreadWatcher; var ThreadWatcher$1 = ThreadWatcher;
/*
* This file has the code for the jsx to { innerHTML: "safe string" }
*
* Usage: import h from this file.
* Attributes are stringified raw, so the names must be like html text: eg class and not className.
* Boolean values are stringified as followed: true will mean the attribute is there, false means it will be omitted.
* Strings bound to attributes and children will be escaped automatically.
* It returns interface EscapedHtml { innerHTML: "safe string", [isEscaped]: true }
*
* For strings that don't have a parent element you can use fragments: <></>.
* Note that you need to import hFragment, which for some reason isn't auto imported on "add all missing imports"
*/
/**
* The symbol indicating that a string is safely escaped.
* This is a symbol so it can't be faked by a json blob from the internet.
*/
const isEscaped = Symbol('isEscaped');
const voidElements = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr',]);
const hFragment = Symbol('hFragment');
/** Function that jsx/tsx will be compiled to. */
function h(tag, attributes, ...children) {
let innerHTML = tag === hFragment ? '' : `<${tag}`;
if (attributes) {
for (const [attribute, value] of Object.entries(attributes)) {
if (!value && value !== 0)
continue;
innerHTML += ` ${attribute}`;
if (value === true)
continue;
innerHTML += `="${E(value.toString())}"`;
}
}
if (tag !== hFragment)
innerHTML += '>';
const isVoid = tag !== hFragment && voidElements.has(tag);
if (isVoid) {
if (children.length)
throw new TypeError(`${tag} is a void html element and can't have child elements`);
}
else {
for (const child of children) {
if (child === null || child === undefined || child === '')
continue;
if (child instanceof Object && "innerHTML" in child && child[isEscaped]) {
innerHTML += child.innerHTML;
continue;
}
innerHTML += E(child.toString());
}
}
if (!isVoid && tag !== hFragment)
innerHTML += `</${tag}>`;
return { innerHTML, [isEscaped]: true };
}
/* /*
* decaffeinate suggestions: * decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns * DS102: Remove unnecessary code created because of implicit returns
@ -6836,32 +6891,30 @@ https://*.hcaptcha.com
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/ */
class Fetcher { class Fetcher {
static initClass() { static archiveTags = {
'\n': {innerHTML: "<br>"},
'[b]': {innerHTML: "<b>"},
'[/b]': {innerHTML: "</b>"},
'[spoiler]': {innerHTML: "<s>"},
'[/spoiler]': {innerHTML: "</s>"},
'[code]': {innerHTML: "<pre class=\"prettyprint\">"},
'[/code]': {innerHTML: "</pre>"},
'[moot]': {innerHTML: "<div style=\"padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px\">"},
'[/moot]': {innerHTML: "</div>"},
'[banned]': {innerHTML: "<strong style=\"color: red;\">"},
'[/banned]': {innerHTML: "</strong>"},
'[fortune]'(text) { return {innerHTML: "<span class=\"fortune\" style=\"color:" + E(text.match(/#\w+|$/)[0]) + "\"><b>"}; },
'[/fortune]': {innerHTML: "</b></span>"},
'[i]': {innerHTML: "<span class=\"mu-i\">"},
'[/i]': {innerHTML: "</span>"},
'[red]': {innerHTML: "<span class=\"mu-r\">"},
'[/red]': {innerHTML: "</span>"},
'[green]': {innerHTML: "<span class=\"mu-g\">"},
'[/green]': {innerHTML: "</span>"},
'[blue]': {innerHTML: "<span class=\"mu-b\">"},
'[/blue]': {innerHTML: "</span>"}
};
this.prototype.archiveTags = {
'\n': {innerHTML: "<br>"},
'[b]': {innerHTML: "<b>"},
'[/b]': {innerHTML: "</b>"},
'[spoiler]': {innerHTML: "<s>"},
'[/spoiler]': {innerHTML: "</s>"},
'[code]': {innerHTML: "<pre class=\"prettyprint\">"},
'[/code]': {innerHTML: "</pre>"},
'[moot]': {innerHTML: "<div style=\"padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px\">"},
'[/moot]': {innerHTML: "</div>"},
'[banned]': {innerHTML: "<strong style=\"color: red;\">"},
'[/banned]': {innerHTML: "</strong>"},
'[fortune]'(text) { return {innerHTML: "<span class=\"fortune\" style=\"color:" + E(text.match(/#\w+|$/)[0]) + "\"><b>"}; },
'[/fortune]': {innerHTML: "</b></span>"},
'[i]': {innerHTML: "<span class=\"mu-i\">"},
'[/i]': {innerHTML: "</span>"},
'[red]': {innerHTML: "<span class=\"mu-r\">"},
'[/red]': {innerHTML: "</span>"},
'[green]': {innerHTML: "<span class=\"mu-g\">"},
'[/green]': {innerHTML: "</span>"},
'[blue]': {innerHTML: "<span class=\"mu-b\">"},
'[/blue]': {innerHTML: "</span>"}
};
}
constructor(boardID, threadID, postID, root, quoter) { constructor(boardID, threadID, postID, root, quoter) {
let post, thread; let post, thread;
this.boardID = boardID; this.boardID = boardID;
@ -7042,25 +7095,21 @@ https://*.hcaptcha.com
// https://github.com/FoolCode/FoolFuuka/blob/800bd090835489e7e24371186db6e336f04b85c0/src/Model/Comment.php#L368-L428 // https://github.com/FoolCode/FoolFuuka/blob/800bd090835489e7e24371186db6e336f04b85c0/src/Model/Comment.php#L368-L428
// https://github.com/bstats/b-stats/blob/6abe7bffaf6e5f523498d760e54b110df5331fbb/inc/classes/Yotsuba.php#L157-L168 // https://github.com/bstats/b-stats/blob/6abe7bffaf6e5f523498d760e54b110df5331fbb/inc/classes/Yotsuba.php#L157-L168
let comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/); let comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/);
comment = (() => { comment = comment.map((text, i) => {
const result = []; if ((i % 2) === 1) {
for (let i = 0; i < comment.length; i++) { var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')];
var text = comment[i]; return (typeof tag === 'function') ? tag(text) : tag;
if ((i % 2) === 1) { } else {
var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')]; var greentext = text[0] === '>';
if (typeof tag === 'function') { result.push(tag(text)); } else { result.push(tag); } text = text
} else { .replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2')
var greentext = text[0] === '>'; .split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g)
text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); .map((text2, j) => ((j % 2) ? `<span class="deadlink">${E(text2)}</span>`: E(text2)))
text = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g).map((text2, j) => .join('');
{((j % 2) ? "<span class=\"deadlink\">" + E(text2) + "</span>" : E(text2));}); return {innerHTML: (greentext ? `<span class="quote">${text}</span>` : text)};
text = {innerHTML: ((greentext) ? "<span class=\"quote\">" + E.cat(text) + "</span>" : E.cat(text))};
result.push(text);
}
} }
return result; });
})(); comment = { innerHTML: E.cat(comment), [isEscaped]: true };
comment = {innerHTML: E.cat(comment)};
this.threadID = +data.thread_num; this.threadID = +data.thread_num;
const o = { const o = {
@ -7133,7 +7182,6 @@ https://*.hcaptcha.com
return this.insert(post); return this.insert(post);
} }
} }
Fetcher.initClass();
/* /*
* decaffeinate suggestions: * decaffeinate suggestions:
@ -7172,7 +7220,7 @@ https://*.hcaptcha.com
mouseover(e) { mouseover(e) {
let origin; let origin;
if (($$1.hasClass(this, 'inlined') && !$$1.hasClass(doc, 'catalog-mode')) || !d$1.contains(this)) { return; } if (($$1.hasClass(this, 'inlined') && !$$1.hasClass(doc$1, 'catalog-mode')) || !d$1.contains(this)) { return; }
const {boardID, threadID, postID} = Get$1.postDataFromLink(this); const {boardID, threadID, postID} = Get$1.postDataFromLink(this);
@ -8757,61 +8805,6 @@ https://*.hcaptcha.com
} }
}; };
/*
* This file has the code for the jsx to { innerHTML: "safe string" }
*
* Usage: import h from this file.
* Attributes are stringified raw, so the names must be like html text: eg class and not className.
* Boolean values are stringified as followed: true will mean the attribute is there, false means it will be omitted.
* Strings bound to attributes and children will be escaped automatically.
* It returns interface EscapedHtml { innerHTML: "safe string", [isEscaped]: true }
*
* For strings that don't have a parent element you can use fragments: <></>.
* Note that you need to import hFragment, which for some reason isn't auto imported on "add all missing imports"
*/
/**
* The symbol indicating that a string is safely escaped.
* This is a symbol so it can't be faked by a json blob from the internet.
*/
const isEscaped = Symbol('isEscaped');
const voidElements = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr',]);
const hFragment = Symbol('hFragment');
/** Function that jsx/tsx will be compiled to. */
function h(tag, attributes, ...children) {
let innerHTML = tag === hFragment ? '' : `<${tag}`;
if (attributes) {
for (const [attribute, value] of Object.entries(attributes)) {
if (!value && value !== 0)
continue;
innerHTML += ` ${attribute}`;
if (value === true)
continue;
innerHTML += `="${E(value.toString())}"`;
}
}
if (tag !== hFragment)
innerHTML += '>';
const isVoid = tag !== hFragment && voidElements.has(tag);
if (isVoid) {
if (children.length)
throw new TypeError(`${tag} is a void html element and can't have child elements`);
}
else {
for (const child of children) {
if (child === null || child === undefined || child === '')
continue;
if (child instanceof Object && "innerHTML" in child && child[isEscaped]) {
innerHTML += child.innerHTML;
continue;
}
innerHTML += E(child.toString());
}
}
if (!isVoid && tag !== hFragment)
innerHTML += `</${tag}>`;
return { innerHTML, [isEscaped]: true };
}
// \u00A0 is non breaking space // \u00A0 is non breaking space
const separator = '\u00A0|\u00A0'; const separator = '\u00A0|\u00A0';
const settingsHtml = h("div", { id: "fourchanx-settings", class: "dialog" }, const settingsHtml = h("div", { id: "fourchanx-settings", class: "dialog" },

View File

@ -3,7 +3,7 @@ import Fetcher from "../classes/Fetcher";
import Get from "../General/Get"; import Get from "../General/Get";
import Header from "../General/Header"; import Header from "../General/Header";
import UI from "../General/UI"; import UI from "../General/UI";
import { Conf, d, g } from "../globals/globals"; import { Conf, d, doc, g } from "../globals/globals";
import ExpandComment from "../Miscellaneous/ExpandComment"; import ExpandComment from "../Miscellaneous/ExpandComment";
import $ from "../platform/$"; import $ from "../platform/$";

View File

@ -10,6 +10,7 @@ import ImageHost from "../Images/ImageHost";
import CrossOrigin from "../platform/CrossOrigin"; import CrossOrigin from "../platform/CrossOrigin";
import Get from "../General/Get"; import Get from "../General/Get";
import { dict } from "../platform/helpers"; import { dict } from "../platform/helpers";
import { isEscaped } from "../globals/jsx";
/* /*
* decaffeinate suggestions: * decaffeinate suggestions:
@ -20,32 +21,30 @@ import { dict } from "../platform/helpers";
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/ */
export default class Fetcher { export default class Fetcher {
static initClass() { static archiveTags = {
'\n': {innerHTML: "<br>"},
'[b]': {innerHTML: "<b>"},
'[/b]': {innerHTML: "</b>"},
'[spoiler]': {innerHTML: "<s>"},
'[/spoiler]': {innerHTML: "</s>"},
'[code]': {innerHTML: "<pre class=\"prettyprint\">"},
'[/code]': {innerHTML: "</pre>"},
'[moot]': {innerHTML: "<div style=\"padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px\">"},
'[/moot]': {innerHTML: "</div>"},
'[banned]': {innerHTML: "<strong style=\"color: red;\">"},
'[/banned]': {innerHTML: "</strong>"},
'[fortune]'(text) { return {innerHTML: "<span class=\"fortune\" style=\"color:" + E(text.match(/#\w+|$/)[0]) + "\"><b>"}; },
'[/fortune]': {innerHTML: "</b></span>"},
'[i]': {innerHTML: "<span class=\"mu-i\">"},
'[/i]': {innerHTML: "</span>"},
'[red]': {innerHTML: "<span class=\"mu-r\">"},
'[/red]': {innerHTML: "</span>"},
'[green]': {innerHTML: "<span class=\"mu-g\">"},
'[/green]': {innerHTML: "</span>"},
'[blue]': {innerHTML: "<span class=\"mu-b\">"},
'[/blue]': {innerHTML: "</span>"}
};
this.prototype.archiveTags = {
'\n': {innerHTML: "<br>"},
'[b]': {innerHTML: "<b>"},
'[/b]': {innerHTML: "</b>"},
'[spoiler]': {innerHTML: "<s>"},
'[/spoiler]': {innerHTML: "</s>"},
'[code]': {innerHTML: "<pre class=\"prettyprint\">"},
'[/code]': {innerHTML: "</pre>"},
'[moot]': {innerHTML: "<div style=\"padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px\">"},
'[/moot]': {innerHTML: "</div>"},
'[banned]': {innerHTML: "<strong style=\"color: red;\">"},
'[/banned]': {innerHTML: "</strong>"},
'[fortune]'(text) { return {innerHTML: "<span class=\"fortune\" style=\"color:" + E(text.match(/#\w+|$/)[0]) + "\"><b>"}; },
'[/fortune]': {innerHTML: "</b></span>"},
'[i]': {innerHTML: "<span class=\"mu-i\">"},
'[/i]': {innerHTML: "</span>"},
'[red]': {innerHTML: "<span class=\"mu-r\">"},
'[/red]': {innerHTML: "</span>"},
'[green]': {innerHTML: "<span class=\"mu-g\">"},
'[/green]': {innerHTML: "</span>"},
'[blue]': {innerHTML: "<span class=\"mu-b\">"},
'[/blue]': {innerHTML: "</span>"}
};
}
constructor(boardID, threadID, postID, root, quoter) { constructor(boardID, threadID, postID, root, quoter) {
let post, thread; let post, thread;
this.boardID = boardID; this.boardID = boardID;
@ -226,25 +225,21 @@ export default class Fetcher {
// https://github.com/FoolCode/FoolFuuka/blob/800bd090835489e7e24371186db6e336f04b85c0/src/Model/Comment.php#L368-L428 // https://github.com/FoolCode/FoolFuuka/blob/800bd090835489e7e24371186db6e336f04b85c0/src/Model/Comment.php#L368-L428
// https://github.com/bstats/b-stats/blob/6abe7bffaf6e5f523498d760e54b110df5331fbb/inc/classes/Yotsuba.php#L157-L168 // https://github.com/bstats/b-stats/blob/6abe7bffaf6e5f523498d760e54b110df5331fbb/inc/classes/Yotsuba.php#L157-L168
let comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/); let comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/);
comment = (() => { comment = comment.map((text, i) => {
const result = []; if ((i % 2) === 1) {
for (let i = 0; i < comment.length; i++) { var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')];
var text = comment[i]; return (typeof tag === 'function') ? tag(text) : tag;
if ((i % 2) === 1) { } else {
var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')]; var greentext = text[0] === '>';
if (typeof tag === 'function') { result.push(tag(text)); } else { result.push(tag); } text = text
} else { .replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2')
var greentext = text[0] === '>'; .split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g)
text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); .map((text2, j) => ((j % 2) ? `<span class="deadlink">${E(text2)}</span>`: E(text2)))
text = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g).map((text2, j) => .join('');
{innerHTML: ((j % 2) ? "<span class=\"deadlink\">" + E(text2) + "</span>" : E(text2));}); return {innerHTML: (greentext ? `<span class="quote">${text}</span>` : text)};
text = {innerHTML: ((greentext) ? "<span class=\"quote\">" + E.cat(text) + "</span>" : E.cat(text))};
result.push(text);
}
} }
return result; });
})(); comment = { innerHTML: E.cat(comment), [isEscaped]: true };
comment = {innerHTML: E.cat(comment)};
this.threadID = +data.thread_num; this.threadID = +data.thread_num;
const o = { const o = {
@ -317,4 +312,3 @@ export default class Fetcher {
return this.insert(post); return this.insert(post);
} }
} }
Fetcher.initClass();

View File

@ -1,4 +1,4 @@
{ {
"version": "XT 2.1.1", "version": "XT 2.1.2",
"date": "2023-07-16T08:49:02.722Z" "date": "2023-07-22T15:46:24.103Z"
} }