From 50ca9a22491955abae50d520ae76d751cf4ae232 Mon Sep 17 00:00:00 2001 From: Qijia Liu Date: Mon, 16 Sep 2024 21:58:56 -0400 Subject: [PATCH] eslint 9 (#69) --- .eslintrc.cjs | 24 ------ eslint.config.mjs | 7 ++ package.json | 21 +++-- page/api.ts | 102 +++++++++++----------- page/customize.ts | 167 +++++++++++++++++++------------------ page/distribution.ts | 13 +-- page/global.d.ts | 8 +- page/index.html | 15 ++-- page/log.ts | 5 +- page/plugin.ts | 13 +-- page/scroll.ts | 42 +++++----- page/theme.ts | 25 +++--- page/ux.ts | 104 ++++++++++++----------- tests/test-generic.spec.ts | 39 +++++---- tests/test-theme.spec.ts | 6 +- tests/util.ts | 30 +++---- 16 files changed, 318 insertions(+), 303 deletions(-) delete mode 100644 .eslintrc.cjs create mode 100644 eslint.config.mjs diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 07ce29f..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,24 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true - }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'standard' - ], - parserOptions: { - ecmaVersion: 'latest', - parser: '@typescript-eslint/parser', - sourceType: 'module' - }, - plugins: [ - '@typescript-eslint', - 'eslint-plugin-html' - ], - rules: { - "@typescript-eslint/no-unused-vars": "error", - "no-undef": 0, - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..9a4ab9e --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,7 @@ +import antfu from '@antfu/eslint-config' + +export default antfu({ + formatters: { + html: true, + }, +}) diff --git a/package.json b/package.json index 0ab40fa..ae345af 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "dev": "parcel page/index.html", "lint": "pnpm run eslint && pnpm run stylelint", "lint:fix": "pnpm run eslint:fix && pnpm run stylelint:fix", - "eslint": "eslint --ext .ts,.html page tests", - "eslint:fix": "eslint --fix --ext .ts,.html page tests", + "eslint": "eslint page tests", + "eslint:fix": "eslint --fix page tests", "stylelint": "stylelint page/*.scss", "stylelint:fix": "stylelint --fix page/*.scss", "check": "tsc --noEmit", @@ -18,16 +18,15 @@ }, "license": "GPL-3.0-or-later", "devDependencies": { + "@antfu/eslint-config": "^3.6.2", "@parcel/transformer-sass": "^2.12.0", - "@playwright/test": "^1.42.1", - "@types/node": "^20.11.24", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "eslint": "^8.57.0", - "eslint-config-standard": "^17.1.0", - "eslint-plugin-html": "^8.0.0", + "@playwright/test": "^1.47.1", + "@types/node": "^22.5.5", + "eslint": "^9.10.0", + "eslint-plugin-format": "^0.1.2", "parcel": "^2.12.0", - "stylelint": "^16.2.1", - "stylelint-config-standard-scss": "^13.0.0", - "typescript": "^5.3.3" + "stylelint": "^16.9.0", + "stylelint-config-standard-scss": "^13.1.0", + "typescript": "^5.6.2" } } diff --git a/page/api.ts b/page/api.ts index adb39ca..0bcc251 100644 --- a/page/api.ts +++ b/page/api.ts @@ -1,47 +1,47 @@ import { fcitx } from './distribution' +import { setStyle } from './customize' // eslint-disable-line perfectionist/sort-imports +import { fcitxLog } from './log' import { - panel, + loadPlugins, + pluginManager, + unloadPlugins, +} from './plugin' +import { + fetchComplete, + getScrollState, + recalculateScroll, + scrollKeyAction, + setScrollEnd, + setScrollState, +} from './scroll' +import { + auxDown, + auxUp, hoverables, + panel, preedit, - auxUp, - auxDown } from './selector' import { - div, - setActions, + setAccentColor, + setTheme, +} from './theme' +import { answerActions, - hideContextmenu, + div, getHoverBehavior, getPagingButtonsStyle, + hideContextmenu, resetMouseMoveState, - resize + resize, + setActions, } from './ux' -import { - setTheme, - setAccentColor -} from './theme' -import { setStyle } from './customize' -import { fcitxLog } from './log' -import { - getScrollState, - setScrollState, - setScrollEnd, - recalculateScroll, - scrollKeyAction, - fetchComplete -} from './scroll' -import { - pluginManager, - loadPlugins, - unloadPlugins -} from './plugin' -function escapeWS (s: string) { +function escapeWS(s: string) { // XXX:   is broken in Safari return s.replaceAll(' ', ' ').replaceAll('\n', '
').replaceAll('\t', ' ') } -function divider (paging: boolean = false) { +function divider(paging: boolean = false) { const e = div('fcitx-divider') // Is this divider between candidates and paging buttons? if (paging) { @@ -54,7 +54,7 @@ function divider (paging: boolean = false) { return e } -function setLayout (layout : 0 | 1) { +function setLayout(layout: 0 | 1) { switch (layout) { case 0: hoverables.classList.remove('fcitx-vertical') @@ -66,18 +66,19 @@ function setLayout (layout : 0 | 1) { } } -function setWritingMode (mode: 0 | 1 | 2) { +function setWritingMode(mode: 0 | 1 | 2) { const classes = ['fcitx-horizontal-tb', 'fcitx-vertical-rl', 'fcitx-vertical-lr'] for (let i = 0; i < classes.length; ++i) { if (mode === i) { panel.classList.add(classes[i]) - } else { + } + else { panel.classList.remove(classes[i]) } } } -function moveHighlight (from: Element | null, to: Element | null) { +function moveHighlight(from: Element | null, to: Element | null) { from?.classList.remove('fcitx-highlighted') to?.classList.add('fcitx-highlighted') // In vertical or scroll mode, there are multiple marks, @@ -102,7 +103,7 @@ const caretRight = common.replace('{}', '0 0 192 512').replace('{}', 'M0 384.662 const arrowBack = common.replace('{}', '0 0 24 24').replace('{}', 'M16.62 2.99a1.25 1.25 0 0 0-1.77 0L6.54 11.3a.996.996 0 0 0 0 1.41l8.31 8.31c.49.49 1.28.49 1.77 0s.49-1.28 0-1.77L9.38 12l7.25-7.25c.48-.48.48-1.28-.01-1.76z') const arrowForward = common.replace('{}', '0 0 24 24').replace('{}', 'M7.38 21.01c.49.49 1.28.49 1.77 0l8.31-8.31a.996.996 0 0 0 0-1.41L9.15 2.98c-.49-.49-1.28-.49-1.77 0s-.49 1.28 0 1.77L14.62 12l-7.25 7.25c-.48.48-.48 1.28.01 1.76z') -function setCandidates (cands: Candidate[], highlighted: number, markText: string, pageable: boolean, hasPrev: boolean, hasNext: boolean, scrollState: SCROLL_STATE, scrollStart: boolean, scrollEnd: boolean) { +function setCandidates(cands: Candidate[], highlighted: number, markText: string, pageable: boolean, hasPrev: boolean, hasNext: boolean, scrollState: SCROLL_STATE, scrollStart: boolean, scrollEnd: boolean) { resetMouseMoveState() hideContextmenu() setScrollState(scrollState) @@ -110,13 +111,15 @@ function setCandidates (cands: Candidate[], highlighted: number, markText: strin if (scrollState !== 2 || scrollStart) { hoverables.innerHTML = '' hoverables.scrollTop = 0 // Otherwise last scroll position will be kept. - } else { + } + else { fetchComplete() } if (scrollState === 2) { hoverables.classList.add('fcitx-horizontal-scroll') setScrollEnd(scrollEnd) - } else { + } + else { hoverables.classList.remove('fcitx-horizontal-scroll') } for (let i = 0; i < cands.length; ++i) { @@ -138,7 +141,8 @@ function setCandidates (cands: Candidate[], highlighted: number, markText: strin const mark = div('fcitx-mark') if (markText === '') { mark.classList.add('fcitx-no-text') - } else { + } + else { mark.innerHTML = markText } candidateInner.append(mark) @@ -180,7 +184,8 @@ function setCandidates (cands: Candidate[], highlighted: number, markText: strin const paging = div('fcitx-paging', 'fcitx-scroll', 'fcitx-hoverable') paging.append(expand) hoverables.append(paging) - } else if (scrollState === 0 && pageable) { + } + else if (scrollState === 0 && pageable) { const isArrow = getPagingButtonsStyle() === 'Arrow' hoverables.append(divider(true)) @@ -203,13 +208,15 @@ function setCandidates (cands: Candidate[], highlighted: number, markText: strin const paging = div('fcitx-paging') if (isArrow) { paging.classList.add('fcitx-arrow') - } else { + } + else { paging.classList.add('fcitx-triangle') } paging.appendChild(prev) paging.appendChild(next) hoverables.appendChild(paging) - } else if (scrollState === 2) { + } + else if (scrollState === 2) { window.requestAnimationFrame(() => { recalculateScroll(scrollStart) }) @@ -226,23 +233,24 @@ function setCandidates (cands: Candidate[], highlighted: number, markText: strin } } -function updateElement (element: Element, innerHTML: string) { +function updateElement(element: Element, innerHTML: string) { if (innerHTML === '') { element.classList.add('fcitx-hidden') - } else { + } + else { element.innerHTML = innerHTML element.classList.remove('fcitx-hidden') } } -function updateInputPanel (preeditHTML: string, auxUpHTML: string, auxDownHTML: string) { +function updateInputPanel(preeditHTML: string, auxUpHTML: string, auxDownHTML: string) { hideContextmenu() updateElement(preedit, preeditHTML) updateElement(auxUp, auxUpHTML) updateElement(auxDown, auxDownHTML) } -function copyHTML () { +function copyHTML() { const html = document.documentElement.outerHTML fcitx._copyHTML(html) } @@ -256,7 +264,7 @@ hoverables.addEventListener('mouseleave', () => { } }) -hoverables.addEventListener('wheel', e => { +hoverables.addEventListener('wheel', (e) => { if (getScrollState() === 2) { return } @@ -277,15 +285,15 @@ fcitx.scrollKeyAction = scrollKeyAction fcitx.answerActions = answerActions Object.defineProperty(fcitx, 'pluginManager', { - value: pluginManager + value: pluginManager, }) Object.defineProperty(fcitx, 'loadPlugins', { - value: loadPlugins + value: loadPlugins, }) Object.defineProperty(fcitx, 'unloadPlugins', { - value: unloadPlugins + value: unloadPlugins, }) fcitx.fcitxLog = fcitxLog diff --git a/page/customize.ts b/page/customize.ts index 511e86a..4e5ace7 100644 --- a/page/customize.ts +++ b/page/customize.ts @@ -1,15 +1,17 @@ -import { +import type { HOVER_BEHAVIOR, - setHoverBehavior, PAGING_BUTTONS_STYLE, - setPagingButtonsStyle, +} from './ux' +import { + setBlink, setBlur, - setBlink + setHoverBehavior, + setPagingButtonsStyle, } from './ux' type CONFIG_BOOL = 'False' | 'True' -type LIGHT_MODE = { +interface LIGHT_MODE { OverrideDefault: CONFIG_BOOL HighlightColor: string HighlightHoverColor: string @@ -30,10 +32,10 @@ type LIGHT_MODE = { DividerColor: string } -type FONT_FAMILY = {[key: string]: string} +interface FONT_FAMILY { [key: string]: string } -type STYLE_JSON = { - LightMode: LIGHT_MODE, +interface STYLE_JSON { + LightMode: LIGHT_MODE DarkMode: LIGHT_MODE & { SameWithLightMode: CONFIG_BOOL } @@ -81,10 +83,6 @@ type STYLE_JSON = { } } -function lightToDark (light: string) { - return light.replace(PANEL_LIGHT, PANEL_DARK) -} - const PANEL = '.fcitx-basic .fcitx-panel' const PANEL_VERTICAL_CANDIDATE = `${PANEL}.fcitx-horizontal-tb .fcitx-vertical .fcitx-candidate` const PANEL_HORIZONTAL_DIVIDER = `${PANEL} .fcitx-hoverables.fcitx-vertical .fcitx-divider` @@ -138,6 +136,11 @@ const CURSOR_NO_TEXT_LIGHT = `${PANEL_LIGHT} .fcitx-cursor.fcitx-no-text` const HIGHLIGHT_MARK_LIGHT = `${PANEL_LIGHT} .fcitx-highlighted .fcitx-mark` const PANEL_DARK = `.fcitx-dark${PANEL}` + +function lightToDark(light: string) { + return light.replace(PANEL_LIGHT, PANEL_DARK) +} + const PANEL_DARK_HIGHLIGHT = lightToDark(PANEL_LIGHT_HIGHLIGHT) const PANEL_DARK_HIGHLIGHT_HOVER = lightToDark(PANEL_LIGHT_HIGHLIGHT_HOVER) const PANEL_DARK_HIGHLIGHT_PRESS = lightToDark(PANEL_LIGHT_HIGHLIGHT_PRESS) @@ -163,24 +166,24 @@ const PANEL_DARK_SCROLL_TRACK = lightToDark(PANEL_LIGHT_SCROLL_TRACK) const CURSOR_NO_TEXT_DARK = lightToDark(CURSOR_NO_TEXT_LIGHT) const HIGHLIGHT_MARK_DARK = lightToDark(HIGHLIGHT_MARK_LIGHT) -function px (n: string | number) { +function px(n: string | number) { return `${n}px` } -function setFontFamily (o: {[key: string]: string}, f: FONT_FAMILY) { +function setFontFamily(o: { [key: string]: string }, f: FONT_FAMILY) { const fontFamily = Object.values(f).filter(s => s.trim().length > 0).map(s => JSON.stringify(s.trim())) if (fontFamily.length > 0) { o['font-family'] = fontFamily.join(', ') } } -function noCache (url: string): string { - return url + '?r=' + Math.random() +function noCache(url: string): string { + return `${url}?r=${Math.random()}` } -export function setStyle (style: string) { +export function setStyle(style: string) { const j = JSON.parse(style) as STYLE_JSON - const rules: {[key: string]: {[key: string]: string}} = {} + const rules: { [key: string]: { [key: string]: string } } = {} const hasBackgroundImage = j.Background.ImageUrl.trim() !== '' const markKey = j.Highlight.MarkStyle === 'Text' ? 'color' : 'background-color' rules[PANEL] = {} @@ -200,78 +203,78 @@ export function setStyle (style: string) { const lightBackgroundColor = hasBackgroundImage ? 'inherit' : j.LightMode.PanelColor rules[PANEL_LIGHT_HIGHLIGHT] = { - 'background-color': j.LightMode.HighlightColor + 'background-color': j.LightMode.HighlightColor, } rules[PANEL_LIGHT_HIGHLIGHT_HOVER] = { - 'background-color': j.LightMode.HighlightHoverColor + 'background-color': j.LightMode.HighlightHoverColor, } rules[PANEL_LIGHT_HIGHLIGHT_PRESS] = { - 'background-color': j.LightMode.HighlightColor + 'background-color': j.LightMode.HighlightColor, } rules[TEXT_LIGHT_HIGHLIGHT] = { - color: j.LightMode.HighlightTextColor + color: j.LightMode.HighlightTextColor, } rules[TEXT_LIGHT_PRESS] = { - color: j.LightMode.HighlightTextPressColor + color: j.LightMode.HighlightTextPressColor, } rules[LABEL_LIGHT_HIGHLIGHT] = { - color: j.LightMode.HighlightLabelColor + color: j.LightMode.HighlightLabelColor, } rules[COMMENT_LIGHT_HIGHLIGHT] = { - color: j.LightMode.HighlightCommentColor + color: j.LightMode.HighlightCommentColor, } rules[HEADER_LIGHT_BACKGROUND] = { - 'background-color': j.LightMode.PanelColor + 'background-color': j.LightMode.PanelColor, } rules[HOVERABLES_LIGHT_BACKGROUND] = { // With background image, discard panel color for unselected candidates - 'background-color': lightBackgroundColor + 'background-color': lightBackgroundColor, } rules[TEXT_LIGHT] = { - color: j.LightMode.TextColor + color: j.LightMode.TextColor, } rules[LABEL_LIGHT] = { - color: j.LightMode.LabelColor + color: j.LightMode.LabelColor, } rules[COMMENT_LIGHT] = { - color: j.LightMode.CommentColor + color: j.LightMode.CommentColor, } rules[PAGING_BUTTON_LIGHT] = { - color: j.LightMode.PagingButtonColor + color: j.LightMode.PagingButtonColor, } rules[PAGING_BUTTON_DISABLED_LIGHT] = { - color: j.LightMode.DisabledPagingButtonColor + color: j.LightMode.DisabledPagingButtonColor, } rules[PREEDIT_LIGHT] = { - color: j.LightMode.PreeditColor + color: j.LightMode.PreeditColor, } rules[CURSOR_NO_TEXT_LIGHT] = { - 'background-color': j.LightMode.PreeditColor + 'background-color': j.LightMode.PreeditColor, } rules[PREEDIT_PRE_CURSOR_LIGHT] = { - color: j.LightMode.PreeditColorPreCursor + color: j.LightMode.PreeditColorPreCursor, } rules[PANEL_LIGHT] = { - 'border-color': j.LightMode.BorderColor + 'border-color': j.LightMode.BorderColor, } rules[PANEL_LIGHT_DIVIDER_MIDDLE] = { - 'background-color': j.LightMode.DividerColor + 'background-color': j.LightMode.DividerColor, } rules[PANEL_LIGHT_DIVIDER_SIDE] = { - 'background-color': lightBackgroundColor + 'background-color': lightBackgroundColor, } rules[PANEL_LIGHT_SCROLL_DIVIDER] = rules[PANEL_LIGHT_SCROLL_TRACK] = { - 'background-color': lightBackgroundColor + 'background-color': lightBackgroundColor, } rules[HIGHLIGHT_MARK_LIGHT] = { - [markKey]: j.LightMode.HighlightMarkColor + [markKey]: j.LightMode.HighlightMarkColor, } if (j.Highlight.HoverBehavior === 'Add') { rules[PANEL_LIGHT_OTHER_HOVER] = { - 'background-color': j.LightMode.HighlightColor + 'background-color': j.LightMode.HighlightColor, } rules[PANEL_LIGHT_OTHER_PRESS] = { - 'background-color': j.LightMode.HighlightHoverColor + 'background-color': j.LightMode.HighlightHoverColor, } } } @@ -301,7 +304,7 @@ export function setStyle (style: string) { PANEL_LIGHT_DIVIDER_SIDE, PANEL_LIGHT_SCROLL_DIVIDER, PANEL_LIGHT_SCROLL_TRACK, - HIGHLIGHT_MARK_LIGHT + HIGHLIGHT_MARK_LIGHT, ] if (j.Highlight.HoverBehavior === 'Add') { // This is the behavior of MSPY @@ -310,81 +313,82 @@ export function setStyle (style: string) { for (const key of keys) { rules[lightToDark(key)] = rules[key] } - } else { + } + else { const darkBackgroundColor = hasBackgroundImage ? 'inherit' : j.DarkMode.PanelColor rules[PANEL_DARK_HIGHLIGHT] = { - 'background-color': j.DarkMode.HighlightColor + 'background-color': j.DarkMode.HighlightColor, } rules[PANEL_DARK_HIGHLIGHT_HOVER] = { - 'background-color': j.DarkMode.HighlightHoverColor + 'background-color': j.DarkMode.HighlightHoverColor, } rules[PANEL_DARK_HIGHLIGHT_PRESS] = { - 'background-color': j.DarkMode.HighlightColor + 'background-color': j.DarkMode.HighlightColor, } rules[TEXT_DARK_HIGHLIGHT] = { - color: j.DarkMode.HighlightTextColor + color: j.DarkMode.HighlightTextColor, } rules[TEXT_DARK_PRESS] = { - color: j.DarkMode.HighlightTextPressColor + color: j.DarkMode.HighlightTextPressColor, } rules[LABEL_DARK_HIGHLIGHT] = { - color: j.DarkMode.HighlightLabelColor + color: j.DarkMode.HighlightLabelColor, } rules[COMMENT_DARK_HIGHLIGHT] = { - color: j.DarkMode.HighlightCommentColor + color: j.DarkMode.HighlightCommentColor, } rules[HEADER_DARK_BACKGROUND] = { - 'background-color': j.DarkMode.PanelColor + 'background-color': j.DarkMode.PanelColor, } rules[HOVERABLES_DARK_BACKGROUND] = { - 'background-color': darkBackgroundColor + 'background-color': darkBackgroundColor, } rules[TEXT_DARK] = { - color: j.DarkMode.TextColor + color: j.DarkMode.TextColor, } rules[LABEL_DARK] = { - color: j.DarkMode.LabelColor + color: j.DarkMode.LabelColor, } rules[COMMENT_DARK] = { - color: j.DarkMode.CommentColor + color: j.DarkMode.CommentColor, } rules[PAGING_BUTTON_DARK] = { - color: j.DarkMode.PagingButtonColor + color: j.DarkMode.PagingButtonColor, } rules[PAGING_BUTTON_DISABLED_DARK] = { - color: j.DarkMode.DisabledPagingButtonColor + color: j.DarkMode.DisabledPagingButtonColor, } rules[PREEDIT_DARK] = { - color: j.DarkMode.PreeditColor + color: j.DarkMode.PreeditColor, } rules[CURSOR_NO_TEXT_DARK] = { - 'background-color': j.DarkMode.PreeditColor + 'background-color': j.DarkMode.PreeditColor, } rules[PREEDIT_PRE_CURSOR_DARK] = { - color: j.DarkMode.PreeditColorPreCursor + color: j.DarkMode.PreeditColorPreCursor, } rules[PANEL_DARK] = { - 'border-color': j.DarkMode.BorderColor + 'border-color': j.DarkMode.BorderColor, } rules[PANEL_DARK_DIVIDER_MIDDLE] = { - 'background-color': j.DarkMode.DividerColor + 'background-color': j.DarkMode.DividerColor, } rules[PANEL_DARK_DIVIDER_SIDE] = { - 'background-color': darkBackgroundColor + 'background-color': darkBackgroundColor, } rules[PANEL_DARK_SCROLL_DIVIDER] = rules[PANEL_DARK_SCROLL_TRACK] = { - 'background-color': darkBackgroundColor + 'background-color': darkBackgroundColor, } rules[HIGHLIGHT_MARK_DARK] = { - [markKey]: j.DarkMode.HighlightMarkColor + [markKey]: j.DarkMode.HighlightMarkColor, } if (j.Highlight.HoverBehavior === 'Add') { rules[PANEL_DARK_OTHER_HOVER] = { - 'background-color': j.DarkMode.HighlightColor + 'background-color': j.DarkMode.HighlightColor, } rules[PANEL_DARK_OTHER_PRESS] = { - 'background-color': j.DarkMode.HighlightHoverColor + 'background-color': j.DarkMode.HighlightHoverColor, } } } @@ -405,7 +409,8 @@ export function setStyle (style: string) { if (j.Background.Blur === 'True') { setBlur(true) rules['.fcitx-blur'] = { '-webkit-backdrop-filter': `blur(${px(j.Background.BlurRadius)})` } - } else { + } + else { setBlur(false) document.querySelector('fcitx-.panel-blur-outer')?.classList.remove('fcitx-blur') document.querySelector('.fcitx-panel-blur-outer')?.classList.remove('fcitx-blur') @@ -443,25 +448,25 @@ export function setStyle (style: string) { if (j.Size.HorizontalDividerWidth === '0') { rules[VERTICAL_CANDIDATE_INNER] = { 'margin-block-start': halfMargin, - 'margin-block-end': halfMargin + 'margin-block-end': halfMargin, } rules[VERTICAL_FIRST_CANDIDATE_INNER] = { - 'margin-block-start': px(j.Size.Margin) + 'margin-block-start': px(j.Size.Margin), } rules[VERTICAL_LAST_CANDIDATE_INNER] = { - 'margin-block-end': px(j.Size.Margin) + 'margin-block-end': px(j.Size.Margin), } } // Unconditional since there is no vertical divider between candidates. rules[HORIZONTAL_CANDIDATE_INNER] = { 'margin-inline-start': halfMargin, - 'margin-inline-end': halfMargin + 'margin-inline-end': halfMargin, } rules[HORIZONTAL_FIRST_CANDIDATE_INNER] = { - 'margin-inline-start': px(j.Size.Margin) + 'margin-inline-start': px(j.Size.Margin), } rules[HORIZONTAL_LAST_CANDIDATE_INNER] = { - 'margin-inline-end': px(j.Size.Margin) + 'margin-inline-end': px(j.Size.Margin), } rules[PAGING_OUTER].margin = px(j.Size.Margin) @@ -472,23 +477,23 @@ export function setStyle (style: string) { rules[CANDIDATE_INNER]['padding-inline-start'] = px(j.Size.LeftPadding) rules[CANDIDATE_INNER].gap = px(j.Size.LabelTextGap) rules[PANEL_VERTICAL_CANDIDATE] = { - 'min-inline-size': px(j.Size.VerticalMinWidth) + 'min-inline-size': px(j.Size.VerticalMinWidth), } rules[PANEL_HORIZONTAL_DIVIDER] = { - 'block-size': px(j.Size.HorizontalDividerWidth) + 'block-size': px(j.Size.HorizontalDividerWidth), } rules[PANEL_HORIZONTAL_DIVIDER_SIDE] = { - 'inline-size': px(j.Size.Margin) + 'inline-size': px(j.Size.Margin), } rules[PANEL_VERTICAL_DIVIDER_SIDE] = { - 'block-size': px(j.Size.Margin) + 'block-size': px(j.Size.Margin), } const basic = document.head.querySelector('#fcitx-basic') if (basic) { basic.innerHTML = Object.entries(rules).map(([selector, block]) => - `${selector} {` + Object.entries(block).map(([key, value]) => - `${key}: ${value};`).join('\n') + '}').join('\n') + `${selector} {${Object.entries(block).map(([key, value]) => + `${key}: ${value};`).join('\n')}}`).join('\n') } document.head.querySelector('#fcitx-user')?.setAttribute('href', noCache(j.Advanced.UserCss)) diff --git a/page/distribution.ts b/page/distribution.ts index 212328b..41dd130 100644 --- a/page/distribution.ts +++ b/page/distribution.ts @@ -1,12 +1,13 @@ // Must be imported first -const distribution = process.env.FCITX_DISTRIBUTION ?? '' +const distribution = process.env.FCITX_DISTRIBUTION ?? '' // eslint-disable-line node/prefer-global/process -let fcitx: FCITX +let fcitx: FCITX // eslint-disable-line import/no-mutable-exports if (distribution === 'fcitx5-js') { fcitx = window.fcitx -} else { +} +else { // @ts-expect-error f5m binds C++ function to JS global function, but we want to call fcitx._select for both f5m and f5j. fcitx = window window.fcitx = fcitx @@ -19,8 +20,8 @@ if (distribution === 'fcitx5-js') { width, height: big enough, disregard window size */ const style = document.createElement('style') - style.innerHTML = -`body { + style.innerHTML += `body { background: rgb(0 0 0 / 0%); margin: 0; overflow: hidden; @@ -33,5 +34,5 @@ if (distribution === 'fcitx5-js') { fcitx.distribution = distribution export { - fcitx + fcitx, } diff --git a/page/global.d.ts b/page/global.d.ts index 2b9e6a5..5ca23b5 100644 --- a/page/global.d.ts +++ b/page/global.d.ts @@ -1,10 +1,10 @@ declare global { - type CandidateAction = { + interface CandidateAction { id: number text: string } - type Candidate = { + interface Candidate { text: string label: string comment: string @@ -16,12 +16,12 @@ declare global { type SCROLL_MOVE_HIGHLIGHT = 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 type SCROLL_KEY_ACTION = SCROLL_SELECT | SCROLL_MOVE_HIGHLIGHT | 20 - type FcitxPlugin = { + interface FcitxPlugin { load: () => void unload: () => void } - type FCITX = { + interface FCITX { distribution: string // C++ APIs that api.ts calls diff --git a/page/index.html b/page/index.html index e5c3211..04e317b 100644 --- a/page/index.html +++ b/page/index.html @@ -1,18 +1,18 @@ - + - + - +
@@ -30,8 +30,7 @@
-
-
+
diff --git a/page/log.ts b/page/log.ts index 043e7fb..e34e579 100644 --- a/page/log.ts +++ b/page/log.ts @@ -1,4 +1,4 @@ -export function fcitxLog (...args: unknown[]) { +export function fcitxLog(...args: unknown[]) { for (let i = 0; i < args.length; ++i) { if (i > 0) { window.fcitx._log(' ') @@ -8,7 +8,8 @@ export function fcitxLog (...args: unknown[]) { if (typeof arg === 'object') { try { serialized = JSON.stringify(arg) - } catch {} + } + catch {} } window.fcitx._log(serialized || String(arg)) } diff --git a/page/plugin.ts b/page/plugin.ts index 0d2b21a..1e22e6a 100644 --- a/page/plugin.ts +++ b/page/plugin.ts @@ -11,10 +11,10 @@ Object.defineProperty(pluginManager, 'register', { } unloaders.push(plugin.unload) plugin.load() - } + }, }) -function loadPlugins (names: string[]) { +function loadPlugins(names: string[]) { for (const name of names) { window.fcitx.fcitxLog(`Loading plugin ${name}`) const script = document.createElement('script') @@ -24,11 +24,12 @@ function loadPlugins (names: string[]) { } } -function unloadPlugins () { +function unloadPlugins() { for (const unloader of unloaders.reverse()) { try { unloader() - } catch (e) { + } + catch (e) { window.fcitx.fcitxLog(`Error unloading plugin: ${e}`) } } @@ -37,7 +38,7 @@ function unloadPlugins () { } export { - pluginManager, loadPlugins, - unloadPlugins + pluginManager, + unloadPlugins, } diff --git a/page/scroll.ts b/page/scroll.ts index 6322a0c..1eaa1ab 100644 --- a/page/scroll.ts +++ b/page/scroll.ts @@ -1,8 +1,8 @@ import { - hoverables + hoverables, } from './selector' import { - hideContextmenu + hideContextmenu, } from './ux' const MAX_ROW = 6 @@ -10,43 +10,43 @@ const MAX_COLUMN = 6 let scrollState: SCROLL_STATE = 0 -export function getScrollState () { +export function getScrollState() { return scrollState } -export function setScrollState (state: SCROLL_STATE) { +export function setScrollState(state: SCROLL_STATE) { scrollState = state } let scrollEnd = false -export function setScrollEnd (end: boolean) { +export function setScrollEnd(end: boolean) { scrollEnd = end } // A lock that prevents fetching same candidates simultaneously. let fetching = false -export function fetchComplete () { +export function fetchComplete() { fetching = false } -export function expand () { +export function expand() { window.fcitx._scroll(0, (MAX_ROW + 1) * MAX_COLUMN) // visible rows plus 1 hidden row } -function collapse () { +function collapse() { window.fcitx._scroll(-1, 0) } let rowItemCount: number[] = [] let highlighted = 0 -function itemCountInFirstNRows (n: number): number { +function itemCountInFirstNRows(n: number): number { return rowItemCount.slice(0, n).reduce((sum, count) => sum + count, 0) } -function getRowOf (index: number): number { +function getRowOf(index: number): number { let skipped = 0 for (let i = 0; i < rowItemCount.length - 1; ++i) { const end = skipped + rowItemCount[i] @@ -58,15 +58,15 @@ function getRowOf (index: number): number { return rowItemCount.length - 1 } -function getHighlightedRow (): number { +function getHighlightedRow(): number { return getRowOf(highlighted) } -function distanceToTop (element: Element, basis: 'top' | 'bottom') { +function distanceToTop(element: Element, basis: 'top' | 'bottom') { return element.getBoundingClientRect()[basis] - hoverables.getBoundingClientRect().top } -function scrollForHighlight () { +function scrollForHighlight() { const candidates = hoverables.querySelectorAll('.fcitx-candidate') const bottomOffset = distanceToTop(candidates[highlighted], 'bottom') - hoverables.clientHeight @@ -82,7 +82,7 @@ function scrollForHighlight () { } } -function renderHighlightAndLabels (newHighlighted: number, clearOld: boolean) { +function renderHighlightAndLabels(newHighlighted: number, clearOld: boolean) { const candidates = hoverables.querySelectorAll('.fcitx-candidate') if (clearOld) { const highlightedRow = getHighlightedRow() @@ -107,7 +107,7 @@ function renderHighlightAndLabels (newHighlighted: number, clearOld: boolean) { candidates[highlighted].classList.add('fcitx-highlighted', 'fcitx-highlighted-original') } -export function recalculateScroll (scrollStart: boolean) { +export function recalculateScroll(scrollStart: boolean) { const candidates = hoverables.querySelectorAll('.fcitx-candidate') let currentY = candidates[0].getBoundingClientRect().y rowItemCount = [] @@ -117,7 +117,8 @@ export function recalculateScroll (scrollStart: boolean) { const { y } = candidate.getBoundingClientRect() if (y === currentY) { ++itemCount - } else { + } + else { rowItemCount.push(itemCount) itemCount = 1 currentY = y @@ -137,13 +138,13 @@ export function recalculateScroll (scrollStart: boolean) { } } -function getNeighborCandidate (index: number, direction: SCROLL_MOVE_HIGHLIGHT): number { +function getNeighborCandidate(index: number, direction: SCROLL_MOVE_HIGHLIGHT): number { const row = getRowOf(index) const candidates = hoverables.querySelectorAll('.fcitx-candidate') const { left, right } = candidates[index].getBoundingClientRect() const mid = (left + right) / 2 - function helper (row: number) { + function helper(row: number) { if (row < 0 || row === rowItemCount.length) { return -1 } @@ -196,7 +197,7 @@ function getNeighborCandidate (index: number, direction: SCROLL_MOVE_HIGHLIGHT): } } -export function scrollKeyAction (action: SCROLL_KEY_ACTION) { +export function scrollKeyAction(action: SCROLL_KEY_ACTION) { hideContextmenu() if (action >= 1 && action <= 6) { const highlightedRow = getHighlightedRow() @@ -227,7 +228,8 @@ export function scrollKeyAction (action: SCROLL_KEY_ACTION) { window.fcitx._scroll(itemCountInFirstNRows(rowItemCount.length), MAX_ROW * MAX_COLUMN) } } - } else if ([10, 16].includes(action) && getHighlightedRow() === 0) { + } + else if ([10, 16].includes(action) && getHighlightedRow() === 0) { collapse() } break diff --git a/page/theme.ts b/page/theme.ts index 06bdfae..666af15 100644 --- a/page/theme.ts +++ b/page/theme.ts @@ -1,37 +1,38 @@ import { - theme + theme, } from './selector' const darkMQL = window.matchMedia('(prefers-color-scheme: dark)') let isSystemDark = darkMQL.matches let followSystemTheme = true -function setLightTheme () { +function setLightTheme() { theme.classList.remove('fcitx-dark') theme.classList.add('fcitx-light') } -function setDarkTheme () { +function setDarkTheme() { theme.classList.remove('fcitx-light') theme.classList.add('fcitx-dark') } -function systemThemeHandler () { +function systemThemeHandler() { if (isSystemDark) { setDarkTheme() - } else { + } + else { setLightTheme() } } -darkMQL.addEventListener('change', event => { +darkMQL.addEventListener('change', (event) => { isSystemDark = event.matches if (followSystemTheme) { systemThemeHandler() } }) -export function setTheme (theme: 0 | 1 | 2) { +export function setTheme(theme: 0 | 1 | 2) { switch (theme) { case 0: followSystemTheme = true @@ -48,7 +49,6 @@ export function setTheme (theme: 0 | 1 | 2) { } } -/* eslint-disable quote-props */ const accentColorMap = { 'null': 'blue', '-1': 'graphite', @@ -58,19 +58,20 @@ const accentColorMap = { '3': 'green', '4': 'blue', '5': 'purple', - '6': 'pink' + '6': 'pink', } -/* eslint-enable quote-props */ + type ACCENT_COLOR = keyof typeof accentColorMap let accentColor: ACCENT_COLOR = 'null' -export function setAccentColor (color: number | null) { +export function setAccentColor(color: number | null) { theme.classList.remove(`fcitx-${accentColorMap[accentColor]}`) const key = String(color) if (key in accentColorMap) { accentColor = key as ACCENT_COLOR - } else { + } + else { accentColor = '4' } theme.classList.add(`fcitx-${accentColorMap[accentColor]}`) diff --git a/page/ux.ts b/page/ux.ts index f9f3c13..736bf55 100644 --- a/page/ux.ts +++ b/page/ux.ts @@ -1,14 +1,14 @@ import { - theme, - panel, - decoration, - contextmenu, - hoverables -} from './selector' -import { + expand, getScrollState, - expand } from './scroll' +import { + contextmenu, + decoration, + hoverables, + panel, + theme, +} from './selector' const DRAG_THRESHOLD = 10 @@ -23,27 +23,27 @@ let dragOffset = 0 // 0: reset, 1: initial (when window is shown even if no mouse move there will be a mousemove event), 2+: moved let mouseMoveState = 0 -export function resetMouseMoveState () { +export function resetMouseMoveState() { mouseMoveState = 0 hoverables.classList.remove('fcitx-mousemoved') } -type ShadowBox = { - anchorTop: number, - anchorRight: number, - anchorLeft: number, - right: number, +interface ShadowBox { + anchorTop: number + anchorRight: number + anchorLeft: number + right: number bottom: number } -export function resize (dx: number, dy: number, dragging: boolean, hasContextmenu: boolean) { - function adaptWindowSize (reserveSpaceForContextmenu: boolean) { +export function resize(dx: number, dy: number, dragging: boolean, hasContextmenu: boolean) { + function adaptWindowSize(reserveSpaceForContextmenu: boolean) { let { anchorTop, anchorRight, anchorLeft, right, - bottom + bottom, } = getBoundingRectWithShadow(panel) // Account for window decorations. @@ -66,10 +66,11 @@ export function resize (dx: number, dy: number, dragging: boolean, hasContextmen if (reserveSpaceForContextmenu) { right += 100 bottom += 100 - } else if (contextmenu.style.display === 'block') { + } + else if (contextmenu.style.display === 'block') { const { right: r, - bottom: b + bottom: b, } = getBoundingRectWithShadow(contextmenu) right = Math.max(right, r) bottom = Math.max(bottom, b) @@ -89,12 +90,12 @@ export function resize (dx: number, dy: number, dragging: boolean, hasContextmen } } -function getBoundingRectWithShadow (element: Element): ShadowBox { +function getBoundingRectWithShadow(element: Element): ShadowBox { const rect = element.getBoundingClientRect() let xHi = rect.right let yHi = rect.bottom - const vals = window.getComputedStyle(element).boxShadow.split(' ').map(parseFloat) + const vals = window.getComputedStyle(element).boxShadow.split(' ').map(Number.parseFloat) // The format of computed style is 'rgb(255, 0, 0) 10px 5px 5px 0px, rgb(255, 0, 0) 10px 5px 5px 0px' // Therefore, vals has exactly (7*n) elements, and vals[7*i] will be NaN. for (let i = 0; i < vals.length / 7; i += 1) { @@ -106,8 +107,10 @@ function getBoundingRectWithShadow (element: Element): ShadowBox { const deltaY = offsetY + blurRadius + spreadRadius const shadowXHi = rect.right + (deltaX > 0 ? deltaX : 0) const shadowYHi = rect.bottom + (deltaY > 0 ? deltaY : 0) - if (shadowXHi > xHi) xHi = shadowXHi - if (shadowYHi > yHi) yHi = shadowYHi + if (shadowXHi > xHi) + xHi = shadowXHi + if (shadowYHi > yHi) + yHi = shadowYHi } // Extend the rect to contain the shadow. return { @@ -115,21 +118,21 @@ function getBoundingRectWithShadow (element: Element): ShadowBox { anchorRight: rect.right, anchorLeft: rect.left, right: xHi, - bottom: yHi + bottom: yHi, } } -export function div (...classList: string[]) { +export function div(...classList: string[]) { const element = document.createElement('div') element.classList.add(...classList) return element } -function isInsideHoverables (target: Element) { +function isInsideHoverables(target: Element) { return target !== hoverables && hoverables.contains(target) } -function getCandidateIndex (target: Element) { +function getCandidateIndex(target: Element) { const allCandidates = hoverables.querySelectorAll('.fcitx-candidate') for (let i = 0; i < allCandidates.length; ++i) { if (allCandidates[i] === target) { @@ -139,7 +142,7 @@ function getCandidateIndex (target: Element) { return -1 } -export function showContextmenu (x: number, y: number, index: number, actions: CandidateAction[]) { +export function showContextmenu(x: number, y: number, index: number, actions: CandidateAction[]) { contextmenu.innerHTML = '' for (const action of actions) { const item = div('fcitx-menu-item') @@ -156,14 +159,14 @@ export function showContextmenu (x: number, y: number, index: number, actions: C resize(0, 0, false, true) } -export function hideContextmenu () { +export function hideContextmenu() { contextmenu.innerHTML = '' contextmenu.style.display = 'none' } const receiver = (window.fcitx.distribution === 'fcitx5-js' ? decoration : document) as HTMLElement -receiver.addEventListener('mousedown', e => { +receiver.addEventListener('mousedown', (e) => { if (e.button !== 0) { return } @@ -175,7 +178,7 @@ receiver.addEventListener('mousedown', e => { dragOffset = 0 }) -receiver.addEventListener('mousemove', e => { +receiver.addEventListener('mousemove', (e) => { if (++mouseMoveState >= 2) { hoverables.classList.add('fcitx-mousemoved') } @@ -198,7 +201,7 @@ receiver.addEventListener('mousemove', e => { resize(dx, dy, true, false) }) -receiver.addEventListener('mouseup', e => { +receiver.addEventListener('mouseup', (e) => { if (e.button !== 0) { return } @@ -216,9 +219,11 @@ receiver.addEventListener('mouseup', e => { while (target.parentElement !== hoverables) { if (target.classList.contains('fcitx-prev')) { return window.fcitx._page(false) - } else if (target.classList.contains('fcitx-next')) { + } + else if (target.classList.contains('fcitx-next')) { return window.fcitx._page(true) - } else if (target.classList.contains('fcitx-expand')) { + } + else if (target.classList.contains('fcitx-expand')) { return expand() } target = target.parentElement! @@ -230,7 +235,7 @@ receiver.addEventListener('mouseup', e => { }) let actions: CandidateAction[][] = [] -export function setActions (newActions: CandidateAction[][]) { +export function setActions(newActions: CandidateAction[][]) { actions = newActions } @@ -238,11 +243,11 @@ let actionX = 0 let actionY = 0 let actionIndex = 0 -export function answerActions (actions: CandidateAction[]) { +export function answerActions(actions: CandidateAction[]) { showContextmenu(actionX, actionY, actionIndex, actions) } -receiver.addEventListener('contextmenu', e => { +receiver.addEventListener('contextmenu', (e) => { e.preventDefault() let target = e.target as Element if (!isInsideHoverables(target)) { @@ -260,13 +265,14 @@ receiver.addEventListener('contextmenu', e => { } if (i >= 0 && actions[i].length > 0) { showContextmenu(e.clientX, e.clientY, i, actions[i]) - } else { + } + else { hideContextmenu() } }) let blurEnabled = true -export function setBlur (enabled: boolean) { +export function setBlur(enabled: boolean) { blurEnabled = enabled } @@ -274,14 +280,15 @@ export function setBlur (enabled: boolean) { let blurSwitch = false const panelBlurOuter = document.querySelector('.fcitx-panel-blur-outer')! const panelBlurInner = document.querySelector('.fcitx-panel-blur-inner')! -function redrawBlur () { +function redrawBlur() { if (!blurEnabled || !theme.classList.contains('fcitx-macos')) { return } if (blurSwitch) { panelBlurOuter.classList.add('fcitx-blur') panelBlurInner.classList.remove('fcitx-blur') - } else { + } + else { panelBlurInner.classList.add('fcitx-blur') panelBlurOuter.classList.remove('fcitx-blur') } @@ -290,11 +297,12 @@ function redrawBlur () { if (window.location.href.startsWith('http')) { // fcitx5-js redrawBlur() -} else { // fcitx5-macos +} +else { // fcitx5-macos setInterval(redrawBlur, 40) } -export function showCursor (show: boolean) { +export function showCursor(show: boolean) { const cursor = document.querySelector('.fcitx-cursor') if (cursor) { (cursor).style.opacity = show ? '1' : '0' @@ -302,7 +310,7 @@ export function showCursor (show: boolean) { } let blinkEnabled = true -export function setBlink (enabled: boolean) { +export function setBlink(enabled: boolean) { blinkEnabled = enabled if (!enabled) { showCursor(true) @@ -320,18 +328,18 @@ setInterval(() => { export type HOVER_BEHAVIOR = 'None' | 'Move' | 'Add' let hoverBehavior: HOVER_BEHAVIOR = 'None' -export function setHoverBehavior (behavior: HOVER_BEHAVIOR) { +export function setHoverBehavior(behavior: HOVER_BEHAVIOR) { hoverBehavior = behavior } -export function getHoverBehavior () { +export function getHoverBehavior() { return hoverBehavior } export type PAGING_BUTTONS_STYLE = 'None' | 'Arrow' | 'Triangle' let pagingButtonsStyle: PAGING_BUTTONS_STYLE = 'Arrow' -export function setPagingButtonsStyle (style: PAGING_BUTTONS_STYLE) { +export function setPagingButtonsStyle(style: PAGING_BUTTONS_STYLE) { pagingButtonsStyle = style } -export function getPagingButtonsStyle () { +export function getPagingButtonsStyle() { return pagingButtonsStyle } diff --git a/tests/test-generic.spec.ts b/tests/test-generic.spec.ts index 014bfe9..49ae72e 100644 --- a/tests/test-generic.spec.ts +++ b/tests/test-generic.spec.ts @@ -1,16 +1,16 @@ import { + expect, test, - expect } from '@playwright/test' import { - setCandidates, - setLayout, - theme, - panel, candidate, getBox, getCppCalls, - init + init, + panel, + setCandidates, + setLayout, + theme, } from './util' test('HTML structure', async ({ page }) => { @@ -23,10 +23,10 @@ test('HTML structure', async ({ page }) => { }) await setCandidates(page, [ { text: '页面结构', label: '1', comment: 'c', actions: [] }, - { text: '测试', label: '2', comment: '', actions: [] }], 0) + { text: '测试', label: '2', comment: '', actions: [] }, + ], 0) - const actual = (await theme(page).evaluate(el => el.outerHTML)).replaceAll(/>\s+<') - .replaceAll(/ class="([^"]+)"/g, (_, classes) => ` class="${classes.split(' ').sort().join(' ')}"`) + const actual = (await theme(page).evaluate(el => el.outerHTML)).replaceAll(/>\s+<').replaceAll(/ class="([^"]+)"/g, (_, classes) => ` class="${classes.split(' ').sort().join(' ')}"`) const expected = `
@@ -83,7 +83,8 @@ test('Select candidate', async ({ page }) => { await init(page) await setCandidates(page, [ { text: '点击', label: '1', comment: '', actions: [] }, - { text: '候选词', label: '2', comment: '', actions: [] }], 0) + { text: '候选词', label: '2', comment: '', actions: [] }, + ], 0) await candidate(page, 1).click() const cppCalls = await getCppCalls(page) @@ -93,7 +94,8 @@ test('Select candidate', async ({ page }) => { test('Candidate action', async ({ page }) => { await init(page) await setCandidates(page, [ - { text: '可遗忘', label: '1', comment: '', actions: [{ id: 1, text: '忘记' }] }], 0) + { text: '可遗忘', label: '1', comment: '', actions: [{ id: 1, text: '忘记' }] }, + ], 0) await candidate(page, 0).click({ button: 'right' }) await page.getByText('忘记').click() @@ -105,7 +107,8 @@ test('Drag should not select candidate', async ({ page }) => { await init(page) await setCandidates(page, [ { text: '拖动', label: '1', comment: '', actions: [] }, - { text: '不选词', label: '2', comment: '', actions: [] }], 0) + { text: '不选词', label: '2', comment: '', actions: [] }, + ], 0) const box = await getBox(candidate(page, 0)) const centerX = box.x + box.width / 2 @@ -123,7 +126,8 @@ test('But micro drag is tolerated', async ({ page }) => { await init(page) await setCandidates(page, [ { text: '微动', label: '1', comment: '', actions: [] }, - { text: '选词', label: '2', comment: '', actions: [] }], 0) + { text: '选词', label: '2', comment: '', actions: [] }, + ], 0) const box = await getBox(candidate(page, 0)) const centerX = box.x + box.width / 2 @@ -144,12 +148,14 @@ test('Set layout', async ({ page }) => { { text: '横', label: '1', comment: '', actions: [] }, { text: '竖', label: '1', comment: '', actions: [] }, { text: '分', label: '1', comment: '', actions: [] }, - { text: '明', label: '1', comment: '', actions: [] }], 0) + { text: '明', label: '1', comment: '', actions: [] }, + ], 0) await setLayout(page, 1) const verticalBox = await getBox(panel(page)) expect(verticalBox).toMatchObject({ - x: 25, y: 39 // shadow and inline-grid + x: 25, + y: 39, // shadow and inline-grid }) expect(verticalBox.width).toBeGreaterThan(197) expect(verticalBox.width).toBeLessThan(207) @@ -159,7 +165,8 @@ test('Set layout', async ({ page }) => { await setLayout(page, 0) const horizontalBox = await getBox(panel(page)) expect(horizontalBox).toMatchObject({ - x: 25, y: 39 + x: 25, + y: 39, }) expect(horizontalBox.width).toBeGreaterThan(170) expect(horizontalBox.width).toBeLessThan(186) diff --git a/tests/test-theme.spec.ts b/tests/test-theme.spec.ts index cc16f49..9b3982b 100644 --- a/tests/test-theme.spec.ts +++ b/tests/test-theme.spec.ts @@ -1,10 +1,10 @@ import { + expect, test, - expect } from '@playwright/test' import { + init, theme, - init } from './util' test('Set accent color', async ({ page }) => { @@ -19,7 +19,7 @@ test('Set accent color', async ({ page }) => { [3, 'fcitx-green'], [4, 'fcitx-blue'], [5, 'fcitx-purple'], - [6, 'fcitx-pink'] + [6, 'fcitx-pink'], ] as [number | null, string][] for (const [value, color] of cases) { diff --git a/tests/util.ts b/tests/util.ts index 229618a..a10a3c8 100644 --- a/tests/util.ts +++ b/tests/util.ts @@ -1,60 +1,60 @@ -import { +import type { + Locator, Page, - Locator } from '@playwright/test' -import { dirname, join } from 'path' +import { dirname, join } from 'node:path' -export async function init (page: Page) { - const url = 'file://' + join(dirname(import.meta.url), '..', 'dist', 'index.html').substring('file:'.length) +export async function init(page: Page) { + const url = `file://${join(dirname(import.meta.url), '..', 'dist', 'index.html').substring('file:'.length)}` await page.goto(url) await page.evaluate(() => { window.fcitx.setTheme(2) window.cppCalls = [] window.fcitx._resize = (dx: number, dy: number, anchorTop: number, anchorRight: number, anchorBottom: number, anchorLeft: number, fullWidth: number, fullHeight: number, dragging: boolean) => { window.cppCalls.push({ - resize: [dx, dy, anchorTop, anchorRight, anchorBottom, anchorLeft, fullWidth, fullHeight, dragging] + resize: [dx, dy, anchorTop, anchorRight, anchorBottom, anchorLeft, fullWidth, fullHeight, dragging], }) } window.fcitx._select = (index: number) => { window.cppCalls.push({ - select: index + select: index, }) } window.fcitx._action = (index: number, id: number) => { window.cppCalls.push({ - action: [index, id] + action: [index, id], }) } window.fcitx._log = () => {} }) } -export function setCandidates (page: Page, cands: Candidate[], highlighted: number) { +export function setCandidates(page: Page, cands: Candidate[], highlighted: number) { return page.evaluate(({ cands, highlighted }) => window.fcitx.setCandidates(cands, highlighted, '', false, false, false, 0, false, false), { cands, highlighted }) } -export function setLayout (page: Page, layout: 0 | 1) { +export function setLayout(page: Page, layout: 0 | 1) { return page.evaluate(({ layout }) => window.fcitx.setLayout(layout), { layout }) } -export function theme (page: Page) { +export function theme(page: Page) { return page.locator('#fcitx-theme') } -export function panel (page: Page) { +export function panel(page: Page) { return page.locator('.fcitx-panel') } -export function candidate (page: Page, index: number) { +export function candidate(page: Page, index: number) { return panel(page).locator('.fcitx-candidate').nth(index) } -export async function getBox (locator: Locator) { +export async function getBox(locator: Locator) { return (await locator.boundingBox())! } -export function getCppCalls (page: Page) { +export function getCppCalls(page: Page) { return page.evaluate(() => window.cppCalls) }