Fix inlining/previewing of archive links like quote links. #5
This commit is contained in:
parent
3f34c5fb75
commit
144143e2b0
@ -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
|
||||
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)
|
||||
|
||||
- Time formatting now falls back to browser locale instead of giving an error when the locale is not set.
|
||||
|
||||
File diff suppressed because one or more lines are too long
144
builds/4chan-XT-noupdate.user.min.js
vendored
144
builds/4chan-XT-noupdate.user.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "4chan XT",
|
||||
"version": "XT 2.1.1",
|
||||
"version": "XT 2.1.2",
|
||||
"manifest_version": 2,
|
||||
"description": "4chan XT is a script that adds various features to anonymous imageboards.",
|
||||
"icons": {
|
||||
|
||||
@ -79,8 +79,8 @@
|
||||
'use strict';
|
||||
|
||||
var version = {
|
||||
"version": "XT 2.1.1",
|
||||
"date": "2023-07-16T08:49:02.722Z"
|
||||
"version": "XT 2.1.2",
|
||||
"date": "2023-07-22T15:46:24.103Z"
|
||||
};
|
||||
|
||||
var meta = {
|
||||
@ -6827,6 +6827,61 @@ https://*.hcaptcha.com
|
||||
};
|
||||
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:
|
||||
* 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
|
||||
*/
|
||||
class Fetcher {
|
||||
static initClass() {
|
||||
|
||||
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>"}
|
||||
};
|
||||
}
|
||||
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>"}
|
||||
};
|
||||
|
||||
constructor(boardID, threadID, postID, root, quoter) {
|
||||
let post, thread;
|
||||
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/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)\])/);
|
||||
comment = (() => {
|
||||
const result = [];
|
||||
for (let i = 0; i < comment.length; i++) {
|
||||
var text = comment[i];
|
||||
if ((i % 2) === 1) {
|
||||
var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')];
|
||||
if (typeof tag === 'function') { result.push(tag(text)); } else { result.push(tag); }
|
||||
} else {
|
||||
var greentext = text[0] === '>';
|
||||
text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2');
|
||||
text = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g).map((text2, j) =>
|
||||
{((j % 2) ? "<span class=\"deadlink\">" + E(text2) + "</span>" : E(text2));});
|
||||
text = {innerHTML: ((greentext) ? "<span class=\"quote\">" + E.cat(text) + "</span>" : E.cat(text))};
|
||||
result.push(text);
|
||||
}
|
||||
comment = comment.map((text, i) => {
|
||||
if ((i % 2) === 1) {
|
||||
var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')];
|
||||
return (typeof tag === 'function') ? tag(text) : tag;
|
||||
} else {
|
||||
var greentext = text[0] === '>';
|
||||
text = text
|
||||
.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2')
|
||||
.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g)
|
||||
.map((text2, j) => ((j % 2) ? `<span class="deadlink">${E(text2)}</span>`: E(text2)))
|
||||
.join('');
|
||||
return {innerHTML: (greentext ? `<span class="quote">${text}</span>` : text)};
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
comment = {innerHTML: E.cat(comment)};
|
||||
});
|
||||
comment = { innerHTML: E.cat(comment), [isEscaped]: true };
|
||||
|
||||
this.threadID = +data.thread_num;
|
||||
const o = {
|
||||
@ -7133,7 +7182,6 @@ https://*.hcaptcha.com
|
||||
return this.insert(post);
|
||||
}
|
||||
}
|
||||
Fetcher.initClass();
|
||||
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
@ -7172,7 +7220,7 @@ https://*.hcaptcha.com
|
||||
|
||||
mouseover(e) {
|
||||
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);
|
||||
|
||||
@ -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
|
||||
const separator = '\u00A0|\u00A0';
|
||||
const settingsHtml = h("div", { id: "fourchanx-settings", class: "dialog" },
|
||||
|
||||
@ -3,7 +3,7 @@ import Fetcher from "../classes/Fetcher";
|
||||
import Get from "../General/Get";
|
||||
import Header from "../General/Header";
|
||||
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 $ from "../platform/$";
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import ImageHost from "../Images/ImageHost";
|
||||
import CrossOrigin from "../platform/CrossOrigin";
|
||||
import Get from "../General/Get";
|
||||
import { dict } from "../platform/helpers";
|
||||
import { isEscaped } from "../globals/jsx";
|
||||
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
@ -20,32 +21,30 @@ import { dict } from "../platform/helpers";
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
||||
*/
|
||||
export default class Fetcher {
|
||||
static initClass() {
|
||||
|
||||
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>"}
|
||||
};
|
||||
}
|
||||
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>"}
|
||||
};
|
||||
|
||||
constructor(boardID, threadID, postID, root, quoter) {
|
||||
let post, thread;
|
||||
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/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)\])/);
|
||||
comment = (() => {
|
||||
const result = [];
|
||||
for (let i = 0; i < comment.length; i++) {
|
||||
var text = comment[i];
|
||||
if ((i % 2) === 1) {
|
||||
var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')];
|
||||
if (typeof tag === 'function') { result.push(tag(text)); } else { result.push(tag); }
|
||||
} else {
|
||||
var greentext = text[0] === '>';
|
||||
text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2');
|
||||
text = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g).map((text2, j) =>
|
||||
{innerHTML: ((j % 2) ? "<span class=\"deadlink\">" + E(text2) + "</span>" : E(text2));});
|
||||
text = {innerHTML: ((greentext) ? "<span class=\"quote\">" + E.cat(text) + "</span>" : E.cat(text))};
|
||||
result.push(text);
|
||||
}
|
||||
comment = comment.map((text, i) => {
|
||||
if ((i % 2) === 1) {
|
||||
var tag = Fetcher.archiveTags[text.replace(/\ .*\]/, ']')];
|
||||
return (typeof tag === 'function') ? tag(text) : tag;
|
||||
} else {
|
||||
var greentext = text[0] === '>';
|
||||
text = text
|
||||
.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2')
|
||||
.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g)
|
||||
.map((text2, j) => ((j % 2) ? `<span class="deadlink">${E(text2)}</span>`: E(text2)))
|
||||
.join('');
|
||||
return {innerHTML: (greentext ? `<span class="quote">${text}</span>` : text)};
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
comment = {innerHTML: E.cat(comment)};
|
||||
});
|
||||
comment = { innerHTML: E.cat(comment), [isEscaped]: true };
|
||||
|
||||
this.threadID = +data.thread_num;
|
||||
const o = {
|
||||
@ -317,4 +312,3 @@ export default class Fetcher {
|
||||
return this.insert(post);
|
||||
}
|
||||
}
|
||||
Fetcher.initClass();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"version": "XT 2.1.1",
|
||||
"date": "2023-07-16T08:49:02.722Z"
|
||||
"version": "XT 2.1.2",
|
||||
"date": "2023-07-22T15:46:24.103Z"
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user