Added types and bug fixes

This commit is contained in:
Lalle 2023-04-19 03:33:50 +02:00
parent f65fbc4fed
commit 241ff1eb7a
No known key found for this signature in database
GPG Key ID: A6583D207A8F6B0D
14 changed files with 227 additions and 317 deletions

View File

@ -874,8 +874,9 @@ var Embedding = {
{
key: 'YouTube',
regExp:
/^\w+:\/\/(?:youtu.be\/|[\w.]*youtube[\w.]*\/.*(?:v=|\bembed\/|\bv\/))([\w\-]{11})(.*)/,
/^\w+:\/\/(?:www\.)?youtube\.com\/(?:watch\?v=|embed\/|v\/)?(\w+)/,
el(a) {
const isShort = a.href.includes('youtube.com/shorts/')
let start = a.dataset.options.match(/\b(?:star)?t\=(\w+)/)
if (start) {
start = start[1]
@ -888,11 +889,15 @@ var Embedding = {
1 * start.match(/(\d+)s/)[1]
}
const el = $.el('iframe', {
src: `//www.youtube.com/embed/${a.dataset.uid}?rel=0&wmode=opaque${
start ? '&start=' + start : ''
}`,
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 : ''}`}`,
})
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
},
title: {
@ -907,17 +912,18 @@ var Embedding = {
const m = _.error.match(/^(\d*)\s*(.*)/)
return [+m[1], m[2]]
} else {
return [200, 'OK']
return [200, null]
}
},
},
preview: {
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,
},
},
},
],
}
export default Embedding

View File

@ -4,11 +4,6 @@ import Filter from '../Filtering/Filter'
import { g, Conf } from '../globals/globals'
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 = {
init() {
if (

View File

@ -2,12 +2,14 @@ import { g, Conf, d } from '../globals/globals'
import $ from '../platform/$'
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
*/
var CopyTextLink = {
interface CopyTextLink {
text: string
init(): VoidFunction
copy(): VoidFunction
}
const CopyTextLink: CopyTextLink = {
text: '',
init() {
if (
!['index', 'thread'].includes(g.VIEW) ||

View File

@ -3,13 +3,9 @@ import ImageCommon from '../Images/ImageCommon'
import $ from '../platform/$'
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 = {
init() {
init(): VoidFunction {
if (
!['index', 'thread'].includes(g.VIEW) ||
!Conf['Menu'] ||
@ -18,7 +14,7 @@ const DownloadLink = {
return
}
const a = $.el('a', {
const a: HTMLAnchorElement = $.el('a', {
className: 'download-link',
textContent: 'Download file',
})
@ -37,7 +33,7 @@ const DownloadLink = {
a.download = file.name
return true
},
})
}) as VoidFunction
},
}
export default DownloadLink

View File

@ -2,14 +2,10 @@ import Callbacks from '../classes/Callbacks'
import UI from '../General/UI'
import { g, Conf } from '../globals/globals'
import $ from '../platform/$'
import Post from '../classes/Post'
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
var Menu = {
init() {
var Menu: any = {
init(): VoidFunction {
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Menu']) {
return
}
@ -33,7 +29,7 @@ var Menu = {
})
},
node() {
node(): HTMLElement {
if (this.isClone) {
const button = $('.menu-button', this.nodes.info)
$.rmClass(button, 'active')
@ -44,15 +40,15 @@ var Menu = {
return $.add(this.nodes.info, Menu.makeButton(this))
},
catalogNode() {
catalogNode(): HTMLElement {
return $.after(this.nodes.icons, Menu.makeButton(this.thread.OP))
},
makeButton(post, button) {
makeButton(post: Post, button?: HTMLElement): HTMLElement {
if (!button) {
button = Menu.button.cloneNode(true)
}
$.on(button, 'click', function (e) {
$.on(button, 'click', (e: Event) => {
return Menu.menu.toggle(e, this, post)
})
return button

View File

@ -1,23 +1,24 @@
import { g, Conf, d } from '../globals/globals'
import $ from '../platform/$'
import Menu from './Menu'
import Post from '../classes/Post'
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
var ReportLink = {
type ReportLinkType = {
init: () => void
report: () => void
url: string
dims: string
}
const ReportLink: ReportLinkType = {
init() {
if (
!['index', 'thread'].includes(g.VIEW) ||
if (!['index', 'thread'].includes(g.VIEW) ||
!Conf['Menu'] ||
!Conf['Report Link']
) {
!Conf['Report Link']) {
return
}
const a = $.el('a', {
const a: HTMLAnchorElement = $.el('a', {
className: 'report-link',
href: 'javascript:;',
textContent: 'Report',
@ -27,10 +28,8 @@ var ReportLink = {
return Menu.menu.addEntry({
el: a,
order: 10,
open(post) {
ReportLink.url = `//sys.${location.hostname.split('.')[1]}.org/${
post.board
}/imgboard.php?mode=report&no=${post}`
open(post: Post) {
ReportLink.url = `//sys.${location.hostname.split('.')[1]}.org/${post.board}/imgboard.php?mode=report&no=${post}`
if (d.cookie.indexOf('pass_enabled=1') >= 0) {
ReportLink.dims = 'width=350,height=275'
} else {
@ -47,5 +46,7 @@ var ReportLink = {
const set = `toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1,${dims}`
return window.open(url, `report${id}`, set)
},
url: '',
dims: ''
}
export default ReportLink

View File

@ -2,20 +2,16 @@ import $ from '../platform/$'
import CSS from '../css/CSS'
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 = {
init() {
init(): void {
if (!Conf['Custom CSS']) {
return
}
return this.addStyle()
},
addStyle() {
addStyle(): HTMLStyleElement {
return (this.style = $.addStyle(
CSS.sub(Conf['usercss']),
'custom-css',
@ -23,18 +19,18 @@ const CustomCSS = {
))
},
rmStyle() {
rmStyle(): boolean {
if (this.style) {
$.rm(this.style)
return delete this.style
}
},
update() {
if (!this.style) {
return this.addStyle()
update(): void {
if (this.style) {
this.rmStyle()
this.addStyle()
}
return (this.style.textContent = CSS.sub(Conf['usercss']))
},
}
}
export default CustomCSS

View File

@ -1,10 +1,10 @@
import Callbacks from '../classes/Callbacks'
import BoardConfig from '../General/BoardConfig'
import { d, doc, g } from '../globals/globals'
import Main from '../main/Main'
import $ from '../platform/$'
import $$ from '../platform/$$'
import ExpandComment from './ExpandComment'
import Callbacks from "../classes/Callbacks";
import BoardConfig from "../General/BoardConfig";
import { d, doc, g } from "../globals/globals";
import Main from "../main/Main";
import $ from "../platform/$";
import $$ from "../platform/$$";
import ExpandComment from "./ExpandComment";
/*
* decaffeinate suggestions:
@ -13,161 +13,110 @@ import ExpandComment from './ExpandComment'
*/
var Fourchan = {
init() {
if (
g.SITE.software !== 'yotsuba' ||
!['index', 'thread', 'archive'].includes(g.VIEW)
) {
return
}
BoardConfig.ready(this.initBoard)
return Main.ready(this.initReady)
if ((g.SITE.software !== 'yotsuba') || !['index', 'thread', 'archive'].includes(g.VIEW)) { return; }
BoardConfig.ready(this.initBoard);
return Main.ready(this.initReady);
},
initBoard() {
if (g.BOARD.config.code_tags) {
$.on(window, 'prettyprint:cb', function (e) {
let post, pre
if (!(post = g.posts.get(e.detail.ID))) {
return
}
if (!(pre = $$('.prettyprint', post.nodes.comment)[+e.detail.i])) {
return
}
let post, pre;
if (!(post = g.posts.get(e.detail.ID))) { return; }
if (!(pre = $$('.prettyprint', post.nodes.comment)[+e.detail.i])) { return; }
if (!$.hasClass(pre, 'prettyprinted')) {
pre.innerHTML = e.detail.html
return $.addClass(pre, 'prettyprinted')
pre.innerHTML = e.detail.html;
return $.addClass(pre, 'prettyprinted');
}
})
$.global(() =>
window.addEventListener(
'prettyprint',
(e) =>
window.dispatchEvent(
new CustomEvent('prettyprint:cb', {
detail: {
ID: e.detail.ID,
i: e.detail.i,
html: window.prettyPrintOne(e.detail.html),
},
}),
),
false,
),
)
});
$.global(() => window.addEventListener('prettyprint', e => window.dispatchEvent(new CustomEvent('prettyprint:cb', {
detail: {
ID: e.detail.ID,
i: e.detail.i,
html: window.prettyPrintOne(e.detail.html)
}
}))
, false));
Callbacks.Post.push({
name: 'Parse [code] tags',
cb: Fourchan.code,
})
cb: Fourchan.code
});
g.posts.forEach(function (post) {
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) {
$.global(() =>
window.addEventListener(
'mathjax',
function (e) {
if (window.MathJax) {
return window.MathJax.Hub.Queue([
'Typeset',
window.MathJax.Hub,
e.target,
])
} else {
if (
!document.querySelector('script[src^="//cdn.mathjax.org/"]')
) {
// don't load MathJax if already loading
window.loadMathJax()
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,
),
)
$.global(() => window.addEventListener('mathjax', function (e) {
if (window.MathJax) {
return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]);
} else {
if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { // don't load MathJax if already loading
window.loadMathJax();
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({
name: 'Parse [math] tags',
cb: Fourchan.math,
})
cb: Fourchan.math
});
g.posts.forEach(function (post) {
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.
initReady() {
return $.global(function () {
window.clickable_ids = false
window.clickable_ids = false;
for (var node of document.querySelectorAll('.posteruid, .capcode')) {
node.removeEventListener('click', window.idClick, false)
node.removeEventListener('click', window.idClick, false);
}
})
});
},
code() {
if (this.isClone) {
return
}
if (this.isClone) { return; }
return $.ready(() => {
const iterable = $$('.prettyprint', this.nodes.comment)
const iterable = $$('.prettyprint', this.nodes.comment);
for (let i = 0; i < iterable.length; i++) {
var pre = iterable[i]
var pre = iterable[i];
if (!$.hasClass(pre, 'prettyprinted')) {
$.event(
'prettyprint',
{ ID: this.fullID, i, html: pre.innerHTML },
window,
)
$.event('prettyprint', { ID: this.fullID, i, html: pre.innerHTML }, window);
}
}
})
});
},
math() {
let wbrs
if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) {
return
}
let wbrs;
if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { return; }
// XXX <wbr> tags frequently break MathJax; remove them.
if ((wbrs = $$('wbr', this.nodes.comment)).length) {
for (var wbr of wbrs) {
$.rm(wbr)
}
this.nodes.comment.normalize()
for (var wbr of wbrs) { $.rm(wbr); }
this.nodes.comment.normalize();
}
var cb = () => {
if (!doc.contains(this.nodes.comment)) {
return
}
$.off(d, 'PostsInserted', cb)
return $.event('mathjax', null, this.nodes.comment)
}
$.on(d, 'PostsInserted', cb)
return cb()
},
}
export default Fourchan
if (!doc.contains(this.nodes.comment)) { return; }
$.off(d, 'PostsInserted', cb);
return $.event('mathjax', null, this.nodes.comment);
};
$.on(d, 'PostsInserted', cb);
return cb();
}
};
export default Fourchan;

View File

@ -1,70 +1,55 @@
import Callbacks from '../classes/Callbacks'
import { g, Conf } from '../globals/globals'
import $ from '../platform/$'
import { dict } from '../platform/helpers'
import Callbacks from "../classes/Callbacks";
import { g, Conf } from "../globals/globals";
import $ from "../platform/$";
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 = {
init() {
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Color User IDs']) {
return
}
this.ids = dict()
this.ids['Heaven'] = [0, 0, 0, '#fff']
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Color User IDs']) { return; }
this.ids = dict();
this.ids['Heaven'] = [0, 0, 0, '#fff'];
return Callbacks.Post.push({
name: 'Color User IDs',
cb: this.node,
})
cb: this.node
});
},
node() {
let span, uid
if (
this.isClone ||
!((uid = this.info.uniqueID) && (span = this.nodes.uniqueID))
) {
return
}
let span, uid;
if (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.
const { style } = span
style.color = rgb[3]
style.backgroundColor = `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`
return $.addClass(span, 'painted')
const { style } = span;
style.color = rgb[3];
style.backgroundColor = `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`;
return $.addClass(span, 'painted');
},
compute(uid) {
// Convert chars to integers, bitshift and math to create a larger integer
// Create a nice string of binary
let hash;
if (typeof g !== 'undefined' && g.SITE && g.SITE.uidColor) {
hash = g.SITE.uidColor(uid);
} else {
hash = parseInt(uid, 16);
}
const hash = g.SITE.uidColor ? g.SITE.uidColor(uid) : parseInt(uid, 16);
// Convert binary string to numerical values with bitshift and '&' truncation.
const rgb = [(hash >> 16) & 0xff, (hash >> 8) & 0xff, hash & 0xff];
// Weight color luminance values, assign a font color that should be readable.
const fontColor = $.luma ? ($.luma(rgb) > 125 ? '#000' : '#fff') : '#000';
// Cache color and font color.
const colorCode = `rgb(${rgb.join(',')})`;
this.ids[uid] = {
color: colorCode,
fontColor: fontColor
};
// Return only the color.
return colorCode;
},
}
export default IDColor
const rgb = [
(hash >> 16) & 0xFF,
(hash >> 8) & 0xFF,
hash & 0xFF
];
// Weight color luminance values, assign a font color that should be readable.
rgb.push($.luma(rgb) > 125 ?
'#000'
:
'#fff'
);
// Cache.
return this.ids[uid] = rgb;
}
};
export default IDColor;

View File

@ -1,50 +1,37 @@
import Callbacks from '../classes/Callbacks'
import { g } from '../globals/globals'
import $ from '../platform/$'
import Callbacks from "../classes/Callbacks";
import { g } from "../globals/globals";
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 = {
init() {
if (!['index', 'thread'].includes(g.VIEW)) {
return
}
if (!['index', 'thread'].includes(g.VIEW)) { return; }
return Callbacks.Post.push({
name: 'Highlight by User ID',
cb: this.node,
})
cb: this.node
});
},
uniqueID: null,
node() {
if (this.nodes.uniqueIDRoot) {
$.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.uniqueIDRoot) { $.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); }
},
set(post) {
const match =
(post.info.uniqueID || post.info.capcode) === IDHighlight.uniqueID
return $[match ? 'addClass' : 'rmClass'](post.nodes.post, 'highlight')
const match = (post.info.uniqueID || post.info.capcode) === IDHighlight.uniqueID;
return $[match ? 'addClass' : 'rmClass'](post.nodes.post, 'highlight');
},
click(post) {
return function () {
const uniqueID = post.info.uniqueID || post.info.capcode
IDHighlight.uniqueID = IDHighlight.uniqueID === uniqueID ? null : uniqueID
return g.posts.forEach(IDHighlight.set)
}
},
}
export default IDHighlight
const uniqueID = post.info.uniqueID || post.info.capcode;
IDHighlight.uniqueID = IDHighlight.uniqueID === uniqueID ? null : uniqueID;
return g.posts.forEach(IDHighlight.set);
};
}
};
export default IDHighlight;

View File

@ -4,15 +4,15 @@ import Main from '../main/Main'
import $ from '../platform/$'
const PSA = {
init() {
let el
init(): void {
let el: HTMLElement
if (g.SITE.software === 'yotsuba' && g.BOARD.ID === 'qa') {
const announcement = {
innerHTML:
'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)
$.onExists(doc, '.boardBanner', (banner) => $.after(banner, el))
el = $.el('span', announcement) as HTMLElement
$.onExists(doc, '.boardBanner', (banner: HTMLElement) => $.after(banner, el))
}
if (
'samachan.org' in Conf['siteProperties'] &&

View File

@ -8,7 +8,7 @@ import { g, Conf } from '../globals/globals'
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
var Time = {
init() {
init(): VoidFunction {
if (
!['index', 'thread', 'archive'].includes(g.VIEW) ||
!Conf['Time Formatting']
@ -22,18 +22,15 @@ var Time = {
})
},
node() {
if (!this.info.date || this.isClone) {
return
node(): any {
if (!this.info.date || this.isClone) {
return;
}
const { textContent } = this.nodes.date
return (this.nodes.date.textContent =
textContent.match(/^\s*/)[0] +
Time.format(Conf['time'], this.info.date) +
textContent.match(/\s*$/)[0])
const { textContent } = this.nodes.date;
return this.nodes.date.textContent = 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) {
if ($.hasOwn(Time.formatters, c)) {
return Time.formatters[c].call(date)
@ -68,16 +65,16 @@ var Time = {
'December',
],
localeFormat(date, options, defaultValue) {
localeFormat(date: Date, options: any, defaultValue: string): string {
if (Conf['timeLocale']) {
try {
return Intl.DateTimeFormat(Conf['timeLocale'], options).format(date)
} catch (error) {}
} catch (error) { }
}
return defaultValue
},
localeFormatPart(date, options, part, defaultValue) {
localeFormatPart(date: Date, options: any, part: string, defaultValue: string): string {
if (Conf['timeLocale']) {
try {
const parts = Intl.DateTimeFormat(
@ -93,12 +90,12 @@ var Time = {
}
})
.join('')
} catch (error) {}
} catch (error) { }
}
return defaultValue
},
zeroPad(n) {
zeroPad(n: number): number | string {
if (n < 10) {
return `0${n}`
} else {
@ -107,59 +104,59 @@ var Time = {
},
formatters: {
a() {
a(): string {
return Time.localeFormat(
this,
{ weekday: 'short' },
Time.day[this.getDay()].slice(0, 3),
)
},
A() {
A(): string {
return Time.localeFormat(
this,
{ weekday: 'long' },
Time.day[this.getDay()],
)
},
b() {
b(): string {
return Time.localeFormat(
this,
{ month: 'short' },
Time.month[this.getMonth()].slice(0, 3),
)
},
B() {
B(): string {
return Time.localeFormat(
this,
{ month: 'long' },
Time.month[this.getMonth()],
)
},
d() {
d(): string | number {
return Time.zeroPad(this.getDate())
},
e() {
e(): number {
return this.getDate()
},
H() {
H(): string | number {
return Time.zeroPad(this.getHours())
},
I() {
I(): string | number {
return Time.zeroPad(this.getHours() % 12 || 12)
},
k() {
k(): number {
return this.getHours()
},
l() {
l(): number {
return this.getHours() % 12 || 12
},
m() {
m(): string | number {
return Time.zeroPad(this.getMonth() + 1)
},
M() {
M(): string | number {
return Time.zeroPad(this.getMinutes())
},
p() {
p(): string {
return Time.localeFormatPart(
this,
{ hour: 'numeric', hour12: true },
@ -167,19 +164,19 @@ var Time = {
this.getHours() < 12 ? 'AM' : 'PM',
)
},
P() {
P(): string {
return Time.formatters.p.call(this).toLowerCase()
},
S() {
S(): string | number {
return Time.zeroPad(this.getSeconds())
},
y() {
y(): string {
return this.getFullYear().toString().slice(2)
},
Y() {
Y(): number {
return this.getFullYear()
},
'%'() {
'%'(): string {
return '%'
},
},

View File

@ -1,5 +1,5 @@
import SWTinyboard from './SW.tinyboard'
import SWYotsuba from './SW.yotsuba'
const SW = { tinyboard: SWTinyboard, yotsuba: SWYotsuba }
const SW = { tinyboard: SWTinyboard, yotsuba: SWYotsuba } as const
export default SW

View File

@ -19,7 +19,7 @@ var Site = {
'smug.nepu.moe': { canonical: 'smuglo.li' },
},
init(cb) {
init(cb: () => void): void {
$.extend(Conf['siteProperties'], Site.defaultProperties)
let hostname = Site.resolve()
if (hostname && $.hasOwn(SW, Conf['siteProperties'][hostname].software)) {
@ -28,7 +28,7 @@ var Site = {
}
return $.onExists(doc, 'body', () => {
for (var software in SW) {
var changes
var changes: { [key: string]: string }
if ((changes = SW[software].detect?.())) {
changes.software = software
hostname = location.hostname.replace(/^www\./, '')
@ -55,7 +55,7 @@ var Site = {
})
},
resolve(url = location) {
resolve(url = location): string {
let { hostname } = url
while (hostname && !$.hasOwn(Conf['siteProperties'], hostname)) {
hostname = hostname.replace(/^[^.]*\.?/, '')
@ -69,14 +69,14 @@ var Site = {
return hostname
},
parseURL(url) {
const siteID = Site.resolve(url)
return Main.parseURL(g.sites[siteID], url)
parseURL(url: Location): ReturnType<typeof Main.parseURL> {
var siteID = Site.resolve(url)
return siteID ? g.sites[siteID].parseURL(url) : null
},
set(hostname) {
set(hostname: string): typeof g.SITE {
for (var ID in Conf['siteProperties']) {
var site
var site: typeof g.SITE
var properties = Conf['siteProperties'][ID]
if (properties.canonical) {
continue