mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2026-01-30 09:48:12 +01:00
Added types and bug fixes
This commit is contained in:
parent
f65fbc4fed
commit
241ff1eb7a
@ -874,8 +874,9 @@ var Embedding = {
|
|||||||
{
|
{
|
||||||
key: 'YouTube',
|
key: 'YouTube',
|
||||||
regExp:
|
regExp:
|
||||||
/^\w+:\/\/(?:youtu.be\/|[\w.]*youtube[\w.]*\/.*(?:v=|\bembed\/|\bv\/))([\w\-]{11})(.*)/,
|
/^\w+:\/\/(?:www\.)?youtube\.com\/(?:watch\?v=|embed\/|v\/)?(\w+)/,
|
||||||
el(a) {
|
el(a) {
|
||||||
|
const isShort = a.href.includes('youtube.com/shorts/')
|
||||||
let start = a.dataset.options.match(/\b(?:star)?t\=(\w+)/)
|
let start = a.dataset.options.match(/\b(?:star)?t\=(\w+)/)
|
||||||
if (start) {
|
if (start) {
|
||||||
start = start[1]
|
start = start[1]
|
||||||
@ -888,11 +889,15 @@ var Embedding = {
|
|||||||
1 * start.match(/(\d+)s/)[1]
|
1 * start.match(/(\d+)s/)[1]
|
||||||
}
|
}
|
||||||
const el = $.el('iframe', {
|
const el = $.el('iframe', {
|
||||||
src: `//www.youtube.com/embed/${a.dataset.uid}?rel=0&wmode=opaque${
|
src: `//www.youtube.com/embed/${a.dataset.uid}${isShort ? '?t=0s&enablejsapi=1&controls=0&loop=1&mute=1&playsinline=1' : `?rel=0&wmode=opaque${start ? '&start=' + start : ''}`}`,
|
||||||
start ? '&start=' + start : ''
|
|
||||||
}`,
|
|
||||||
})
|
})
|
||||||
el.setAttribute('allowfullscreen', 'true')
|
el.setAttribute('allowfullscreen', 'true')
|
||||||
|
if (isShort) {
|
||||||
|
el.setAttribute('allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share')
|
||||||
|
el.setAttribute('allowfullscreen', '')
|
||||||
|
el.setAttribute('loading', 'lazy')
|
||||||
|
el.setAttribute('class', 'youtube-short')
|
||||||
|
}
|
||||||
return el
|
return el
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
@ -907,17 +912,18 @@ var Embedding = {
|
|||||||
const m = _.error.match(/^(\d*)\s*(.*)/)
|
const m = _.error.match(/^(\d*)\s*(.*)/)
|
||||||
return [+m[1], m[2]]
|
return [+m[1], m[2]]
|
||||||
} else {
|
} else {
|
||||||
return [200, 'OK']
|
return [200, null]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
url(uid) {
|
url(uid) {
|
||||||
return `https://img.youtube.com/vi/${uid}/0.jpg`
|
const isShort = uid.includes('shorts')
|
||||||
|
return `https://img.youtube.com/vi/${uid}${isShort ? '/mqdefault.jpg' : '/0.jpg'}`
|
||||||
},
|
},
|
||||||
height: 360,
|
height: 360,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
export default Embedding
|
export default Embedding
|
||||||
|
|||||||
@ -4,11 +4,6 @@ import Filter from '../Filtering/Filter'
|
|||||||
import { g, Conf } from '../globals/globals'
|
import { g, Conf } from '../globals/globals'
|
||||||
import Menu from './Menu'
|
import Menu from './Menu'
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const ArchiveLink = {
|
const ArchiveLink = {
|
||||||
init() {
|
init() {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -2,12 +2,14 @@ import { g, Conf, d } from '../globals/globals'
|
|||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
import Menu from './Menu'
|
import Menu from './Menu'
|
||||||
|
|
||||||
/*
|
interface CopyTextLink {
|
||||||
* decaffeinate suggestions:
|
text: string
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
init(): VoidFunction
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
copy(): VoidFunction
|
||||||
*/
|
}
|
||||||
var CopyTextLink = {
|
|
||||||
|
const CopyTextLink: CopyTextLink = {
|
||||||
|
text: '',
|
||||||
init() {
|
init() {
|
||||||
if (
|
if (
|
||||||
!['index', 'thread'].includes(g.VIEW) ||
|
!['index', 'thread'].includes(g.VIEW) ||
|
||||||
@ -3,13 +3,9 @@ import ImageCommon from '../Images/ImageCommon'
|
|||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
import Menu from './Menu'
|
import Menu from './Menu'
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const DownloadLink = {
|
const DownloadLink = {
|
||||||
init() {
|
init(): VoidFunction {
|
||||||
if (
|
if (
|
||||||
!['index', 'thread'].includes(g.VIEW) ||
|
!['index', 'thread'].includes(g.VIEW) ||
|
||||||
!Conf['Menu'] ||
|
!Conf['Menu'] ||
|
||||||
@ -18,7 +14,7 @@ const DownloadLink = {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const a = $.el('a', {
|
const a: HTMLAnchorElement = $.el('a', {
|
||||||
className: 'download-link',
|
className: 'download-link',
|
||||||
textContent: 'Download file',
|
textContent: 'Download file',
|
||||||
})
|
})
|
||||||
@ -37,7 +33,7 @@ const DownloadLink = {
|
|||||||
a.download = file.name
|
a.download = file.name
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
})
|
}) as VoidFunction
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
export default DownloadLink
|
export default DownloadLink
|
||||||
@ -2,14 +2,10 @@ import Callbacks from '../classes/Callbacks'
|
|||||||
import UI from '../General/UI'
|
import UI from '../General/UI'
|
||||||
import { g, Conf } from '../globals/globals'
|
import { g, Conf } from '../globals/globals'
|
||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
|
import Post from '../classes/Post'
|
||||||
|
|
||||||
/*
|
var Menu: any = {
|
||||||
* decaffeinate suggestions:
|
init(): VoidFunction {
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
var Menu = {
|
|
||||||
init() {
|
|
||||||
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Menu']) {
|
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Menu']) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -33,7 +29,7 @@ var Menu = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
node() {
|
node(): HTMLElement {
|
||||||
if (this.isClone) {
|
if (this.isClone) {
|
||||||
const button = $('.menu-button', this.nodes.info)
|
const button = $('.menu-button', this.nodes.info)
|
||||||
$.rmClass(button, 'active')
|
$.rmClass(button, 'active')
|
||||||
@ -44,15 +40,15 @@ var Menu = {
|
|||||||
return $.add(this.nodes.info, Menu.makeButton(this))
|
return $.add(this.nodes.info, Menu.makeButton(this))
|
||||||
},
|
},
|
||||||
|
|
||||||
catalogNode() {
|
catalogNode(): HTMLElement {
|
||||||
return $.after(this.nodes.icons, Menu.makeButton(this.thread.OP))
|
return $.after(this.nodes.icons, Menu.makeButton(this.thread.OP))
|
||||||
},
|
},
|
||||||
|
|
||||||
makeButton(post, button) {
|
makeButton(post: Post, button?: HTMLElement): HTMLElement {
|
||||||
if (!button) {
|
if (!button) {
|
||||||
button = Menu.button.cloneNode(true)
|
button = Menu.button.cloneNode(true)
|
||||||
}
|
}
|
||||||
$.on(button, 'click', function (e) {
|
$.on(button, 'click', (e: Event) => {
|
||||||
return Menu.menu.toggle(e, this, post)
|
return Menu.menu.toggle(e, this, post)
|
||||||
})
|
})
|
||||||
return button
|
return button
|
||||||
@ -1,23 +1,24 @@
|
|||||||
import { g, Conf, d } from '../globals/globals'
|
import { g, Conf, d } from '../globals/globals'
|
||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
import Menu from './Menu'
|
import Menu from './Menu'
|
||||||
|
import Post from '../classes/Post'
|
||||||
|
|
||||||
/*
|
type ReportLinkType = {
|
||||||
* decaffeinate suggestions:
|
init: () => void
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
report: () => void
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
url: string
|
||||||
*/
|
dims: string
|
||||||
var ReportLink = {
|
}
|
||||||
|
|
||||||
|
const ReportLink: ReportLinkType = {
|
||||||
init() {
|
init() {
|
||||||
if (
|
if (!['index', 'thread'].includes(g.VIEW) ||
|
||||||
!['index', 'thread'].includes(g.VIEW) ||
|
|
||||||
!Conf['Menu'] ||
|
!Conf['Menu'] ||
|
||||||
!Conf['Report Link']
|
!Conf['Report Link']) {
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const a = $.el('a', {
|
const a: HTMLAnchorElement = $.el('a', {
|
||||||
className: 'report-link',
|
className: 'report-link',
|
||||||
href: 'javascript:;',
|
href: 'javascript:;',
|
||||||
textContent: 'Report',
|
textContent: 'Report',
|
||||||
@ -27,10 +28,8 @@ var ReportLink = {
|
|||||||
return Menu.menu.addEntry({
|
return Menu.menu.addEntry({
|
||||||
el: a,
|
el: a,
|
||||||
order: 10,
|
order: 10,
|
||||||
open(post) {
|
open(post: Post) {
|
||||||
ReportLink.url = `//sys.${location.hostname.split('.')[1]}.org/${
|
ReportLink.url = `//sys.${location.hostname.split('.')[1]}.org/${post.board}/imgboard.php?mode=report&no=${post}`
|
||||||
post.board
|
|
||||||
}/imgboard.php?mode=report&no=${post}`
|
|
||||||
if (d.cookie.indexOf('pass_enabled=1') >= 0) {
|
if (d.cookie.indexOf('pass_enabled=1') >= 0) {
|
||||||
ReportLink.dims = 'width=350,height=275'
|
ReportLink.dims = 'width=350,height=275'
|
||||||
} else {
|
} else {
|
||||||
@ -47,5 +46,7 @@ var ReportLink = {
|
|||||||
const set = `toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1,${dims}`
|
const set = `toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1,${dims}`
|
||||||
return window.open(url, `report${id}`, set)
|
return window.open(url, `report${id}`, set)
|
||||||
},
|
},
|
||||||
|
url: '',
|
||||||
|
dims: ''
|
||||||
}
|
}
|
||||||
export default ReportLink
|
export default ReportLink
|
||||||
@ -2,20 +2,16 @@ import $ from '../platform/$'
|
|||||||
import CSS from '../css/CSS'
|
import CSS from '../css/CSS'
|
||||||
import { Conf } from '../globals/globals'
|
import { Conf } from '../globals/globals'
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const CustomCSS = {
|
const CustomCSS = {
|
||||||
init() {
|
init(): void {
|
||||||
if (!Conf['Custom CSS']) {
|
if (!Conf['Custom CSS']) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return this.addStyle()
|
return this.addStyle()
|
||||||
},
|
},
|
||||||
|
|
||||||
addStyle() {
|
addStyle(): HTMLStyleElement {
|
||||||
return (this.style = $.addStyle(
|
return (this.style = $.addStyle(
|
||||||
CSS.sub(Conf['usercss']),
|
CSS.sub(Conf['usercss']),
|
||||||
'custom-css',
|
'custom-css',
|
||||||
@ -23,18 +19,18 @@ const CustomCSS = {
|
|||||||
))
|
))
|
||||||
},
|
},
|
||||||
|
|
||||||
rmStyle() {
|
rmStyle(): boolean {
|
||||||
if (this.style) {
|
if (this.style) {
|
||||||
$.rm(this.style)
|
$.rm(this.style)
|
||||||
return delete this.style
|
return delete this.style
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
update() {
|
update(): void {
|
||||||
if (!this.style) {
|
if (this.style) {
|
||||||
return this.addStyle()
|
this.rmStyle()
|
||||||
|
this.addStyle()
|
||||||
}
|
}
|
||||||
return (this.style.textContent = CSS.sub(Conf['usercss']))
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
export default CustomCSS
|
export default CustomCSS
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import Callbacks from '../classes/Callbacks'
|
import Callbacks from "../classes/Callbacks";
|
||||||
import BoardConfig from '../General/BoardConfig'
|
import BoardConfig from "../General/BoardConfig";
|
||||||
import { d, doc, g } from '../globals/globals'
|
import { d, doc, g } from "../globals/globals";
|
||||||
import Main from '../main/Main'
|
import Main from "../main/Main";
|
||||||
import $ from '../platform/$'
|
import $ from "../platform/$";
|
||||||
import $$ from '../platform/$$'
|
import $$ from "../platform/$$";
|
||||||
import ExpandComment from './ExpandComment'
|
import ExpandComment from "./ExpandComment";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* decaffeinate suggestions:
|
* decaffeinate suggestions:
|
||||||
@ -13,161 +13,110 @@ import ExpandComment from './ExpandComment'
|
|||||||
*/
|
*/
|
||||||
var Fourchan = {
|
var Fourchan = {
|
||||||
init() {
|
init() {
|
||||||
if (
|
if ((g.SITE.software !== 'yotsuba') || !['index', 'thread', 'archive'].includes(g.VIEW)) { return; }
|
||||||
g.SITE.software !== 'yotsuba' ||
|
BoardConfig.ready(this.initBoard);
|
||||||
!['index', 'thread', 'archive'].includes(g.VIEW)
|
return Main.ready(this.initReady);
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
BoardConfig.ready(this.initBoard)
|
|
||||||
return Main.ready(this.initReady)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
initBoard() {
|
initBoard() {
|
||||||
if (g.BOARD.config.code_tags) {
|
if (g.BOARD.config.code_tags) {
|
||||||
$.on(window, 'prettyprint:cb', function (e) {
|
$.on(window, 'prettyprint:cb', function (e) {
|
||||||
let post, pre
|
let post, pre;
|
||||||
if (!(post = g.posts.get(e.detail.ID))) {
|
if (!(post = g.posts.get(e.detail.ID))) { return; }
|
||||||
return
|
if (!(pre = $$('.prettyprint', post.nodes.comment)[+e.detail.i])) { return; }
|
||||||
}
|
|
||||||
if (!(pre = $$('.prettyprint', post.nodes.comment)[+e.detail.i])) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!$.hasClass(pre, 'prettyprinted')) {
|
if (!$.hasClass(pre, 'prettyprinted')) {
|
||||||
pre.innerHTML = e.detail.html
|
pre.innerHTML = e.detail.html;
|
||||||
return $.addClass(pre, 'prettyprinted')
|
return $.addClass(pre, 'prettyprinted');
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
$.global(() =>
|
$.global(() => window.addEventListener('prettyprint', e => window.dispatchEvent(new CustomEvent('prettyprint:cb', {
|
||||||
window.addEventListener(
|
detail: {
|
||||||
'prettyprint',
|
ID: e.detail.ID,
|
||||||
(e) =>
|
i: e.detail.i,
|
||||||
window.dispatchEvent(
|
html: window.prettyPrintOne(e.detail.html)
|
||||||
new CustomEvent('prettyprint:cb', {
|
}
|
||||||
detail: {
|
}))
|
||||||
ID: e.detail.ID,
|
, false));
|
||||||
i: e.detail.i,
|
|
||||||
html: window.prettyPrintOne(e.detail.html),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
Callbacks.Post.push({
|
Callbacks.Post.push({
|
||||||
name: 'Parse [code] tags',
|
name: 'Parse [code] tags',
|
||||||
cb: Fourchan.code,
|
cb: Fourchan.code
|
||||||
})
|
});
|
||||||
g.posts.forEach(function (post) {
|
g.posts.forEach(function (post) {
|
||||||
if (post.callbacksExecuted) {
|
if (post.callbacksExecuted) {
|
||||||
return Callbacks.Post.execute(post, ['Parse [code] tags'], true)
|
return Callbacks.Post.execute(post, ['Parse [code] tags'], true);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
ExpandComment.callbacks.push(Fourchan.code)
|
ExpandComment.callbacks.push(Fourchan.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g.BOARD.config.math_tags) {
|
if (g.BOARD.config.math_tags) {
|
||||||
$.global(() =>
|
$.global(() => window.addEventListener('mathjax', function (e) {
|
||||||
window.addEventListener(
|
if (window.MathJax) {
|
||||||
'mathjax',
|
return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]);
|
||||||
function (e) {
|
} else {
|
||||||
if (window.MathJax) {
|
if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { // don't load MathJax if already loading
|
||||||
return window.MathJax.Hub.Queue([
|
window.loadMathJax();
|
||||||
'Typeset',
|
window.loadMathJax = function () { };
|
||||||
window.MathJax.Hub,
|
}
|
||||||
e.target,
|
// 4chan only handles post comments on MathJax load; anything else (e.g. the QR preview) must be queued explicitly.
|
||||||
])
|
if (!e.target.classList.contains('postMessage')) {
|
||||||
} else {
|
return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', () => window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target])
|
||||||
if (
|
, false);
|
||||||
!document.querySelector('script[src^="//cdn.mathjax.org/"]')
|
}
|
||||||
) {
|
}
|
||||||
// don't load MathJax if already loading
|
}
|
||||||
window.loadMathJax()
|
, false));
|
||||||
window.loadMathJax = function () {}
|
|
||||||
}
|
|
||||||
// 4chan only handles post comments on MathJax load; anything else (e.g. the QR preview) must be queued explicitly.
|
|
||||||
if (!e.target.classList.contains('postMessage')) {
|
|
||||||
return document
|
|
||||||
.querySelector('script[src^="//cdn.mathjax.org/"]')
|
|
||||||
.addEventListener(
|
|
||||||
'load',
|
|
||||||
() =>
|
|
||||||
window.MathJax.Hub.Queue([
|
|
||||||
'Typeset',
|
|
||||||
window.MathJax.Hub,
|
|
||||||
e.target,
|
|
||||||
]),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
Callbacks.Post.push({
|
Callbacks.Post.push({
|
||||||
name: 'Parse [math] tags',
|
name: 'Parse [math] tags',
|
||||||
cb: Fourchan.math,
|
cb: Fourchan.math
|
||||||
})
|
});
|
||||||
g.posts.forEach(function (post) {
|
g.posts.forEach(function (post) {
|
||||||
if (post.callbacksExecuted) {
|
if (post.callbacksExecuted) {
|
||||||
return Callbacks.Post.execute(post, ['Parse [math] tags'], true)
|
return Callbacks.Post.execute(post, ['Parse [math] tags'], true);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
return ExpandComment.callbacks.push(Fourchan.math)
|
return ExpandComment.callbacks.push(Fourchan.math);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Disable 4chan's ID highlighting (replaced by IDHighlight) and reported post hiding.
|
// Disable 4chan's ID highlighting (replaced by IDHighlight) and reported post hiding.
|
||||||
initReady() {
|
initReady() {
|
||||||
return $.global(function () {
|
return $.global(function () {
|
||||||
window.clickable_ids = false
|
window.clickable_ids = false;
|
||||||
for (var node of document.querySelectorAll('.posteruid, .capcode')) {
|
for (var node of document.querySelectorAll('.posteruid, .capcode')) {
|
||||||
node.removeEventListener('click', window.idClick, false)
|
node.removeEventListener('click', window.idClick, false);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
code() {
|
code() {
|
||||||
if (this.isClone) {
|
if (this.isClone) { return; }
|
||||||
return
|
|
||||||
}
|
|
||||||
return $.ready(() => {
|
return $.ready(() => {
|
||||||
const iterable = $$('.prettyprint', this.nodes.comment)
|
const iterable = $$('.prettyprint', this.nodes.comment);
|
||||||
for (let i = 0; i < iterable.length; i++) {
|
for (let i = 0; i < iterable.length; i++) {
|
||||||
var pre = iterable[i]
|
var pre = iterable[i];
|
||||||
if (!$.hasClass(pre, 'prettyprinted')) {
|
if (!$.hasClass(pre, 'prettyprinted')) {
|
||||||
$.event(
|
$.event('prettyprint', { ID: this.fullID, i, html: pre.innerHTML }, window);
|
||||||
'prettyprint',
|
|
||||||
{ ID: this.fullID, i, html: pre.innerHTML },
|
|
||||||
window,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
math() {
|
math() {
|
||||||
let wbrs
|
let wbrs;
|
||||||
if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) {
|
if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { return; }
|
||||||
return
|
|
||||||
}
|
|
||||||
// XXX <wbr> tags frequently break MathJax; remove them.
|
// XXX <wbr> tags frequently break MathJax; remove them.
|
||||||
if ((wbrs = $$('wbr', this.nodes.comment)).length) {
|
if ((wbrs = $$('wbr', this.nodes.comment)).length) {
|
||||||
for (var wbr of wbrs) {
|
for (var wbr of wbrs) { $.rm(wbr); }
|
||||||
$.rm(wbr)
|
this.nodes.comment.normalize();
|
||||||
}
|
|
||||||
this.nodes.comment.normalize()
|
|
||||||
}
|
}
|
||||||
var cb = () => {
|
var cb = () => {
|
||||||
if (!doc.contains(this.nodes.comment)) {
|
if (!doc.contains(this.nodes.comment)) { return; }
|
||||||
return
|
$.off(d, 'PostsInserted', cb);
|
||||||
}
|
return $.event('mathjax', null, this.nodes.comment);
|
||||||
$.off(d, 'PostsInserted', cb)
|
};
|
||||||
return $.event('mathjax', null, this.nodes.comment)
|
$.on(d, 'PostsInserted', cb);
|
||||||
}
|
return cb();
|
||||||
$.on(d, 'PostsInserted', cb)
|
}
|
||||||
return cb()
|
};
|
||||||
},
|
export default Fourchan;
|
||||||
}
|
|
||||||
export default Fourchan
|
|
||||||
|
|||||||
@ -1,70 +1,55 @@
|
|||||||
import Callbacks from '../classes/Callbacks'
|
import Callbacks from "../classes/Callbacks";
|
||||||
import { g, Conf } from '../globals/globals'
|
import { g, Conf } from "../globals/globals";
|
||||||
import $ from '../platform/$'
|
import $ from "../platform/$";
|
||||||
import { dict } from '../platform/helpers'
|
import { dict } from "../platform/helpers";
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
var IDColor = {
|
var IDColor = {
|
||||||
init() {
|
init() {
|
||||||
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Color User IDs']) {
|
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Color User IDs']) { return; }
|
||||||
return
|
this.ids = dict();
|
||||||
}
|
this.ids['Heaven'] = [0, 0, 0, '#fff'];
|
||||||
this.ids = dict()
|
|
||||||
this.ids['Heaven'] = [0, 0, 0, '#fff']
|
|
||||||
|
|
||||||
return Callbacks.Post.push({
|
return Callbacks.Post.push({
|
||||||
name: 'Color User IDs',
|
name: 'Color User IDs',
|
||||||
cb: this.node,
|
cb: this.node
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
node() {
|
node() {
|
||||||
let span, uid
|
let span, uid;
|
||||||
if (
|
if (this.isClone || !((uid = this.info.uniqueID) && (span = this.nodes.uniqueID))) { return; }
|
||||||
this.isClone ||
|
|
||||||
!((uid = this.info.uniqueID) && (span = this.nodes.uniqueID))
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const rgb = IDColor.ids[uid] || IDColor.compute(uid)
|
const rgb = IDColor.ids[uid] || IDColor.compute(uid);
|
||||||
|
|
||||||
// Style the damn node.
|
// Style the damn node.
|
||||||
const { style } = span
|
const { style } = span;
|
||||||
style.color = rgb[3]
|
style.color = rgb[3];
|
||||||
style.backgroundColor = `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`
|
style.backgroundColor = `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`;
|
||||||
return $.addClass(span, 'painted')
|
return $.addClass(span, 'painted');
|
||||||
},
|
},
|
||||||
|
|
||||||
compute(uid) {
|
compute(uid) {
|
||||||
// Convert chars to integers, bitshift and math to create a larger integer
|
// Convert chars to integers, bitshift and math to create a larger integer
|
||||||
// Create a nice string of binary
|
// Create a nice string of binary
|
||||||
let hash;
|
const hash = g.SITE.uidColor ? g.SITE.uidColor(uid) : parseInt(uid, 16);
|
||||||
if (typeof g !== 'undefined' && g.SITE && g.SITE.uidColor) {
|
|
||||||
hash = g.SITE.uidColor(uid);
|
|
||||||
} else {
|
|
||||||
hash = parseInt(uid, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert binary string to numerical values with bitshift and '&' truncation.
|
// Convert binary string to numerical values with bitshift and '&' truncation.
|
||||||
const rgb = [(hash >> 16) & 0xff, (hash >> 8) & 0xff, hash & 0xff];
|
const rgb = [
|
||||||
|
(hash >> 16) & 0xFF,
|
||||||
// Weight color luminance values, assign a font color that should be readable.
|
(hash >> 8) & 0xFF,
|
||||||
const fontColor = $.luma ? ($.luma(rgb) > 125 ? '#000' : '#fff') : '#000';
|
hash & 0xFF
|
||||||
|
];
|
||||||
// Cache color and font color.
|
|
||||||
const colorCode = `rgb(${rgb.join(',')})`;
|
// Weight color luminance values, assign a font color that should be readable.
|
||||||
this.ids[uid] = {
|
rgb.push($.luma(rgb) > 125 ?
|
||||||
color: colorCode,
|
'#000'
|
||||||
fontColor: fontColor
|
:
|
||||||
};
|
'#fff'
|
||||||
|
);
|
||||||
// Return only the color.
|
|
||||||
return colorCode;
|
// Cache.
|
||||||
},
|
return this.ids[uid] = rgb;
|
||||||
}
|
}
|
||||||
export default IDColor
|
};
|
||||||
|
export default IDColor;
|
||||||
|
|||||||
@ -1,50 +1,37 @@
|
|||||||
import Callbacks from '../classes/Callbacks'
|
import Callbacks from "../classes/Callbacks";
|
||||||
import { g } from '../globals/globals'
|
import { g } from "../globals/globals";
|
||||||
import $ from '../platform/$'
|
import $ from "../platform/$";
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
var IDHighlight = {
|
var IDHighlight = {
|
||||||
init() {
|
init() {
|
||||||
if (!['index', 'thread'].includes(g.VIEW)) {
|
if (!['index', 'thread'].includes(g.VIEW)) { return; }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return Callbacks.Post.push({
|
return Callbacks.Post.push({
|
||||||
name: 'Highlight by User ID',
|
name: 'Highlight by User ID',
|
||||||
cb: this.node,
|
cb: this.node
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
uniqueID: null,
|
uniqueID: null,
|
||||||
|
|
||||||
node() {
|
node() {
|
||||||
if (this.nodes.uniqueIDRoot) {
|
if (this.nodes.uniqueIDRoot) { $.on(this.nodes.uniqueIDRoot, 'click', IDHighlight.click(this)); }
|
||||||
$.on(this.nodes.uniqueIDRoot, 'click', IDHighlight.click(this))
|
if (this.nodes.capcode) { $.on(this.nodes.capcode, 'click', IDHighlight.click(this)); }
|
||||||
}
|
if (!this.isClone) { return IDHighlight.set(this); }
|
||||||
if (this.nodes.capcode) {
|
|
||||||
$.on(this.nodes.capcode, 'click', IDHighlight.click(this))
|
|
||||||
}
|
|
||||||
if (!this.isClone) {
|
|
||||||
return IDHighlight.set(this)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
set(post) {
|
set(post) {
|
||||||
const match =
|
const match = (post.info.uniqueID || post.info.capcode) === IDHighlight.uniqueID;
|
||||||
(post.info.uniqueID || post.info.capcode) === IDHighlight.uniqueID
|
return $[match ? 'addClass' : 'rmClass'](post.nodes.post, 'highlight');
|
||||||
return $[match ? 'addClass' : 'rmClass'](post.nodes.post, 'highlight')
|
|
||||||
},
|
},
|
||||||
|
|
||||||
click(post) {
|
click(post) {
|
||||||
return function () {
|
return function () {
|
||||||
const uniqueID = post.info.uniqueID || post.info.capcode
|
const uniqueID = post.info.uniqueID || post.info.capcode;
|
||||||
IDHighlight.uniqueID = IDHighlight.uniqueID === uniqueID ? null : uniqueID
|
IDHighlight.uniqueID = IDHighlight.uniqueID === uniqueID ? null : uniqueID;
|
||||||
return g.posts.forEach(IDHighlight.set)
|
return g.posts.forEach(IDHighlight.set);
|
||||||
}
|
};
|
||||||
},
|
}
|
||||||
}
|
};
|
||||||
export default IDHighlight
|
export default IDHighlight;
|
||||||
|
|||||||
@ -4,15 +4,15 @@ import Main from '../main/Main'
|
|||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
|
|
||||||
const PSA = {
|
const PSA = {
|
||||||
init() {
|
init(): void {
|
||||||
let el
|
let el: HTMLElement
|
||||||
if (g.SITE.software === 'yotsuba' && g.BOARD.ID === 'qa') {
|
if (g.SITE.software === 'yotsuba' && g.BOARD.ID === 'qa') {
|
||||||
const announcement = {
|
const announcement = {
|
||||||
innerHTML:
|
innerHTML:
|
||||||
'Stay in touch with your <a href="https://www.4chan-x.net/qa_friends.html" target="_blank" rel="noopener">/qa/ friends</a>!',
|
'Stay in touch with your <a href="https://www.4chan-x.net/qa_friends.html" target="_blank" rel="noopener">/qa/ friends</a>!',
|
||||||
}
|
}
|
||||||
el = $.el('div', { className: 'fcx-announcement' }, announcement)
|
el = $.el('span', announcement) as HTMLElement
|
||||||
$.onExists(doc, '.boardBanner', (banner) => $.after(banner, el))
|
$.onExists(doc, '.boardBanner', (banner: HTMLElement) => $.after(banner, el))
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
'samachan.org' in Conf['siteProperties'] &&
|
'samachan.org' in Conf['siteProperties'] &&
|
||||||
@ -8,7 +8,7 @@ import { g, Conf } from '../globals/globals'
|
|||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
||||||
*/
|
*/
|
||||||
var Time = {
|
var Time = {
|
||||||
init() {
|
init(): VoidFunction {
|
||||||
if (
|
if (
|
||||||
!['index', 'thread', 'archive'].includes(g.VIEW) ||
|
!['index', 'thread', 'archive'].includes(g.VIEW) ||
|
||||||
!Conf['Time Formatting']
|
!Conf['Time Formatting']
|
||||||
@ -22,18 +22,15 @@ var Time = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
node() {
|
node(): any {
|
||||||
if (!this.info.date || this.isClone) {
|
if (!this.info.date || this.isClone) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
const { textContent } = this.nodes.date
|
const { textContent } = this.nodes.date;
|
||||||
return (this.nodes.date.textContent =
|
return this.nodes.date.textContent = textContent.match(/^\s*/)[0] + Time.format(Conf['time'], this.info.date) + textContent.match(/\s*$/)[0];
|
||||||
textContent.match(/^\s*/)[0] +
|
|
||||||
Time.format(Conf['time'], this.info.date) +
|
|
||||||
textContent.match(/\s*$/)[0])
|
|
||||||
},
|
},
|
||||||
|
|
||||||
format(formatString, date) {
|
format(formatString: string, date: Date): string {
|
||||||
return formatString.replace(/%(.)/g, function (s, c) {
|
return formatString.replace(/%(.)/g, function (s, c) {
|
||||||
if ($.hasOwn(Time.formatters, c)) {
|
if ($.hasOwn(Time.formatters, c)) {
|
||||||
return Time.formatters[c].call(date)
|
return Time.formatters[c].call(date)
|
||||||
@ -68,16 +65,16 @@ var Time = {
|
|||||||
'December',
|
'December',
|
||||||
],
|
],
|
||||||
|
|
||||||
localeFormat(date, options, defaultValue) {
|
localeFormat(date: Date, options: any, defaultValue: string): string {
|
||||||
if (Conf['timeLocale']) {
|
if (Conf['timeLocale']) {
|
||||||
try {
|
try {
|
||||||
return Intl.DateTimeFormat(Conf['timeLocale'], options).format(date)
|
return Intl.DateTimeFormat(Conf['timeLocale'], options).format(date)
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
}
|
}
|
||||||
return defaultValue
|
return defaultValue
|
||||||
},
|
},
|
||||||
|
|
||||||
localeFormatPart(date, options, part, defaultValue) {
|
localeFormatPart(date: Date, options: any, part: string, defaultValue: string): string {
|
||||||
if (Conf['timeLocale']) {
|
if (Conf['timeLocale']) {
|
||||||
try {
|
try {
|
||||||
const parts = Intl.DateTimeFormat(
|
const parts = Intl.DateTimeFormat(
|
||||||
@ -93,12 +90,12 @@ var Time = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.join('')
|
.join('')
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
}
|
}
|
||||||
return defaultValue
|
return defaultValue
|
||||||
},
|
},
|
||||||
|
|
||||||
zeroPad(n) {
|
zeroPad(n: number): number | string {
|
||||||
if (n < 10) {
|
if (n < 10) {
|
||||||
return `0${n}`
|
return `0${n}`
|
||||||
} else {
|
} else {
|
||||||
@ -107,59 +104,59 @@ var Time = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
formatters: {
|
formatters: {
|
||||||
a() {
|
a(): string {
|
||||||
return Time.localeFormat(
|
return Time.localeFormat(
|
||||||
this,
|
this,
|
||||||
{ weekday: 'short' },
|
{ weekday: 'short' },
|
||||||
Time.day[this.getDay()].slice(0, 3),
|
Time.day[this.getDay()].slice(0, 3),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
A() {
|
A(): string {
|
||||||
return Time.localeFormat(
|
return Time.localeFormat(
|
||||||
this,
|
this,
|
||||||
{ weekday: 'long' },
|
{ weekday: 'long' },
|
||||||
Time.day[this.getDay()],
|
Time.day[this.getDay()],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
b() {
|
b(): string {
|
||||||
return Time.localeFormat(
|
return Time.localeFormat(
|
||||||
this,
|
this,
|
||||||
{ month: 'short' },
|
{ month: 'short' },
|
||||||
Time.month[this.getMonth()].slice(0, 3),
|
Time.month[this.getMonth()].slice(0, 3),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
B() {
|
B(): string {
|
||||||
return Time.localeFormat(
|
return Time.localeFormat(
|
||||||
this,
|
this,
|
||||||
{ month: 'long' },
|
{ month: 'long' },
|
||||||
Time.month[this.getMonth()],
|
Time.month[this.getMonth()],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
d() {
|
d(): string | number {
|
||||||
return Time.zeroPad(this.getDate())
|
return Time.zeroPad(this.getDate())
|
||||||
},
|
},
|
||||||
e() {
|
e(): number {
|
||||||
return this.getDate()
|
return this.getDate()
|
||||||
},
|
},
|
||||||
H() {
|
H(): string | number {
|
||||||
return Time.zeroPad(this.getHours())
|
return Time.zeroPad(this.getHours())
|
||||||
},
|
},
|
||||||
I() {
|
I(): string | number {
|
||||||
return Time.zeroPad(this.getHours() % 12 || 12)
|
return Time.zeroPad(this.getHours() % 12 || 12)
|
||||||
},
|
},
|
||||||
k() {
|
k(): number {
|
||||||
return this.getHours()
|
return this.getHours()
|
||||||
},
|
},
|
||||||
l() {
|
l(): number {
|
||||||
return this.getHours() % 12 || 12
|
return this.getHours() % 12 || 12
|
||||||
},
|
},
|
||||||
m() {
|
m(): string | number {
|
||||||
return Time.zeroPad(this.getMonth() + 1)
|
return Time.zeroPad(this.getMonth() + 1)
|
||||||
},
|
},
|
||||||
M() {
|
M(): string | number {
|
||||||
return Time.zeroPad(this.getMinutes())
|
return Time.zeroPad(this.getMinutes())
|
||||||
},
|
},
|
||||||
p() {
|
p(): string {
|
||||||
return Time.localeFormatPart(
|
return Time.localeFormatPart(
|
||||||
this,
|
this,
|
||||||
{ hour: 'numeric', hour12: true },
|
{ hour: 'numeric', hour12: true },
|
||||||
@ -167,19 +164,19 @@ var Time = {
|
|||||||
this.getHours() < 12 ? 'AM' : 'PM',
|
this.getHours() < 12 ? 'AM' : 'PM',
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
P() {
|
P(): string {
|
||||||
return Time.formatters.p.call(this).toLowerCase()
|
return Time.formatters.p.call(this).toLowerCase()
|
||||||
},
|
},
|
||||||
S() {
|
S(): string | number {
|
||||||
return Time.zeroPad(this.getSeconds())
|
return Time.zeroPad(this.getSeconds())
|
||||||
},
|
},
|
||||||
y() {
|
y(): string {
|
||||||
return this.getFullYear().toString().slice(2)
|
return this.getFullYear().toString().slice(2)
|
||||||
},
|
},
|
||||||
Y() {
|
Y(): number {
|
||||||
return this.getFullYear()
|
return this.getFullYear()
|
||||||
},
|
},
|
||||||
'%'() {
|
'%'(): string {
|
||||||
return '%'
|
return '%'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import SWTinyboard from './SW.tinyboard'
|
import SWTinyboard from './SW.tinyboard'
|
||||||
import SWYotsuba from './SW.yotsuba'
|
import SWYotsuba from './SW.yotsuba'
|
||||||
|
|
||||||
const SW = { tinyboard: SWTinyboard, yotsuba: SWYotsuba }
|
const SW = { tinyboard: SWTinyboard, yotsuba: SWYotsuba } as const
|
||||||
export default SW
|
export default SW
|
||||||
@ -19,7 +19,7 @@ var Site = {
|
|||||||
'smug.nepu.moe': { canonical: 'smuglo.li' },
|
'smug.nepu.moe': { canonical: 'smuglo.li' },
|
||||||
},
|
},
|
||||||
|
|
||||||
init(cb) {
|
init(cb: () => void): void {
|
||||||
$.extend(Conf['siteProperties'], Site.defaultProperties)
|
$.extend(Conf['siteProperties'], Site.defaultProperties)
|
||||||
let hostname = Site.resolve()
|
let hostname = Site.resolve()
|
||||||
if (hostname && $.hasOwn(SW, Conf['siteProperties'][hostname].software)) {
|
if (hostname && $.hasOwn(SW, Conf['siteProperties'][hostname].software)) {
|
||||||
@ -28,7 +28,7 @@ var Site = {
|
|||||||
}
|
}
|
||||||
return $.onExists(doc, 'body', () => {
|
return $.onExists(doc, 'body', () => {
|
||||||
for (var software in SW) {
|
for (var software in SW) {
|
||||||
var changes
|
var changes: { [key: string]: string }
|
||||||
if ((changes = SW[software].detect?.())) {
|
if ((changes = SW[software].detect?.())) {
|
||||||
changes.software = software
|
changes.software = software
|
||||||
hostname = location.hostname.replace(/^www\./, '')
|
hostname = location.hostname.replace(/^www\./, '')
|
||||||
@ -55,7 +55,7 @@ var Site = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
resolve(url = location) {
|
resolve(url = location): string {
|
||||||
let { hostname } = url
|
let { hostname } = url
|
||||||
while (hostname && !$.hasOwn(Conf['siteProperties'], hostname)) {
|
while (hostname && !$.hasOwn(Conf['siteProperties'], hostname)) {
|
||||||
hostname = hostname.replace(/^[^.]*\.?/, '')
|
hostname = hostname.replace(/^[^.]*\.?/, '')
|
||||||
@ -69,14 +69,14 @@ var Site = {
|
|||||||
return hostname
|
return hostname
|
||||||
},
|
},
|
||||||
|
|
||||||
parseURL(url) {
|
parseURL(url: Location): ReturnType<typeof Main.parseURL> {
|
||||||
const siteID = Site.resolve(url)
|
var siteID = Site.resolve(url)
|
||||||
return Main.parseURL(g.sites[siteID], url)
|
return siteID ? g.sites[siteID].parseURL(url) : null
|
||||||
},
|
},
|
||||||
|
|
||||||
set(hostname) {
|
set(hostname: string): typeof g.SITE {
|
||||||
for (var ID in Conf['siteProperties']) {
|
for (var ID in Conf['siteProperties']) {
|
||||||
var site
|
var site: typeof g.SITE
|
||||||
var properties = Conf['siteProperties'][ID]
|
var properties = Conf['siteProperties'][ID]
|
||||||
if (properties.canonical) {
|
if (properties.canonical) {
|
||||||
continue
|
continue
|
||||||
Loading…
x
Reference in New Issue
Block a user