mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2026-03-20 01:37:47 +01:00
Typescript and more
This commit is contained in:
parent
23cf79092b
commit
12483e97c5
@ -10,7 +10,22 @@ import { dict, HOUR } from '../platform/helpers'
|
|||||||
* DS205: Consider reworking code to avoid use of IIFEs
|
* DS205: Consider reworking code to avoid use of IIFEs
|
||||||
* 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 BoardConfig = {
|
|
||||||
|
interface BoardConfig {
|
||||||
|
cbs: (() => void)[]
|
||||||
|
init(): void
|
||||||
|
load(): void
|
||||||
|
set(boards: { [key: string]: any }): void
|
||||||
|
ready(cb: () => void): void
|
||||||
|
sfwBoards(sfw: boolean): string[]
|
||||||
|
isSFW(board: string): boolean
|
||||||
|
domain(board: string): string
|
||||||
|
isArchived(board: string): boolean
|
||||||
|
noAudio(boardID: string): boolean
|
||||||
|
title(boardID: string): string
|
||||||
|
}
|
||||||
|
|
||||||
|
var BoardConfig: BoardConfig = {
|
||||||
cbs: [],
|
cbs: [],
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -161,7 +161,9 @@ aero|asia|biz|cat|com|coop|dance|info|int|jobs|mobi|moe|museum|name|net|org|post
|
|||||||
|\
|
|\
|
||||||
[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}\
|
[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}\
|
||||||
|\
|
|\
|
||||||
|
(\
|
||||||
[-\\w\\d.@]+@[a-z\\d.-]+\\.[a-z\\d]\
|
[-\\w\\d.@]+@[a-z\\d.-]+\\.[a-z\\d]\
|
||||||
|
)\
|
||||||
)`,
|
)`,
|
||||||
'i',
|
'i',
|
||||||
),
|
),
|
||||||
|
|||||||
@ -45,7 +45,7 @@ var ReportLink = {
|
|||||||
const { url, dims } = ReportLink
|
const { url, dims } = ReportLink
|
||||||
const id = Date.now()
|
const id = Date.now()
|
||||||
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, id, set)
|
return window.open(url, id.toString(), set)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
export default ReportLink
|
export default ReportLink
|
||||||
|
|||||||
@ -1,161 +0,0 @@
|
|||||||
import Redirect from '../Archive/Redirect'
|
|
||||||
import $ from '../platform/$'
|
|
||||||
import ReportPage from './Report/ArchiveReport.html'
|
|
||||||
import CSS from '../css/CSS'
|
|
||||||
import Captcha from '../Posting/Captcha'
|
|
||||||
import { Conf, d, g } 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Report = {
|
|
||||||
init() {
|
|
||||||
let match
|
|
||||||
if (!(match = location.search.match(/\bno=(\d+)/))) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Captcha.replace.init()
|
|
||||||
this.postID = +match[1]
|
|
||||||
return $.ready(this.ready)
|
|
||||||
},
|
|
||||||
|
|
||||||
ready() {
|
|
||||||
$.addStyle(CSS.report)
|
|
||||||
|
|
||||||
if (Conf['Archive Report']) {
|
|
||||||
Report.archive()
|
|
||||||
}
|
|
||||||
|
|
||||||
new MutationObserver(function () {
|
|
||||||
Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]')
|
|
||||||
return Report.fit('body')
|
|
||||||
}).observe(d.body, {
|
|
||||||
childList: true,
|
|
||||||
attributes: true,
|
|
||||||
subtree: true,
|
|
||||||
})
|
|
||||||
return Report.fit('body')
|
|
||||||
},
|
|
||||||
|
|
||||||
fit(selector) {
|
|
||||||
let el
|
|
||||||
if (
|
|
||||||
!((el = $(selector, el)) && getComputedStyle(el).visibility !== 'hidden')
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const dy = el.getBoundingClientRect().bottom - el.clientHeight + 8
|
|
||||||
if (dy > 0) {
|
|
||||||
return window.resizeBy(0, dy)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
archive() {
|
|
||||||
let match, urls
|
|
||||||
if (!(urls = Redirect.report(g.BOARD.ID)).length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const form = $('form')
|
|
||||||
const types = $.id('reportTypes')
|
|
||||||
const message = $('h3')
|
|
||||||
|
|
||||||
const fieldset = $.el(
|
|
||||||
'fieldset',
|
|
||||||
{
|
|
||||||
id: 'archive-report',
|
|
||||||
hidden: true,
|
|
||||||
},
|
|
||||||
{ innerHTML: ReportPage },
|
|
||||||
)
|
|
||||||
const enabled = $('#archive-report-enabled', fieldset)
|
|
||||||
const reason = $('#archive-report-reason', fieldset)
|
|
||||||
const submit = $('#archive-report-submit', fieldset)
|
|
||||||
|
|
||||||
$.on(enabled, 'change', function () {
|
|
||||||
return (reason.disabled = !this.checked)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (form && types) {
|
|
||||||
fieldset.hidden = !$('[value="31"]', types).checked
|
|
||||||
$.on(types, 'change', function (e) {
|
|
||||||
fieldset.hidden = e.target.value !== '31'
|
|
||||||
return Report.fit('body')
|
|
||||||
})
|
|
||||||
$.after(types, fieldset)
|
|
||||||
Report.fit('body')
|
|
||||||
$.one(form, 'submit', function (e) {
|
|
||||||
if (!fieldset.hidden && enabled.checked) {
|
|
||||||
e.preventDefault()
|
|
||||||
return Report.archiveSubmit(urls, reason.value, (results) => {
|
|
||||||
this.action =
|
|
||||||
'#archiveresults=' + encodeURIComponent(JSON.stringify(results))
|
|
||||||
return this.submit()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if (message) {
|
|
||||||
fieldset.hidden = /Report submitted!/.test(message.textContent)
|
|
||||||
$.on(enabled, 'change', function () {
|
|
||||||
return (submit.hidden = !this.checked)
|
|
||||||
})
|
|
||||||
$.after(message, fieldset)
|
|
||||||
$.on(submit, 'click', () =>
|
|
||||||
Report.archiveSubmit(urls, reason.value, Report.archiveResults),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((match = location.hash.match(/^#archiveresults=(.*)$/))) {
|
|
||||||
try {
|
|
||||||
return Report.archiveResults(JSON.parse(decodeURIComponent(match[1])))
|
|
||||||
} catch (error) {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
archiveSubmit(urls, reason, cb) {
|
|
||||||
const form = $.formData({
|
|
||||||
board: g.BOARD.ID,
|
|
||||||
num: Report.postID,
|
|
||||||
reason,
|
|
||||||
})
|
|
||||||
const results = []
|
|
||||||
for (var [name, url] of urls) {
|
|
||||||
;(function (name, url) {
|
|
||||||
return $.ajax(url, {
|
|
||||||
onloadend() {
|
|
||||||
results.push([name, this.response || { error: '' }])
|
|
||||||
if (results.length === urls.length) {
|
|
||||||
return cb(results)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
form,
|
|
||||||
})
|
|
||||||
})(name, url)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
archiveResults(results) {
|
|
||||||
const fieldset = $.id('archive-report')
|
|
||||||
for (var [name, response] of results) {
|
|
||||||
var line = $.el('h3', { className: 'archive-report-response' })
|
|
||||||
if ('success' in response) {
|
|
||||||
$.addClass(line, 'archive-report-success')
|
|
||||||
line.textContent = `${name}: ${response.success}`
|
|
||||||
} else {
|
|
||||||
$.addClass(line, 'archive-report-error')
|
|
||||||
line.textContent = `${name}: ${
|
|
||||||
response.error || 'Error reporting post.'
|
|
||||||
}`
|
|
||||||
}
|
|
||||||
if (fieldset) {
|
|
||||||
$.before(fieldset, line)
|
|
||||||
} else {
|
|
||||||
$.add(d.body, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
export default Report
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
import CaptchaReplace from './Captcha.replace'
|
|
||||||
import CaptchaT from './Captcha.t'
|
import CaptchaT from './Captcha.t'
|
||||||
import meta from '../../package.json'
|
import meta from '../../package.json'
|
||||||
import Main from '../main/Main'
|
import Main from '../main/Main'
|
||||||
@ -178,7 +177,6 @@ const Captcha = {
|
|||||||
return $.event('CaptchaCount', this.captchas.length)
|
return $.event('CaptchaCount', this.captchas.length)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Replace: CaptchaReplace,
|
|
||||||
t: CaptchaT,
|
t: CaptchaT,
|
||||||
v2: {
|
v2: {
|
||||||
lifetime: 2 * MINUTE,
|
lifetime: 2 * MINUTE,
|
||||||
|
|||||||
@ -1,79 +0,0 @@
|
|||||||
import { g, Conf, doc, d } from '../globals/globals'
|
|
||||||
import Main from '../main/Main'
|
|
||||||
import $ from '../platform/$'
|
|
||||||
import Captcha from './Captcha'
|
|
||||||
|
|
||||||
const CaptchaReplace = {
|
|
||||||
init() {
|
|
||||||
if (
|
|
||||||
g.SITE.software !== 'yotsuba' ||
|
|
||||||
d.cookie.indexOf('pass_enabled=1') >= 0
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Conf['Force Noscript Captcha'] && Main.jsEnabled) {
|
|
||||||
$.ready(Captcha.replace.noscript)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Conf['captchaLanguage'].trim()) {
|
|
||||||
if (
|
|
||||||
['boards.4chan.org', 'boards.4channel.org'].includes(location.hostname)
|
|
||||||
) {
|
|
||||||
return $.onExists(doc, '#captchaFormPart', (node) =>
|
|
||||||
$.onExists(
|
|
||||||
node,
|
|
||||||
'iframe[src^="https://www.google.com/recaptcha/"]',
|
|
||||||
Captcha.replace.iframe,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return $.onExists(
|
|
||||||
doc,
|
|
||||||
'iframe[src^="https://www.google.com/recaptcha/"]',
|
|
||||||
Captcha.replace.iframe,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
noscript() {
|
|
||||||
let noscript, original, toggle
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
(original = $('#g-recaptcha')) &&
|
|
||||||
(noscript = $('noscript', original.parentNode))
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const span = $.el('span', { id: 'captcha-forced-noscript' })
|
|
||||||
$.replace(noscript, span)
|
|
||||||
$.rm(original)
|
|
||||||
const insert = function () {
|
|
||||||
span.innerHTML = noscript.textContent
|
|
||||||
return Captcha.replace.iframe(
|
|
||||||
$('iframe[src^="https://www.google.com/recaptcha/"]', span),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if ((toggle = $('#togglePostFormLink a, #form-link'))) {
|
|
||||||
return $.on(toggle, 'click', insert)
|
|
||||||
} else {
|
|
||||||
return insert()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
iframe(iframe) {
|
|
||||||
let lang
|
|
||||||
if ((lang = Conf['captchaLanguage'].trim())) {
|
|
||||||
const src = /[?&]hl=/.test(iframe.src)
|
|
||||||
? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang))
|
|
||||||
: iframe.src + `&hl=${encodeURIComponent(lang)}`
|
|
||||||
if (iframe.src !== src) {
|
|
||||||
iframe.src = src
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
export default CaptchaReplace
|
|
||||||
@ -11,7 +11,7 @@ const PassLink = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ready(): void {
|
ready(): void {
|
||||||
let styleSelector
|
let styleSelector: HTMLElement
|
||||||
if (!(styleSelector = $.id('styleSelector'))) {
|
if (!(styleSelector = $.id('styleSelector'))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,8 @@
|
|||||||
import { d } from '../globals/globals'
|
import { d } 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
|
|
||||||
*/
|
|
||||||
const PostRedirect = {
|
const PostRedirect = {
|
||||||
init() {
|
init(): void {
|
||||||
return $.on(d, 'QRPostSuccessful', (e) => {
|
return $.on(d, 'QRPostSuccessful', (e) => {
|
||||||
if (!e.detail.redirect) {
|
if (!e.detail.redirect) {
|
||||||
return
|
return
|
||||||
@ -24,7 +19,7 @@ const PostRedirect = {
|
|||||||
|
|
||||||
delays: 0,
|
delays: 0,
|
||||||
|
|
||||||
delay() {
|
delay(): (() => void) | null {
|
||||||
if (!this.event) {
|
if (!this.event) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -69,14 +69,7 @@ var QuotePreview = {
|
|||||||
$.add(Header.hover, qp)
|
$.add(Header.hover, qp)
|
||||||
new Fetcher(boardID, threadID, postID, qp, Get.postFromNode(this))
|
new Fetcher(boardID, threadID, postID, qp, Get.postFromNode(this))
|
||||||
|
|
||||||
UI.hover({
|
UI.hover({root: this, el: qp, latestEvent: e, endEvents: 'mouseout click', cb: QuotePreview.mouseout, cbArgs: [this]})
|
||||||
root: this,
|
|
||||||
el: qp,
|
|
||||||
latestEvent: e,
|
|
||||||
endEvents: 'mouseout click',
|
|
||||||
cb: QuotePreview.mouseout,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
Conf['Quote Highlighting'] &&
|
Conf['Quote Highlighting'] &&
|
||||||
(origin = g.posts.get(`${boardID}.${postID}`))
|
(origin = g.posts.get(`${boardID}.${postID}`))
|
||||||
|
|||||||
@ -3,13 +3,8 @@ import Get from '../General/Get'
|
|||||||
import { g, Conf } from '../globals/globals'
|
import { g, Conf } 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
|
|
||||||
*/
|
|
||||||
const QuoteStrikeThrough = {
|
const QuoteStrikeThrough = {
|
||||||
init() {
|
init(): void {
|
||||||
if (
|
if (
|
||||||
!['index', 'thread'].includes(g.VIEW) ||
|
!['index', 'thread'].includes(g.VIEW) ||
|
||||||
(!Conf['Reply Hiding Buttons'] &&
|
(!Conf['Reply Hiding Buttons'] &&
|
||||||
@ -25,7 +20,7 @@ const QuoteStrikeThrough = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
node() {
|
node(): void {
|
||||||
if (this.isClone) {
|
if (this.isClone) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2,11 +2,6 @@ import BoardConfig from '../General/BoardConfig'
|
|||||||
import { d, g } from '../globals/globals'
|
import { d, g } from '../globals/globals'
|
||||||
import SimpleDict from './SimpleDict'
|
import SimpleDict from './SimpleDict'
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
export default class Board {
|
export default class Board {
|
||||||
toString() {
|
toString() {
|
||||||
return this.ID
|
return this.ID
|
||||||
@ -20,7 +15,7 @@ export default class Board {
|
|||||||
this.posts = new SimpleDict()
|
this.posts = new SimpleDict()
|
||||||
this.config = BoardConfig.boards?.[this.ID] || {}
|
this.config = BoardConfig.boards?.[this.ID] || {}
|
||||||
|
|
||||||
g.boards[this] = this
|
g.boards[this.ID] = this
|
||||||
}
|
}
|
||||||
|
|
||||||
cooldowns() {
|
cooldowns() {
|
||||||
|
|||||||
@ -1,11 +1,5 @@
|
|||||||
import Main from '../main/Main'
|
import Main from '../main/Main'
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* DS206: Consider reworking classes to avoid initClass
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
export default class Callbacks {
|
export default class Callbacks {
|
||||||
static initClass() {
|
static initClass() {
|
||||||
this.Post = new Callbacks('Post')
|
this.Post = new Callbacks('Post')
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
import $ from '../platform/$'
|
|
||||||
|
|
||||||
export default class CatalogThread {
|
|
||||||
toString() {
|
|
||||||
return this.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(root, thread) {
|
|
||||||
this.thread = thread
|
|
||||||
this.ID = this.thread.ID
|
|
||||||
this.board = this.thread.board
|
|
||||||
const { post } = this.thread.OP.nodes
|
|
||||||
this.nodes = {
|
|
||||||
root,
|
|
||||||
thumb: $('.catalog-thumb', post),
|
|
||||||
icons: $('.catalog-icons', post),
|
|
||||||
postCount: $('.post-count', post),
|
|
||||||
fileCount: $('.file-count', post),
|
|
||||||
pageCount: $('.page-count', post),
|
|
||||||
replies: null,
|
|
||||||
}
|
|
||||||
this.thread.catalogView = this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
37
src/classes/CatalogThread.ts
Normal file
37
src/classes/CatalogThread.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import $ from '../platform/$';
|
||||||
|
|
||||||
|
export default class CatalogThread {
|
||||||
|
private thread: any;
|
||||||
|
private ID: number;
|
||||||
|
private board: string;
|
||||||
|
private nodes: {
|
||||||
|
root: any,
|
||||||
|
thumb: HTMLElement,
|
||||||
|
icons: HTMLElement,
|
||||||
|
postCount: HTMLElement,
|
||||||
|
fileCount: HTMLElement,
|
||||||
|
pageCount: HTMLElement,
|
||||||
|
replies: null | any,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(root: any, thread: any) {
|
||||||
|
this.thread = thread;
|
||||||
|
this.ID = this.thread.ID;
|
||||||
|
this.board = this.thread.board;
|
||||||
|
const { post } = this.thread.OP.nodes;
|
||||||
|
this.nodes = {
|
||||||
|
root,
|
||||||
|
thumb: $('.catalog-thumb', post),
|
||||||
|
icons: $('.catalog-icons', post),
|
||||||
|
postCount: $('.post-count', post),
|
||||||
|
fileCount: $('.file-count', post),
|
||||||
|
pageCount: $('.page-count', post),
|
||||||
|
replies: null,
|
||||||
|
};
|
||||||
|
this.thread.catalogView = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toString(): string {
|
||||||
|
return this.ID.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import { g } from '../globals/globals'
|
|
||||||
import $ from '../platform/$'
|
|
||||||
import Board from './Board'
|
|
||||||
import Thread from './Thread'
|
|
||||||
|
|
||||||
export default class CatalogThreadNative {
|
|
||||||
toString() {
|
|
||||||
return this.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(root) {
|
|
||||||
this.nodes = {
|
|
||||||
root,
|
|
||||||
thumb: $(g.SITE.selectors.catalog.thumb, root),
|
|
||||||
}
|
|
||||||
this.siteID = g.SITE.ID
|
|
||||||
this.boardID = this.nodes.thumb.parentNode.pathname.split(/\/+/)[1]
|
|
||||||
this.board = g.boards[this.boardID] || new Board(this.boardID)
|
|
||||||
this.ID = this.threadID = +(root.dataset.id || root.id).match(/\d*$/)[0]
|
|
||||||
this.thread =
|
|
||||||
this.board.threads.get(this.ID) || new Thread(this.ID, this.board)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
34
src/classes/CatalogThreadNative.ts
Normal file
34
src/classes/CatalogThreadNative.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { g } from '../globals/globals';
|
||||||
|
import $ from '../platform/$';
|
||||||
|
import Board from './Board';
|
||||||
|
import Thread from './Thread';
|
||||||
|
|
||||||
|
export default class CatalogThreadNative {
|
||||||
|
nodes: {
|
||||||
|
root: HTMLElement;
|
||||||
|
thumb: any;
|
||||||
|
};
|
||||||
|
siteID: string;
|
||||||
|
boardID: string;
|
||||||
|
board: Board;
|
||||||
|
ID: number;
|
||||||
|
threadID: number;
|
||||||
|
thread: Thread;
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return this.ID.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(root: HTMLElement) {
|
||||||
|
this.nodes = {
|
||||||
|
root,
|
||||||
|
thumb: $(g.SITE.selectors.catalog.thumb, root),
|
||||||
|
};
|
||||||
|
this.siteID = g.SITE.ID;
|
||||||
|
this.boardID = this.nodes.thumb[0].parentNode.pathname.split(/\/+/)[1];
|
||||||
|
this.board = g.boards[this.boardID] || new Board(this.boardID);
|
||||||
|
this.ID = this.threadID = +(root.dataset.id || root.id).match(/\d*$/)[0];
|
||||||
|
this.thread =
|
||||||
|
this.board.threads.get(this.ID) || new Thread(this.ID, this.board);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,51 +0,0 @@
|
|||||||
import $ from '../platform/$'
|
|
||||||
import { g } 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
|
|
||||||
*/
|
|
||||||
export default class Connection {
|
|
||||||
constructor(target, origin, cb = {}) {
|
|
||||||
this.send = this.send.bind(this)
|
|
||||||
this.onMessage = this.onMessage.bind(this)
|
|
||||||
this.target = target
|
|
||||||
this.origin = origin
|
|
||||||
this.cb = cb
|
|
||||||
$.on(window, 'message', this.onMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
targetWindow() {
|
|
||||||
if (this.target instanceof window.HTMLIFrameElement) {
|
|
||||||
return this.target.contentWindow
|
|
||||||
} else {
|
|
||||||
return this.target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
send(data) {
|
|
||||||
return this.targetWindow().postMessage(
|
|
||||||
`${g.NAMESPACE}${JSON.stringify(data)}`,
|
|
||||||
this.origin,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
onMessage(e) {
|
|
||||||
if (
|
|
||||||
e.source !== this.targetWindow() ||
|
|
||||||
e.origin !== this.origin ||
|
|
||||||
typeof e.data !== 'string' ||
|
|
||||||
e.data.slice(0, g.NAMESPACE.length) !== g.NAMESPACE
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const data = JSON.parse(e.data.slice(g.NAMESPACE.length))
|
|
||||||
for (var type in data) {
|
|
||||||
var value = data[type]
|
|
||||||
if ($.hasOwn(this.cb, type)) {
|
|
||||||
this.cb[type](value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
54
src/classes/Connection.ts
Normal file
54
src/classes/Connection.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import $ from '../platform/$';
|
||||||
|
import { g } from '../globals/globals';
|
||||||
|
|
||||||
|
interface Callbacks {
|
||||||
|
[key: string]: (value: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Connection {
|
||||||
|
private target: Window | HTMLIFrameElement;
|
||||||
|
private origin: string;
|
||||||
|
private cb: Callbacks;
|
||||||
|
|
||||||
|
constructor(target: Window | HTMLIFrameElement, origin: string, cb: Callbacks = {}) {
|
||||||
|
this.send = this.send.bind(this);
|
||||||
|
this.onMessage = this.onMessage.bind(this);
|
||||||
|
this.target = target;
|
||||||
|
this.origin = origin;
|
||||||
|
this.cb = cb;
|
||||||
|
$.on(window, 'message', this.onMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private targetWindow(): Window {
|
||||||
|
if (this.target instanceof window.HTMLIFrameElement) {
|
||||||
|
return this.target.contentWindow;
|
||||||
|
} else {
|
||||||
|
return this.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public send(data: any): void {
|
||||||
|
return this.targetWindow().postMessage(
|
||||||
|
`${g.NAMESPACE}${JSON.stringify(data)}`,
|
||||||
|
this.origin,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private onMessage(e: MessageEvent): void {
|
||||||
|
if (
|
||||||
|
e.source !== this.targetWindow() ||
|
||||||
|
e.origin !== this.origin ||
|
||||||
|
typeof e.data !== 'string' ||
|
||||||
|
e.data.slice(0, g.NAMESPACE.length) !== g.NAMESPACE
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = JSON.parse(e.data.slice(g.NAMESPACE.length));
|
||||||
|
for (const type in data) {
|
||||||
|
const value = data[type];
|
||||||
|
if ($.hasOwn(this.cb, type)) {
|
||||||
|
this.cb[type](value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,7 +11,6 @@ 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'
|
||||||
|
|
||||||
|
|
||||||
export default class Fetcher {
|
export default class Fetcher {
|
||||||
static initClass() {
|
static initClass() {
|
||||||
this.prototype.archiveTags = {
|
this.prototype.archiveTags = {
|
||||||
@ -80,53 +79,20 @@ export default class Fetcher {
|
|||||||
this.root.textContent = `Loading post No.${this.postID}...`
|
this.root.textContent = `Loading post No.${this.postID}...`
|
||||||
if (this.threadID) {
|
if (this.threadID) {
|
||||||
const that = this
|
const that = this
|
||||||
Fetcher.fetchThread(
|
$.cache(
|
||||||
this.boardID,
|
g.SITE.urls.threadJSON({
|
||||||
this.threadID,
|
boardID: this.boardID,
|
||||||
function (req, isCached) {
|
threadID: this.threadID,
|
||||||
that.fetchedThread(req, isCached)
|
}),
|
||||||
|
function ({ isCached }) {
|
||||||
|
return that.fetchedPost(this, isCached)
|
||||||
},
|
},
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
const that = this
|
this.archivedPost()
|
||||||
Fetcher.fetchPost(
|
|
||||||
this.boardID,
|
|
||||||
this.postID,
|
|
||||||
function (req, isCached) {
|
|
||||||
that.fetchedPost(req, isCached)
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchedThread(req) {
|
|
||||||
const { status, response } = req
|
|
||||||
const { boardID, threadID } = this
|
|
||||||
const board = g.boards[boardID]
|
|
||||||
if (status === 404) {
|
|
||||||
this.root.textContent = `Thread No.${threadID} not found.`
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (status !== 200) {
|
|
||||||
this.root.textContent = `Error loading thread No.${threadID}.`
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (response === '') {
|
|
||||||
this.root.textContent = `Thread No.${threadID} is empty.`
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const thread = new Thread(
|
|
||||||
g.SITE.Build.threadFromObject(response, boardID),board)
|
|
||||||
Main.callbackNodes('Thread', [thread])
|
|
||||||
const post = thread.posts.get(this.postID)
|
|
||||||
if (post) {
|
|
||||||
this.insert(post)
|
|
||||||
} else {
|
|
||||||
this.root.textContent = `Post No.${this.postID} not found.`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insert(post) {
|
insert(post) {
|
||||||
// Stop here if the container has been removed while loading.
|
// Stop here if the container has been removed while loading.
|
||||||
if (!this.root.parentNode) {
|
if (!this.root.parentNode) {
|
||||||
@ -180,75 +146,76 @@ export default class Fetcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchedPost(req, isCached) {
|
fetchedPost(req, isCached) {
|
||||||
const { status, response } = req;
|
// In case of multiple callbacks for the same request,
|
||||||
const { boardID, postID, threadID } = this;
|
// don't parse the same original post more than once.
|
||||||
const postKey = `${boardID}.${postID}`;
|
let post
|
||||||
|
if ((post = g.posts.get(`${this.boardID}.${this.postID}`))) {
|
||||||
const post = g.posts.get(postKey);
|
this.insert(post)
|
||||||
if (post) {
|
return
|
||||||
this.insert(post);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { status } = req
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
this.handleNon200Status(status);
|
// The thread can die by the time we check a quote.
|
||||||
return;
|
if (status && this.archivedPost()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$.addClass(this.root, 'warning')
|
||||||
|
this.root.textContent =
|
||||||
|
status === 404
|
||||||
|
? `Thread No.${this.threadID} 404'd.`
|
||||||
|
: !status
|
||||||
|
? 'Connection Error'
|
||||||
|
: `Error ${req.statusText} (${req.status}).`
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { posts } = response;
|
const { posts } = req.response
|
||||||
g.SITE.Build.spoilerRange[boardID] = posts[0].custom_spoiler;
|
g.SITE.Build.spoilerRange[this.boardID] = posts[0].custom_spoiler
|
||||||
|
for (post of posts) {
|
||||||
|
if (post.no === this.postID) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} // we found it!
|
||||||
|
|
||||||
const foundPost = posts.find((p) => p.no === postID);
|
if (post.no !== this.postID) {
|
||||||
|
// Cached requests can be stale and must be rechecked.
|
||||||
|
if (isCached) {
|
||||||
|
const api = g.SITE.urls.threadJSON({
|
||||||
|
boardID: this.boardID,
|
||||||
|
threadID: this.threadID,
|
||||||
|
})
|
||||||
|
$.cleanCache((url) => url === api)
|
||||||
|
const that = this
|
||||||
|
$.cache(api, function () {
|
||||||
|
return that.fetchedPost(this, false)
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (!foundPost) {
|
// The post can be deleted by the time we check a quote.
|
||||||
this.handlePostNotFound(isCached);
|
if (this.archivedPost()) {
|
||||||
return;
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$.addClass(this.root, 'warning')
|
||||||
|
this.root.textContent = `Post No.${this.postID} was not found.`
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const board = g.boards[boardID] || new Board(boardID);
|
const board = g.boards[this.boardID] || new Board(this.boardID)
|
||||||
const threadKey = `${boardID}.${threadID}`;
|
const thread =
|
||||||
const thread = g.threads.get(threadKey) || new Thread(threadID, board);
|
g.threads.get(`${this.boardID}.${this.threadID}`) ||
|
||||||
const newPost = new Post(
|
new Thread(this.threadID, board)
|
||||||
g.SITE.Build.postFromObject(foundPost, boardID),
|
post = new Post(
|
||||||
|
g.SITE.Build.postFromObject(post, this.boardID),
|
||||||
thread,
|
thread,
|
||||||
board,
|
board,
|
||||||
{ isFetchedQuote: true },
|
{ isFetchedQuote: true },
|
||||||
);
|
)
|
||||||
Main.callbackNodes("Post", [newPost]);
|
Main.callbackNodes('Post', [post])
|
||||||
return this.insert(newPost);
|
return this.insert(post)
|
||||||
}
|
|
||||||
|
|
||||||
handleNon200Status(status, req) {
|
|
||||||
$.addClass(this.root, "warning");
|
|
||||||
this.root.textContent =
|
|
||||||
status === 404
|
|
||||||
? `Thread No.${this.threadID} 404'd.`
|
|
||||||
: !status
|
|
||||||
? "Connection Error"
|
|
||||||
: `Error ${req.statusText} (${req.status}).`;
|
|
||||||
|
|
||||||
if (status && this.archivedPost()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePostNotFound(isCached) {
|
|
||||||
if (isCached) {
|
|
||||||
const api = g.SITE.urls.threadJSON({
|
|
||||||
boardID: this.boardID,
|
|
||||||
threadID: this.threadID,
|
|
||||||
});
|
|
||||||
$.cleanCache((url) => url === api);
|
|
||||||
$.cache(api, () => this.fetchedPost(this, false));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.archivedPost()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.addClass(this.root, "warning");
|
|
||||||
this.root.textContent = `Post No.${this.postID} was not found.`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
archivedPost() {
|
archivedPost() {
|
||||||
|
|||||||
@ -1,25 +1,22 @@
|
|||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
class ShimSet {
|
class ShimSet {
|
||||||
|
elements: { [key: string]: boolean }
|
||||||
|
size: number
|
||||||
constructor() {
|
constructor() {
|
||||||
this.elements = $.dict()
|
this.elements = $.dict()
|
||||||
this.size = 0
|
this.size = 0
|
||||||
}
|
}
|
||||||
has(value) {
|
has(value: string) {
|
||||||
return value in this.elements
|
return value in this.elements
|
||||||
}
|
}
|
||||||
add(value) {
|
add(value: string) {
|
||||||
if (this.elements[value]) {
|
if (this.elements[value]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.elements[value] = true
|
this.elements[value] = true
|
||||||
return this.size++
|
return this.size++
|
||||||
}
|
}
|
||||||
delete(value) {
|
delete(value: string) {
|
||||||
if (!this.elements[value]) {
|
if (!this.elements[value]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -29,5 +26,6 @@ class ShimSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!('Set' in window)) {
|
if (!('Set' in window)) {
|
||||||
|
// @ts-ignore
|
||||||
window.Set = ShimSet
|
window.Set = ShimSet
|
||||||
}
|
}
|
||||||
@ -86,7 +86,6 @@ import Header from '../General/Header'
|
|||||||
import { c, Conf, d, doc, docSet, E, g } from '../globals/globals'
|
import { c, Conf, d, doc, docSet, E, g } from '../globals/globals'
|
||||||
import Menu from '../Menu/Menu'
|
import Menu from '../Menu/Menu'
|
||||||
import BoardConfig from '../General/BoardConfig'
|
import BoardConfig from '../General/BoardConfig'
|
||||||
import CaptchaReplace from '../Posting/Captcha.replace'
|
|
||||||
import Get from '../General/Get'
|
import Get from '../General/Get'
|
||||||
import { dict, platform } from '../platform/helpers'
|
import { dict, platform } from '../platform/helpers'
|
||||||
import Polyfill from '../General/Polyfill'
|
import Polyfill from '../General/Polyfill'
|
||||||
@ -1075,7 +1074,6 @@ User agent: ${navigator.userAgent}\
|
|||||||
['Board Configuration', BoardConfig],
|
['Board Configuration', BoardConfig],
|
||||||
['Normalize URL', NormalizeURL],
|
['Normalize URL', NormalizeURL],
|
||||||
['Delay Redirect on Post', PostRedirect],
|
['Delay Redirect on Post', PostRedirect],
|
||||||
['Captcha Configuration', CaptchaReplace],
|
|
||||||
['Image Host Rewriting', ImageHost],
|
['Image Host Rewriting', ImageHost],
|
||||||
['Redirect', Redirect],
|
['Redirect', Redirect],
|
||||||
['Header', Header],
|
['Header', Header],
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import { d } from '../globals/globals'
|
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS101: Remove unnecessary use of Array.from
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const $$ = (selector, root = d.body) => [
|
|
||||||
...Array.from(root.querySelectorAll(selector)),
|
|
||||||
]
|
|
||||||
export default $$
|
|
||||||
4
src/platform/$$.ts
Normal file
4
src/platform/$$.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
const $$ = (selector: string, root: HTMLElement | null = document.body): Element[] =>
|
||||||
|
Array.from(root?.querySelectorAll(selector) ?? []) as Element[];
|
||||||
|
|
||||||
|
export default $$;
|
||||||
@ -54,6 +54,20 @@ $.ajaxPage = function (url, options) {
|
|||||||
r.send(form)
|
r.send(form)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
$.cache = function (key, value, time) {
|
||||||
|
if (value == null) {
|
||||||
|
value = null
|
||||||
|
}
|
||||||
|
if (time == null) {
|
||||||
|
time = MINUTE
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
return $.set(key, value, time)
|
||||||
|
} else {
|
||||||
|
return $.get(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$.ready = function (fc) {
|
$.ready = function (fc) {
|
||||||
if (d.readyState !== 'loading') {
|
if (d.readyState !== 'loading') {
|
||||||
$.queueTask(fc)
|
$.queueTask(fc)
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export const debounce = (wait: number, fn: Function) => {
|
|||||||
|
|
||||||
export const dict = () => Object.create(null)
|
export const dict = () => Object.create(null)
|
||||||
|
|
||||||
dict.clone = function (obj) {
|
dict.clone = function (obj: object) {
|
||||||
if (typeof obj !== 'object' || obj === null) {
|
if (typeof obj !== 'object' || obj === null) {
|
||||||
return obj
|
return obj
|
||||||
} else if (obj instanceof Array) {
|
} else if (obj instanceof Array) {
|
||||||
|
|||||||
@ -2,14 +2,14 @@ import h, { hFragment, EscapedHtml } from '../../globals/jsx'
|
|||||||
|
|
||||||
export default function generateCatalogThreadHtml(
|
export default function generateCatalogThreadHtml(
|
||||||
thread,
|
thread,
|
||||||
src,
|
src: string,
|
||||||
imgClass,
|
imgClass: string,
|
||||||
data,
|
data: any,
|
||||||
postCount,
|
postCount: number,
|
||||||
fileCount,
|
fileCount: number,
|
||||||
pageCount,
|
pageCount: number,
|
||||||
staticPath,
|
staticPath: string,
|
||||||
gifIcon,
|
gifIcon: string,
|
||||||
): EscapedHtml {
|
): EscapedHtml {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -1,15 +1,29 @@
|
|||||||
import h, { EscapedHtml, isEscaped } from '../../globals/jsx'
|
import h, { EscapedHtml, isEscaped } from '../../globals/jsx'
|
||||||
|
|
||||||
|
type File = {
|
||||||
|
MD5: string
|
||||||
|
name: string
|
||||||
|
size: string
|
||||||
|
dimensions: string
|
||||||
|
tag: string
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
twidth: number
|
||||||
|
theight: number
|
||||||
|
hasDownscale: boolean
|
||||||
|
isSpoiler: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export default function generateFileHtml(
|
export default function generateFileHtml(
|
||||||
file,
|
file: File | null,
|
||||||
ID,
|
ID: number,
|
||||||
boardID,
|
boardID: string,
|
||||||
fileURL,
|
fileURL: string,
|
||||||
shortFilename,
|
shortFilename: string,
|
||||||
fileThumb,
|
fileThumb: string,
|
||||||
o,
|
o: any,
|
||||||
staticPath,
|
staticPath: string,
|
||||||
gifIcon,
|
gifIcon: string,
|
||||||
): EscapedHtml {
|
): EscapedHtml {
|
||||||
if (file) {
|
if (file) {
|
||||||
const fileContent: (EscapedHtml | string)[] = []
|
const fileContent: (EscapedHtml | string)[] = []
|
||||||
|
|||||||
@ -2,29 +2,29 @@ import { g } from '../../globals/globals'
|
|||||||
import h, { EscapedHtml } from '../../globals/jsx'
|
import h, { EscapedHtml } from '../../globals/jsx'
|
||||||
|
|
||||||
export default function generatePostInfoHtml(
|
export default function generatePostInfoHtml(
|
||||||
ID,
|
ID: number,
|
||||||
o,
|
o: any,
|
||||||
subject,
|
subject: string,
|
||||||
capcode,
|
capcode: string,
|
||||||
email,
|
email: string,
|
||||||
name,
|
name: string,
|
||||||
tripcode,
|
tripcode: string,
|
||||||
pass,
|
pass: string,
|
||||||
capcodeLC,
|
capcodeLC: string,
|
||||||
capcodePlural,
|
capcodePlural: string,
|
||||||
staticPath,
|
staticPath: string,
|
||||||
gifIcon,
|
gifIcon: string,
|
||||||
capcodeDescription,
|
capcodeDescription: string,
|
||||||
uniqueID,
|
uniqueID: string,
|
||||||
flag,
|
flag: string,
|
||||||
flagCode,
|
flagCode: string,
|
||||||
flagCodeTroll,
|
flagCodeTroll: string,
|
||||||
dateUTC,
|
dateUTC: string,
|
||||||
dateText,
|
dateText: string,
|
||||||
postLink,
|
postLink: string,
|
||||||
quoteLink,
|
quoteLink: string,
|
||||||
boardID,
|
boardID: string,
|
||||||
threadID,
|
threadID: number,
|
||||||
): EscapedHtml {
|
): EscapedHtml {
|
||||||
const nameHtml: (EscapedHtml | string)[] = [
|
const nameHtml: (EscapedHtml | string)[] = [
|
||||||
<span class={`name${capcode ? ' ' + capcode : ''}`}>{name}</span>,
|
<span class={`name${capcode ? ' ' + capcode : ''}`}>{name}</span>,
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import Redirect from "../Archive/Redirect";
|
import Redirect from "../Archive/Redirect";
|
||||||
import PassMessage from "../Miscellaneous/PassMessage";
|
import PassMessage from "../Miscellaneous/PassMessage";
|
||||||
import Report from "../Miscellaneous/Report";
|
|
||||||
import $ from "../platform/$";
|
import $ from "../platform/$";
|
||||||
import $$ from "../platform/$$";
|
import $$ from "../platform/$$";
|
||||||
import Captcha from "../Posting/Captcha";
|
import Captcha from "../Posting/Captcha";
|
||||||
@ -9,20 +8,12 @@ import ImageHost from "../Images/ImageHost";
|
|||||||
import { g, Conf, E, d, doc } from "../globals/globals";
|
import { g, Conf, E, d, doc } from "../globals/globals";
|
||||||
import BoardConfig from "../General/BoardConfig";
|
import BoardConfig from "../General/BoardConfig";
|
||||||
import CSS from "../css/CSS";
|
import CSS from "../css/CSS";
|
||||||
|
|
||||||
import generatePostInfoHtml from './SW.yotsuba.Build/PostInfoHtml';
|
import generatePostInfoHtml from './SW.yotsuba.Build/PostInfoHtml';
|
||||||
import generateFileHtml from "./SW.yotsuba.Build/FileHtml";
|
import generateFileHtml from "./SW.yotsuba.Build/FileHtml";
|
||||||
import generateCatalogThreadHtml from "./SW.yotsuba.Build/CatalogThreadHtml";
|
import generateCatalogThreadHtml from "./SW.yotsuba.Build/CatalogThreadHtml";
|
||||||
import h, { hFragment, isEscaped } from "../globals/jsx";
|
import h, { hFragment, isEscaped } from "../globals/jsx";
|
||||||
import { dict, MINUTE } from "../platform/helpers";
|
import { dict, MINUTE } from "../platform/helpers";
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS101: Remove unnecessary use of Array.from
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* DS205: Consider reworking code to avoid use of IIFEs
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const SWYotsuba = {
|
const SWYotsuba = {
|
||||||
isOPContainerThread: false,
|
isOPContainerThread: false,
|
||||||
hasIPCount: true,
|
hasIPCount: true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user