Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ module.exports = {
'max-nested-callbacks': [0],
'max-params': [0],
'max-statements': [0],
'multiline-comment-style': [2, 'separate-lines'],
'multiline-comment-style': [0],
'new-cap': [0],
'no-alert': [0],
'no-array-constructor': [0], // handled by @typescript-eslint/no-array-constructor
Expand Down
2 changes: 1 addition & 1 deletion web_src/js/modules/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type ToastOpts = {

type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast };

// See https://github.com/apvarun/toastify-js#api for options
/** See https://github.com/apvarun/toastify-js#api for options */
function showToast(message: string, level: Intent, {gravity, position, duration, useHtmlBody, preventDuplicates = true, ...other}: ToastOpts = {}): Toast {
const body = useHtmlBody ? message : htmlEscape(message);
const parent = document.querySelector('.ui.dimmer.active') ?? document.body;
Expand Down
1 change: 0 additions & 1 deletion web_src/js/render/plugins/3d-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {extname} from '../../utils.ts';

// support common 3D model file formats, use online-3d-viewer library for rendering

// eslint-disable-next-line multiline-comment-style
/* a simple text STL file example:
solid SimpleTriangle
facet normal 0 0 1
Expand Down
28 changes: 14 additions & 14 deletions web_src/js/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,38 @@ import {decode, encode} from 'uint8-to-base64';
import type {IssuePageInfo, IssuePathInfo, RepoOwnerPathInfo} from './types.ts';
import {toggleElemClass, toggleElem} from './utils/dom.ts';

// transform /path/to/file.ext to /path/to
/** transform /path/to/file.ext to /path/to */
export function dirname(path: string): string {
const lastSlashIndex = path.lastIndexOf('/');
return lastSlashIndex < 0 ? '' : path.substring(0, lastSlashIndex);
}

// transform /path/to/file.ext to file.ext
/** transform /path/to/file.ext to file.ext */
export function basename(path: string): string {
const lastSlashIndex = path.lastIndexOf('/');
return lastSlashIndex < 0 ? path : path.substring(lastSlashIndex + 1);
}

// transform /path/to/file.ext to .ext
/** transform /path/to/file.ext to .ext */
export function extname(path: string): string {
const lastSlashIndex = path.lastIndexOf('/');
const lastPointIndex = path.lastIndexOf('.');
if (lastSlashIndex > lastPointIndex) return '';
return lastPointIndex < 0 ? '' : path.substring(lastPointIndex);
}

// test whether a variable is an object
/** test whether a variable is an object */
export function isObject(obj: any): boolean {
return Object.prototype.toString.call(obj) === '[object Object]';
}

// returns whether a dark theme is enabled
/** returns whether a dark theme is enabled */
export function isDarkTheme(): boolean {
const style = window.getComputedStyle(document.documentElement);
return style.getPropertyValue('--is-dark-theme').trim().toLowerCase() === 'true';
}

// strip <tags> from a string
/** strip <tags> from a string */
export function stripTags(text: string): string {
return text.replace(/<[^>]*>?/g, '');
}
Expand Down Expand Up @@ -62,27 +62,27 @@ export function parseIssuePageInfo(): IssuePageInfo {
};
}

// parse a URL, either relative '/path' or absolute 'https://localhost/path'
/** parse a URL, either relative '/path' or absolute 'https://localhost/path' */
export function parseUrl(str: string): URL {
return new URL(str, str.startsWith('http') ? undefined : window.location.origin);
}

// return current locale chosen by user
/** return current locale chosen by user */
export function getCurrentLocale(): string {
return document.documentElement.lang;
}

// given a month (0-11), returns it in the documents language
/** given a month (0-11), returns it in the documents language */
export function translateMonth(month: number) {
return new Date(Date.UTC(2022, month, 12)).toLocaleString(getCurrentLocale(), {month: 'short', timeZone: 'UTC'});
}

// given a weekday (0-6, Sunday to Saturday), returns it in the documents language
/** given a weekday (0-6, Sunday to Saturday), returns it in the documents language */
export function translateDay(day: number) {
return new Date(Date.UTC(2022, 7, day)).toLocaleString(getCurrentLocale(), {weekday: 'short', timeZone: 'UTC'});
}

// convert a Blob to a DataURI
/** convert a Blob to a DataURI */
export function blobToDataURI(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
try {
Expand All @@ -100,7 +100,7 @@ export function blobToDataURI(blob: Blob): Promise<string> {
});
}

// convert image Blob to another mime-type format.
/** convert image Blob to another mime-type format. */
export function convertImage(blob: Blob, mime: string): Promise<Blob> {
return new Promise(async (resolve, reject) => {
try {
Expand Down Expand Up @@ -143,15 +143,15 @@ export function toAbsoluteUrl(url: string): string {
return `${window.location.origin}${url}`;
}

// Encode an Uint8Array into a URLEncoded base64 string.
/** Encode an Uint8Array into a URLEncoded base64 string. */
export function encodeURLEncodedBase64(uint8Array: Uint8Array): string {
return encode(uint8Array)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}

// Decode a URLEncoded base64 to an Uint8Array.
/** Decode a URLEncoded base64 to an Uint8Array. */
export function decodeURLEncodedBase64(base64url: string): Uint8Array {
return decode(base64url
.replace(/_/g, '/')
Expand Down
7 changes: 4 additions & 3 deletions web_src/js/utils/color.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import tinycolor from 'tinycolor2';
import type {ColorInput} from 'tinycolor2';

// Returns relative luminance for a SRGB color - https://en.wikipedia.org/wiki/Relative_luminance
/** Returns relative luminance for a SRGB color - https://en.wikipedia.org/wiki/Relative_luminance */
// Keep this in sync with modules/util/color.go
function getRelativeLuminance(color: ColorInput): number {
const {r, g, b} = tinycolor(color).toRgb();
Expand All @@ -12,8 +12,9 @@ function useLightText(backgroundColor: ColorInput): boolean {
return getRelativeLuminance(backgroundColor) < 0.453;
}

// Given a background color, returns a black or white foreground color that the highest
// contrast ratio. In the future, the APCA contrast function, or CSS `contrast-color` will be better.
/** Given a background color, returns a black or white foreground color that the highest
* contrast ratio. */
// In the future, the APCA contrast function, or CSS `contrast-color` will be better.
// https://github.com/color-js/color.js/blob/eb7b53f7a13bb716ec8b28c7a56f052cd599acd9/src/contrast/APCA.js#L42
export function contrastColor(backgroundColor: ColorInput): string {
return useLightText(backgroundColor) ? '#fff' : '#000';
Expand Down
20 changes: 10 additions & 10 deletions web_src/js/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function queryElemSiblings<T extends Element>(el: Element, selector = '*'
}), fn);
}

// it works like jQuery.children: only the direct children are selected
/** it works like jQuery.children: only the direct children are selected */
export function queryElemChildren<T extends Element>(parent: Element | ParentNode, selector = '*', fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
if (isInFrontendUnitTest()) {
// https://github.com/capricorn86/happy-dom/issues/1620 : ":scope" doesn't work
Expand All @@ -81,7 +81,7 @@ export function queryElemChildren<T extends Element>(parent: Element | ParentNod
return applyElemsCallback<T>(parent.querySelectorAll(`:scope > ${selector}`), fn);
}

// it works like parent.querySelectorAll: all descendants are selected
/** it works like parent.querySelectorAll: all descendants are selected */
// in the future, all "queryElems(document, ...)" should be refactored to use a more specific parent if the targets are not for page-level components.
export function queryElems<T extends HTMLElement>(parent: Element | ParentNode, selector: string, fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
return applyElemsCallback<T>(parent.querySelectorAll(selector), fn);
Expand All @@ -95,8 +95,8 @@ export function onDomReady(cb: () => Promisable<void>) {
}
}

// checks whether an element is owned by the current document, and whether it is a document fragment or element node
// if it is, it means it is a "normal" element managed by us, which can be modified safely.
/** checks whether an element is owned by the current document, and whether it is a document fragment or element node
* if it is, it means it is a "normal" element managed by us, which can be modified safely. */
export function isDocumentFragmentOrElementNode(el: Node) {
try {
return el.ownerDocument === document && el.nodeType === Node.ELEMENT_NODE || el.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
Expand All @@ -106,8 +106,8 @@ export function isDocumentFragmentOrElementNode(el: Node) {
}
}

// autosize a textarea to fit content. Based on
// https://github.com/github/textarea-autosize
/** autosize a textarea to fit content. */
// Based on https://github.com/github/textarea-autosize
// ---------------------------------------------------------------------
// Copyright (c) 2018 GitHub, Inc.
//
Expand Down Expand Up @@ -246,8 +246,8 @@ export function onInputDebounce(fn: () => Promisable<any>) {

type LoadableElement = HTMLEmbedElement | HTMLIFrameElement | HTMLImageElement | HTMLScriptElement | HTMLTrackElement;

// Set the `src` attribute on an element and returns a promise that resolves once the element
// has loaded or errored.
/** Set the `src` attribute on an element and returns a promise that resolves once the element
* has loaded or errored. */
export function loadElem(el: LoadableElement, src: string) {
return new Promise((resolve) => {
el.addEventListener('load', () => resolve(true), {once: true});
Expand Down Expand Up @@ -286,7 +286,7 @@ export function isElemVisible(el: HTMLElement): boolean {
return !el.classList.contains('tw-hidden') && (el.offsetWidth || el.offsetHeight || el.getClientRects().length) && el.style.display !== 'none';
}

// replace selected text in a textarea while preserving editor history, e.g. CTRL-Z works after this
/** replace selected text in a textarea while preserving editor history, e.g. CTRL-Z works after this */
export function replaceTextareaSelection(textarea: HTMLTextAreaElement, text: string) {
const before = textarea.value.slice(0, textarea.selectionStart ?? undefined);
const after = textarea.value.slice(textarea.selectionEnd ?? undefined);
Expand Down Expand Up @@ -368,7 +368,7 @@ export function addDelegatedEventListener<T extends HTMLElement, E extends Event
}, options);
}

// Returns whether a click event is a left-click without any modifiers held
/** Returns whether a click event is a left-click without any modifiers held */
export function isPlainClick(e: MouseEvent) {
return e.button === 0 && !e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey;
}
Expand Down
4 changes: 2 additions & 2 deletions web_src/js/utils/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type ImageInfo = {
dppx?: number,
}

// decode a image and try to obtain width and dppx. It will never throw but instead
// return default values.
/** decode a image and try to obtain width and dppx. It will never throw but instead
* return default values. */
export async function imageInfo(blob: Blob): Promise<ImageInfo> {
let width = 0, dppx = 1; // dppx: 1 dot per pixel for non-HiDPI screens

Expand Down
4 changes: 2 additions & 2 deletions web_src/js/utils/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export function fillEmptyStartDaysWithZeroes(startDays: number[], data: DayDataO

let dateFormat: Intl.DateTimeFormat;

// format a Date object to document's locale, but with 24h format from user's current locale because this
// option is a personal preference of the user, not something that the document's locale should dictate.
/** Format a Date object to document's locale, but with 24h format from user's current locale because this
* option is a personal preference of the user, not something that the document's locale should dictate. */
export function formatDatetime(date: Date | number): string {
if (!dateFormat) {
// TODO: replace `hour12` with `Intl.Locale.prototype.getHourCycles` once there is broad browser support
Expand Down
4 changes: 2 additions & 2 deletions web_src/js/utils/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export function isUrl(url: string): boolean {
}
}

// Convert an absolute or relative URL to an absolute URL with the current origin. It only
// processes absolute HTTP/HTTPS URLs or relative URLs like '/xxx' or '//host/xxx'.
/** Convert an absolute or relative URL to an absolute URL with the current origin. It only
* processes absolute HTTP/HTTPS URLs or relative URLs like '/xxx' or '//host/xxx'. */
export function toOriginUrl(urlStr: string) {
try {
if (urlStr.startsWith('http://') || urlStr.startsWith('https://') || urlStr.startsWith('/')) {
Expand Down