diff --git a/browser/dom/caret.ts b/browser/dom/caret.ts index 847c0b0..2bad859 100644 --- a/browser/dom/caret.ts +++ b/browser/dom/caret.ts @@ -41,7 +41,7 @@ interface ReactFiber { * @return カーソルと選択範囲の情報 * @throws {Error} #text-inputとReact Componentの隠しpropertyが見つからなかった */ -export function caret(): CaretInfo { +export const caret = (): CaretInfo => { const textarea = textInput(); if (!textarea) { throw Error(`#text-input is not found.`); @@ -59,4 +59,4 @@ export function caret(): CaretInfo { return (textarea[ reactKey ] as ReactFiber).return.return.stateNode.props; -} +}; diff --git a/browser/dom/click.ts b/browser/dom/click.ts index d6350ba..fa85786 100644 --- a/browser/dom/click.ts +++ b/browser/dom/click.ts @@ -15,10 +15,10 @@ export interface ClickOptions { } /** Emulate click event sequences */ -export async function click( +export const click = async ( element: HTMLElement, options: ClickOptions, -): Promise { +): Promise => { const mouseOptions: MouseEventInit = { button: options.button ?? 0, clientX: options.X, @@ -37,17 +37,17 @@ export async function click( // ScrapboxのReactの処理が終わるまで少し待つ // 待ち時間は感覚で決めた await sleep(10); -} +}; export interface HoldDownOptions extends ClickOptions { holding?: number; } /** Emulate long tap event sequence */ -export async function holdDown( +export const holdDown = async ( element: HTMLElement, options: HoldDownOptions, -): Promise { +): Promise => { const touch = new Touch({ identifier: 0, target: element, @@ -79,4 +79,4 @@ export async function holdDown( // ScrapboxのReactの処理が終わるまで少し待つ // 待ち時間は感覚で決めた await sleep(10); -} +}; diff --git a/browser/dom/edit.ts b/browser/dom/edit.ts index a722afe..c22a84c 100644 --- a/browser/dom/edit.ts +++ b/browser/dom/edit.ts @@ -6,38 +6,45 @@ import { textInput } from "./dom.ts"; import { isArray, isNumber, isString } from "../../is.ts"; import { sleep } from "../../sleep.ts"; -export function undo(count = 1) { +export const undo = (count = 1): void => { for (const _ of range(0, count)) { press("z", { ctrlKey: true }); } -} -export function redo(count = 1) { +}; +export const redo = (count = 1): void => { for (const _ of range(0, count)) { press("z", { shiftKey: true, ctrlKey: true }); } -} +}; -export function insertIcon(count = 1) { +export const insertIcon = (count = 1): void => { for (const _ of range(0, count)) { press("i", { ctrlKey: true }); } -} +}; -export function insertTimestamp(index = 1) { +export const insertTimestamp = (index = 1): void => { for (const _ of range(0, index)) { press("t", { altKey: true }); } -} +}; -export async function insertLine(lineNo: number, text: string) { +export const insertLine = async ( + lineNo: number, + text: string, +): Promise => { await goLine(lineNo); goHead(); press("Enter"); press("ArrowUp"); await insertText(text); -} +}; -export async function replaceLines(start: number, end: number, text: string) { +export const replaceLines = async ( + start: number, + end: number, + text: string, +): Promise => { await goLine(start); goHead(); for (const _ of range(start, end)) { @@ -45,9 +52,12 @@ export async function replaceLines(start: number, end: number, text: string) { } press("End", { shiftKey: true }); await insertText(text); -} +}; -export async function deleteLines(from: number | string | string[], count = 1) { +export const deleteLines = async ( + from: number | string | string[], + count = 1, +): Promise => { if (isNumber(from)) { if (getLineCount() === from + count) { await goLine(from - 1); @@ -78,74 +88,74 @@ export async function deleteLines(from: number | string | string[], count = 1) { throw new TypeError( `The type of value must be number | string | string[] but actual is "${typeof from}"`, ); -} +}; -export function indentLines(count = 1) { +export const indentLines = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowRight", { ctrlKey: true }); } -} -export function outdentLines(count = 1) { +}; +export const outdentLines = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowLeft", { ctrlKey: true }); } -} -export function moveLines(count: number) { +}; +export const moveLines = (count: number): void => { if (count > 0) { downLines(count); } else { upLines(-count); } -} +}; // to行目の後ろに移動させる -export function moveLinesBefore(from: number, to: number) { +export const moveLinesBefore = (from: number, to: number): void => { const count = to - from; if (count >= 0) { downLines(count); } else { upLines(-count - 1); } -} -export function upLines(count = 1) { +}; +export const upLines = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowUp", { ctrlKey: true }); } -} -export function downLines(count = 1) { +}; +export const downLines = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowDown", { ctrlKey: true }); } -} +}; -export function indentBlocks(count = 1) { +export const indentBlocks = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowRight", { altKey: true }); } -} -export function outdentBlocks(count = 1) { +}; +export const outdentBlocks = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowLeft", { altKey: true }); } -} -export function moveBlocks(count: number) { +}; +export const moveBlocks = (count: number): void => { if (count > 0) { downBlocks(count); } else { upBlocks(-count); } -} -export function upBlocks(count = 1) { +}; +export const upBlocks = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowUp", { altKey: true }); } -} -export function downBlocks(count = 1) { +}; +export const downBlocks = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowDown", { altKey: true }); } -} +}; -export async function insertText(text: string) { +export const insertText = async (text: string): Promise => { const cursor = textInput(); if (!cursor) { throw Error("#text-input is not ditected."); @@ -156,4 +166,4 @@ export async function insertText(text: string) { const event = new InputEvent("input", { bubbles: true }); cursor.dispatchEvent(event); await sleep(1); // 待ち時間は感覚で決めた -} +}; diff --git a/browser/dom/isHeightViewable.ts b/browser/dom/isHeightViewable.ts index 4fc8497..a67c92f 100644 --- a/browser/dom/isHeightViewable.ts +++ b/browser/dom/isHeightViewable.ts @@ -2,7 +2,7 @@ /// /// -export function isHeightViewable(element: HTMLElement) { +export const isHeightViewable = (element: HTMLElement): boolean => { const { top, bottom } = element.getBoundingClientRect(); return top >= 0 && bottom <= window.innerHeight; -} +}; diff --git a/browser/dom/motion.ts b/browser/dom/motion.ts index 2ffc2de..9554e05 100644 --- a/browser/dom/motion.ts +++ b/browser/dom/motion.ts @@ -18,13 +18,14 @@ import { caret } from "./caret.ts"; import { isHeightViewable } from "./isHeightViewable.ts"; import { range } from "../../range.ts"; -/** カーソル行の行末を長押ししてfocusを得る +/** @deprecated + * カーソル行の行末を長押ししてfocusを得る * * mobile版scrapbox用 * * @param [holding=1000] 長押しする時間(ミリ秒単位) */ -export async function focusEnd(holding = 1000) { +export const focusEnd = async (holding = 1000): Promise => { const target = getLineDOM(caret().position.line) ?.getElementsByClassName( "text", @@ -34,69 +35,69 @@ export async function focusEnd(holding = 1000) { const { right, top, height } = target.getBoundingClientRect(); await holdDown(target, { X: right + 1, Y: top + height / 2, holding }); -} +}; /** カーソルを左に動かす * * @param [count=1] 動かす回数 */ -export function moveLeft(count = 1) { +export const moveLeft = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowLeft"); } -} +}; /** カーソルを上に動かす * * @param [count=1] 動かす回数 */ -export function moveUp(count = 1) { +export const moveUp = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowUp"); } -} +}; /** カーソルを下に動かす * * @param [count=1] 動かす回数 */ -export function moveDown(count = 1) { +export const moveDown = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowDown"); } -} +}; /** カーソルを右に動かす * * @param [count=1] 動かす回数 */ -export function moveRight(count = 1) { +export const moveRight = (count = 1): void => { for (const _ of range(0, count)) { press("ArrowRight"); } -} +}; /** インデントを除いた行頭に移動する */ -export function goHeadWithoutBlank() { +export const goHeadWithoutBlank = (): void => { press("End"); press("Home"); -} +}; /** 最後の非空白文字に移動する */ -export function goEndWithoutBlank() { +export const goEndWithoutBlank = (): void => { press("End"); moveLeft( getText(caret().position.line)?.match?.(/(\s*)$/)?.[1]?.length ?? 0, ); -} +}; /** 行頭に移動する */ -export function goHead() { +export const goHead = (): void => { press("Home"); press("Home"); -} +}; /** 行末に移動する */ -export function goEnd() { +export const goEnd = (): void => { press("End"); -} +}; /** 最初の行の行頭に移動する */ -export async function goHeadLine() { +export const goHeadLine = async (): Promise => { const target = getHeadLineDOM(); if (!target) throw Error(".line:first-of-type can't be found."); if (!isHeightViewable(target)) target.scrollIntoView({ block: "center" }); @@ -105,26 +106,28 @@ export async function goHeadLine() { if (!charDOM) throw Error(".line:first-of-type .c-0 can't be found."); const { left, top } = charDOM.getBoundingClientRect(); await click(target, { X: left, Y: top }); -} +}; /** 最後の行の行末に移動する */ -export async function goLastLine() { +export const goLastLine = async (): Promise => { await _goLine(getTailLineDOM()); -} +}; /** 任意の行の行末に移動する * * @param value 移動したい行の行番号 or 行ID or 行のDOM */ -export async function goLine(value: string | number | HTMLElement | undefined) { +export const goLine = async ( + value: string | number | HTMLElement | undefined, +): Promise => { await _goLine(getLineDOM(value)); -} -async function _goLine(target: HTMLDivElement | undefined) { +}; +const _goLine = async (target: HTMLDivElement | undefined) => { if (!target) throw Error("The target line DOM is failed to find."); if (!isHeightViewable(target)) target.scrollIntoView({ block: "center" }); const { right, top, height } = target.getElementsByClassName("text")[0] .getBoundingClientRect(); await click(target, { X: right + 1, Y: top + height / 2 }); -} +}; /** 任意の文字に移動する * @@ -133,7 +136,10 @@ async function _goLine(target: HTMLDivElement | undefined) { * @param line 移動したい文字がある行 * @param pos 移動したい文字の列 */ -export async function goChar(line: string | number | HTMLElement, pos: number) { +export const goChar = async ( + line: string | number | HTMLElement, + pos: number, +): Promise => { const charDOM = getCharDOM(line, pos); if (!charDOM) { throw Error( @@ -144,25 +150,25 @@ export async function goChar(line: string | number | HTMLElement, pos: number) { const { left, top } = charDOM.getBoundingClientRect(); await click(charDOM, { X: left, Y: top }); -} +}; /** 画面に収まる最大行数を計算する * * 行の高さは最後の行を基準とする */ -function getVisibleLineCount() { +const getVisibleLineCount = (): number => { const clientHeight = getTailLineDOM()?.clientHeight; if (clientHeight === undefined) { throw Error("Could not find .line:last-of-type"); } return Math.round(window.innerHeight / clientHeight); -} +}; /** 半ページ上にスクロールする * * @param [count=1] スクロール回数 */ -export async function scrollHalfUp(count = 1) { +export const scrollHalfUp = async (count = 1): Promise => { const lineNo = getLineNo(caret().position.line); if (lineNo === undefined) { throw Error("Could not detect the present cursor line No."); @@ -171,12 +177,12 @@ export async function scrollHalfUp(count = 1) { (lineNo - getVisibleLineCount() / 2) * count, ); await goLine(Math.max(index, 0)); -} +}; /** 半ページ下にスクロールする * * @param [count=1] スクロール回数 */ -export async function scrollHalfDown(count = 1) { +export const scrollHalfDown = async (count = 1): Promise => { const lineNo = getLineNo(caret().position.line); if (lineNo === undefined) { throw Error("Could not detect the present cursor line No."); @@ -185,22 +191,22 @@ export async function scrollHalfDown(count = 1) { (lineNo + getVisibleLineCount() / 2) * count, ); await goLine(Math.min(index, getLineCount() - 1)); -} +}; /** 1ページ上にスクロールする * * @param [count=1] スクロール回数 */ -export function scrollUp(count = 1) { +export const scrollUp = (count = 1): void => { for (const _ of range(0, count)) { press("PageUp"); } -} +}; /** 1ページ下にスクロールする * * @param [count=1] スクロール回数 */ -export function scrollDown(count = 1) { +export const scrollDown = (count = 1): void => { for (const _ of range(0, count)) { press("PageDown"); } -} +}; diff --git a/browser/dom/node.ts b/browser/dom/node.ts index 0897057..4357120 100644 --- a/browser/dom/node.ts +++ b/browser/dom/node.ts @@ -3,7 +3,7 @@ /// import { isNone, isNumber, isString } from "../../is.ts"; import { ensureArray } from "../../ensure.ts"; -import type { Scrapbox } from "../../deps/scrapbox.ts"; +import type { Line, Scrapbox } from "../../deps/scrapbox.ts"; import { lines } from "./dom.ts"; import * as Text from "../../text.ts"; declare const scrapbox: Scrapbox; @@ -14,9 +14,9 @@ declare const scrapbox: Scrapbox; * * @param value - value the line id of which you want to get */ -export function getLineId( +export const getLineId = ( value?: number | string | T, -): string | undefined { +): string | undefined => { if (isNone(value)) return undefined; // 行番号のとき @@ -33,7 +33,7 @@ export function getLineId( if (line) return line.id.slice(1); return undefined; -} +}; /** Get the line number from value * @@ -41,7 +41,9 @@ export function getLineId( * * @param value - value the line number of which you want to get */ -export function getLineNo(value?: number | string | T) { +export const getLineNo = ( + value?: number | string | T, +): number | undefined => { if (isNone(value)) return undefined; // 行番号のとき @@ -49,9 +51,11 @@ export function getLineNo(value?: number | string | T) { // 行ID or DOMのとき const id = getLineId(value); return id ? getLines().findIndex((line) => line.id === id) : -1; -} +}; -export function getLine(value?: number | string | T) { +export const getLine = ( + value?: number | string | T, +): Line | undefined => { if (isNone(value)) return undefined; // 行番号のとき @@ -61,9 +65,11 @@ export function getLine(value?: number | string | T) { // 行ID or DOMのとき const id = getLineId(value); return id ? getLines().find((line) => line.id === id) : undefined; -} +}; -export function getLineDOM(value?: number | string | T) { +export const getLineDOM = ( + value?: number | string | T, +): HTMLDivElement | undefined => { if (isLineDOM(value)) return value; const id = getLineId(value); @@ -71,20 +77,20 @@ export function getLineDOM(value?: number | string | T) { const line = document.getElementById(`L${id}`); if (isNone(line)) return undefined; return line as HTMLDivElement; -} -export function isLineDOM(dom: unknown): dom is HTMLDivElement { - return dom instanceof HTMLDivElement && dom.classList.contains("line"); -} -export function getLineCount() { - return getLines().length; -} +}; +export const isLineDOM = (dom: unknown): dom is HTMLDivElement => + dom instanceof HTMLDivElement && dom.classList.contains("line"); + +export const getLineCount = (): number => getLines().length; -export function getLines() { +export const getLines = (): Line[] => { ensureArray(scrapbox.Page.lines, "scrapbox.Page.lines"); return scrapbox.Page.lines; -} +}; -export function getText(value?: number | string | T) { +export const getText = ( + value?: number | string | T, +): string | undefined => { if (isNone(value)) return undefined; // 数字と文字列は行として扱う @@ -110,112 +116,121 @@ export function getText(value?: number | string | T) { chars.push(getIndex(dom)); } return line.text.slice(Math.min(...chars), Math.max(...chars) + 1); -} +}; -export function getExternalLink(dom: HTMLElement) { +export const getExternalLink = (dom: HTMLElement): HTMLElement | undefined => { const link = dom.closest(".link"); if (isNone(link)) return undefined; return link as HTMLElement; -} -export function getInternalLink(dom: HTMLElement) { +}; +export const getInternalLink = (dom: HTMLElement): HTMLElement | undefined => { const link = dom.closest(".page-link"); if (isNone(link)) return undefined; return link as HTMLElement; -} -export function getLink(dom: HTMLElement) { +}; +export const getLink = (dom: HTMLElement) => { const link = dom.closest(".link, .page-link"); if (isNone(link)) return undefined; return link as HTMLElement; -} +}; -export function getFormula(dom: HTMLElement) { +export const getFormula = (dom: HTMLElement): HTMLElement | undefined => { const formula = dom.closest(".formula"); if (isNone(formula)) return undefined; return formula as HTMLElement; -} -export function getNextLine( +}; +export const getNextLine = ( value?: number | string | T, -) { +): Line | undefined => { const index = getLineNo(value); if (isNone(index)) return undefined; return getLine(index + 1); -} +}; -export function getPrevLine( +export const getPrevLine = ( value?: number | string | T, -) { +): Line | undefined => { const index = getLineNo(value); if (isNone(index)) return undefined; return getLine(index - 1); -} +}; -export function getHeadLineDOM() { +export const getHeadLineDOM = (): HTMLDivElement | undefined => { const line = lines()?.firstElementChild; if (isNone(line)) return undefined; return line as HTMLDivElement; -} -export function getTailLineDOM() { +}; +export const getTailLineDOM = (): HTMLDivElement | undefined => { const line = lines()?.lastElementChild; if (isNone(line)) return undefined; return line as HTMLDivElement; -} -export function getIndentCount( +}; +export const getIndentCount = ( value?: number | string | T, -) { +): number | undefined => { const text = getText(value); if (isNone(text)) return undefined; return Text.getIndentCount(text); -} +}; /** 指定した行の配下にある行の数を返す * * @param value 指定したい行の行番号か行IDかDOM */ -export function getIndentLineCount( +export const getIndentLineCount = ( value?: number | string | T, -) { +): number | undefined => { const index = getLineNo(value); if (isNone(index)) return; return Text.getIndentLineCount(index, getLines()); -} +}; -export function* getChars(value: T) { +export function* getChars( + value: T, +): Generator { const chars = value.getElementsByClassName("char-index"); for (let i = 0; i < chars.length; i++) { yield chars[0] as HTMLSpanElement; } } -export function isCharDOM(dom: unknown): dom is HTMLSpanElement { +export const isCharDOM = (dom: unknown): dom is HTMLSpanElement => { return dom instanceof HTMLSpanElement && dom.classList.contains("char-index"); -} +}; -export function getIndex(dom: HTMLSpanElement) { +export const getIndex = (dom: HTMLSpanElement): number => { if (!isCharDOM(dom)) throw Error("A char DOM is required."); const index = dom.className.match(/c-(\d+)/)?.[1]; if (isNone(index)) throw Error('.char-index must have ".c-{\\d}"'); return parseInt(index); -} -export function getHeadCharDOM(dom?: HTMLElement) { +}; +export const getHeadCharDOM = ( + dom?: HTMLElement, +): HTMLSpanElement | undefined => { const char = dom?.getElementsByClassName?.("c-0")?.[0]; return isCharDOM(char) ? char : undefined; -} +}; -export function getTailCharDOM(dom?: HTMLElement) { +export const getTailCharDOM = ( + dom?: HTMLElement, +): HTMLSpanElement | undefined => { const char = dom?.querySelector(".char-index:last-of-type"); return isCharDOM(char) ? char : undefined; -} +}; -export function getCharDOM( +export const getCharDOM = ( line: string | number | T, pos: number, -) { +): HTMLSpanElement | undefined => { const char = getLineDOM(line)?.getElementsByClassName?.(`c-${pos}`)?.[0]; return isCharDOM(char) ? char : undefined; -} -export function getDOMFromPoint(x: number, y: number) { +}; +export const getDOMFromPoint = ( + x: number, + y: number, +): { char?: HTMLSpanElement; line?: HTMLDivElement } => { const targets = document.elementsFromPoint(x, y); const char = targets.find((target) => isCharDOM(target)); const line = targets.find((target) => isLineDOM(target)); @@ -223,4 +238,4 @@ export function getDOMFromPoint(x: number, y: number) { char: isNone(char) ? undefined : char as HTMLSpanElement, line: isNone(line) ? undefined : line as HTMLDivElement, }; -} +}; diff --git a/browser/dom/press.ts b/browser/dom/press.ts index c6eba79..c995874 100644 --- a/browser/dom/press.ts +++ b/browser/dom/press.ts @@ -21,10 +21,10 @@ export interface PressOptions { * @param key 押したいキーの名前 * @param pressOptions options */ -export function press( +export const press = ( key: KeyName, pressOptions?: PressOptions, -): void { +): void => { const { noModifiedKeys = false, ...rest } = pressOptions ?? {}; const options = { bubbles: true, @@ -36,7 +36,7 @@ export function press( if (!textarea) throw Error("#text-input must exist."); textarea.dispatchEvent(new KeyboardEvent("keydown", options)); textarea.dispatchEvent(new KeyboardEvent("keyup", options)); -} +}; export type KeyName = keyof typeof KEYCODE_MAP; const KEYCODE_MAP = { diff --git a/browser/dom/statusBar.ts b/browser/dom/statusBar.ts index 5d77fc4..c0d0ff2 100644 --- a/browser/dom/statusBar.ts +++ b/browser/dom/statusBar.ts @@ -8,7 +8,7 @@ export interface UseStatusBarResult { } /** .status-barの一区画を取得し、各種操作函数を返す */ -export function useStatusBar() { +export const useStatusBar = (): UseStatusBarResult => { const bar = statusBar(); if (!bar) throw new Error(`div.status-bar can't be found`); @@ -23,7 +23,7 @@ export function useStatusBar() { }, dispose: () => status.remove(), }; -} +}; export interface ItemGroup { type: "group"; @@ -36,7 +36,7 @@ export type Item = | { type: "text"; text: string } | ItemGroup; -function makeGroup(...items: Item[]): HTMLSpanElement | undefined { +const makeGroup = (...items: Item[]): HTMLSpanElement | undefined => { const nodes = items.flatMap((item) => { switch (item.type) { case "spinner": @@ -59,31 +59,31 @@ function makeGroup(...items: Item[]): HTMLSpanElement | undefined { span.classList.add("item-group"); span.append(...nodes); return span; -} -function makeItem(child: string | Node) { +}; +const makeItem = (child: string | Node) => { const span = document.createElement("span"); span.classList.add("item"); span.append(child); return span; -} +}; /** スピナーを作る */ -function makeSpinner() { +const makeSpinner = () => { const i = document.createElement("i"); i.classList.add("fa", "fa-spinner"); return makeItem(i); -} +}; /** チェックマークを作る */ -function makeCheckCircle() { +const makeCheckCircle = () => { const i = document.createElement("i"); i.classList.add("kamon", "kamon-check-circle"); return makeItem(i); -} +}; /** 警告アイコンを作る */ -function makeExclamationTriangle() { +const makeExclamationTriangle = () => { const i = document.createElement("i"); i.classList.add("fas", "fa-exclamation-triangle"); return makeItem(i); -} +}; diff --git a/browser/websocket/_fetch.ts b/browser/websocket/_fetch.ts index fc9aa2b..e722e5c 100644 --- a/browser/websocket/_fetch.ts +++ b/browser/websocket/_fetch.ts @@ -22,11 +22,11 @@ export type PushCommitInit = { userId: string; }; -export async function pushCommit( +export const pushCommit = async ( request: RequestFunc, changes: Change[] | [Delete] | [Pin], commitInit: PushCommitInit, -) { +) => { if (changes.length === 0) return { commitId: commitInit.parentId }; const res = await request("socket.io-request", { method: "commit", @@ -39,9 +39,9 @@ export async function pushCommit( }, }); return res as { commitId: string }; -} +}; -export async function pushWithRetry( +export const pushWithRetry = async ( request: RequestFunc, changes: Change[] | [Delete] | [Pin], { project, title, retry = 3, parentId, ...commitInit }: @@ -51,7 +51,7 @@ export async function pushWithRetry( title: string; retry?: number; }, -) { +) => { try { const res = await pushCommit(request, changes, { parentId, @@ -78,4 +78,4 @@ export async function pushWithRetry( throw Error("Faild to retry pushing."); } return parentId; -} +}; diff --git a/browser/websocket/applyCommit.ts b/browser/websocket/applyCommit.ts index dee3a5c..11fcb02 100644 --- a/browser/websocket/applyCommit.ts +++ b/browser/websocket/applyCommit.ts @@ -1,5 +1,5 @@ import type { CommitNotification } from "../../deps/socket.ts"; -import type { Line } from "../../deps/scrapbox.ts"; +import type { Line } from "../../deps/scrapbox-rest.ts"; import { getUnixTimeFromId } from "./id.ts"; export interface ApplyCommitProp { @@ -17,11 +17,11 @@ export interface ApplyCommitProp { * @param lines commitsを適用する行 * @param changes 適用するcommits */ -export function applyCommit( +export const applyCommit = ( lines: readonly Line[], changes: CommitNotification["changes"], { updated, userId }: ApplyCommitProp, -) { +): Line[] => { const newLines = [...lines]; const getPos = (lineId: string) => { const position = newLines.findIndex(({ id }) => id === lineId); @@ -57,4 +57,4 @@ export function applyCommit( } } return newLines; -} +}; diff --git a/browser/websocket/deletePage.ts b/browser/websocket/deletePage.ts index c761fc4..c486f80 100644 --- a/browser/websocket/deletePage.ts +++ b/browser/websocket/deletePage.ts @@ -14,11 +14,11 @@ export interface DeletePageOptions { * @param title 削除したいページのタイトル * @param options 使用したいSocketがあれば指定する */ -export async function deletePage( +export const deletePage = async ( project: string, title: string, options?: DeletePageOptions, -): Promise { +): Promise => { const [ { pageId, commitId: parentId, persistent }, projectId, @@ -47,4 +47,4 @@ export async function deletePage( } finally { if (!injectedSocket) await disconnect(socket); } -} +}; diff --git a/browser/websocket/diff.ts b/browser/websocket/diff.ts index 16840f9..a68780a 100644 --- a/browser/websocket/diff.ts +++ b/browser/websocket/diff.ts @@ -36,10 +36,10 @@ export interface DiffResult { buildSES(): Generator, void, unknown>; } -export function diff( +export const diff = ( left: ArrayLike, right: ArrayLike, -): DiffResult { +): DiffResult => { const reversed = left.length > right.length; const a = reversed ? right : left; const b = reversed ? left : right; @@ -114,7 +114,7 @@ export function diff( } }, }; -} +}; export function* toExtendedChanges( changes: Iterable>, @@ -165,16 +165,14 @@ export function* toExtendedChanges( yield* flush(); } -function makeReplaced( +const makeReplaced = ( left: Added, right: Deleted, -): Replaced { - return { - value: left.value, - oldValue: right.value, - type: "replaced", - }; -} +): Replaced => ({ + value: left.value, + oldValue: right.value, + type: "replaced", +}); function* reverse(list: ArrayLike) { for (let i = list.length - 1; i >= 0; i--) { diff --git a/browser/websocket/id.ts b/browser/websocket/id.ts index a979c71..0a69505 100644 --- a/browser/websocket/id.ts +++ b/browser/websocket/id.ts @@ -3,7 +3,7 @@ import { getProfile } from "../../rest/profile.ts"; /** cached user ID */ let userId: string | undefined; -export async function getUserId() { +export const getUserId = async (): Promise => { if (userId !== undefined) return userId; const user = await getProfile(); @@ -12,11 +12,11 @@ export async function getUserId() { } userId = user.id; return userId; -} +}; /** cached pairs of project name and project id */ const projectMap = new Map(); -export async function getProjectId(project: string) { +export const getProjectId = async (project: string): Promise => { const cachedId = projectMap.get(project); if (cachedId !== undefined) return cachedId; @@ -28,22 +28,18 @@ export async function getProjectId(project: string) { const { id } = result.value; projectMap.set(project, id); return id; -} +}; -function zero(n: string) { - return n.padStart(8, "0"); -} +const zero = (n: string) => n.padStart(8, "0"); -export function createNewLineId(userId: string) { +export const createNewLineId = (userId: string): string => { const time = Math.floor(new Date().getTime() / 1000).toString(16); const rand = Math.floor(0xFFFFFE * Math.random()).toString(16); return `${zero(time).slice(-8)}${userId.slice(-6)}0000${zero(rand)}`; -} -export function getUnixTimeFromId(id: string) { +}; +export const getUnixTimeFromId = (id: string): number => { if (!isId(id)) throw SyntaxError(`"${id}" is an invalid id.`); return parseInt(`0x${id.slice(0, 8)}`, 16); -} -export function isId(id: string) { - return /^[a-f\d]{24,32}$/.test(id); -} +}; +export const isId = (id: string): boolean => /^[a-f\d]{24,32}$/.test(id); diff --git a/browser/websocket/makeChanges.ts b/browser/websocket/makeChanges.ts index ea1b8fd..0b12cf8 100644 --- a/browser/websocket/makeChanges.ts +++ b/browser/websocket/makeChanges.ts @@ -15,11 +15,11 @@ export interface Init { userId: string; head: HeadData; } -export function makeChanges( +export const makeChanges = ( left: Pick[], right: string[], { userId, head }: Init, -) { +): Change[] => { // 改行文字が入るのを防ぐ const right_ = right.flatMap((text) => text.split("\n")); // 本文の差分 @@ -51,10 +51,10 @@ export function makeChanges( } return changes; -} +}; /** テキストに含まれる全てのリンクと最初の画像を探す */ -function findLinksAndImage(text: string): [string[], string | null] { +const findLinksAndImage = (text: string): [string[], string | null] => { const rows = parseToRows(text); const blocks = packRows(rows, { hasTitle: true }).flatMap((pack) => { switch (pack.type) { @@ -115,7 +115,7 @@ function findLinksAndImage(text: string): [string[], string | null] { } return [links, image]; -} +}; function* blocksToNodes(blocks: Iterable) { for (const block of blocks) { diff --git a/browser/websocket/patch.ts b/browser/websocket/patch.ts index dcd47d3..941a947 100644 --- a/browser/websocket/patch.ts +++ b/browser/websocket/patch.ts @@ -19,7 +19,7 @@ export interface PatchOptions { * @param update 書き換え後の本文を作成する函数。引数には現在の本文が渡される。空配列を返すとページが削除される。undefinedを返すと書き換えを中断する * @param options 使用したいSocketがあれば指定する */ -export async function patch( +export const patch = async ( project: string, title: string, update: ( @@ -27,7 +27,7 @@ export async function patch( metadata: HeadData, ) => string[] | undefined | Promise, options?: PatchOptions, -): Promise { +): Promise => { const [ head_, projectId, @@ -90,4 +90,4 @@ export async function patch( } finally { if (!injectedSocket) await disconnect(socket); } -} +}; diff --git a/browser/websocket/pin.ts b/browser/websocket/pin.ts index d9ba8cf..602fd31 100644 --- a/browser/websocket/pin.ts +++ b/browser/websocket/pin.ts @@ -21,11 +21,11 @@ export interface PinOptions { * @param title ピン留めしたいページのタイトル * @param options 使用したいSocketがあれば指定する */ -export async function pin( +export const pin = async ( project: string, title: string, options?: PinOptions, -): Promise { +): Promise => { const [ head, projectId, @@ -63,7 +63,7 @@ export async function pin( } finally { if (!injectedSocket) await disconnect(socket); } -} +}; export interface UnPinOptions { socket?: Socket; @@ -73,11 +73,11 @@ export interface UnPinOptions { * @param project ピン留めを外したいページのproject * @param title ピン留めを外したいページのタイトル */ -export async function unpin( +export const unpin = async ( project: string, title: string, options: UnPinOptions, -): Promise { +): Promise => { const [ head, projectId, @@ -109,7 +109,7 @@ export async function unpin( } finally { if (!injectedSocket) await disconnect(socket); } -} +}; export const pinNumber = (): number => Number.MAX_SAFE_INTEGER - Math.floor(Date.now() / 1000); diff --git a/browser/websocket/pull.ts b/browser/websocket/pull.ts index 58d4182..9417a83 100644 --- a/browser/websocket/pull.ts +++ b/browser/websocket/pull.ts @@ -10,7 +10,10 @@ export interface HeadData { links: string[]; lines: Line[]; } -export async function pull(project: string, title: string): Promise { +export const pull = async ( + project: string, + title: string, +): Promise => { const result = await getPage(project, title); // TODO: 編集不可なページはStream購読だけ提供する @@ -28,4 +31,4 @@ export async function pull(project: string, title: string): Promise { pin, lines, }; -} +}; diff --git a/browser/websocket/socket.ts b/browser/websocket/socket.ts index 3df58dd..4fed4b4 100644 --- a/browser/websocket/socket.ts +++ b/browser/websocket/socket.ts @@ -2,15 +2,13 @@ import { Socket, socketIO } from "../../deps/socket.ts"; export type { Socket } from "../../deps/socket.ts"; /** 新しいsocketを作る */ -export function makeSocket() { - return socketIO(); -} +export const makeSocket = (): Promise => socketIO(); /** websocketに(再)接続する * * @param socket 接続したいsocket */ -export async function connect(socket: Socket): Promise { +export const connect = async (socket: Socket): Promise => { if (socket.connected) return; const waiting = new Promise((resolve) => @@ -18,13 +16,13 @@ export async function connect(socket: Socket): Promise { ); socket.connect(); await waiting; -} +}; /** websocketを切断する * * @param socket 切断したいsocket */ -export async function disconnect(socket: Socket): Promise { +export const disconnect = async (socket: Socket): Promise => { if (socket.disconnected) return; const waiting = new Promise((resolve) => { @@ -37,4 +35,4 @@ export async function disconnect(socket: Socket): Promise { }); socket.disconnect(); await waiting; -} +};