From 7b48f59f59f61c58ee98f42994804efcb8db229a Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Tue, 28 Oct 2025 14:22:36 -0700 Subject: [PATCH] Allow .tsx files to be .std.tsx --- .eslint/rules/file-suffix.js | 13 +++++--- .eslintrc.js | 1 + app/WindowsNotifications.main.ts | 3 +- ...ast.dom.tsx => renderWindowsToast.std.tsx} | 30 ++++++++++++------- ...om.tsx => renderWindowsToast_test.std.tsx} | 2 +- 5 files changed, 31 insertions(+), 18 deletions(-) rename app/{renderWindowsToast.dom.tsx => renderWindowsToast.std.tsx} (80%) rename ts/test-node/app/{renderWindowsToast_test.dom.tsx => renderWindowsToast_test.std.tsx} (99%) diff --git a/.eslint/rules/file-suffix.js b/.eslint/rules/file-suffix.js index 1d8989b249..20666b9c45 100644 --- a/.eslint/rules/file-suffix.js +++ b/.eslint/rules/file-suffix.js @@ -409,13 +409,13 @@ module.exports = { const [, moduleName] = source.match(/^([^@\/]+|@[^\/]+\/[^\/]+)/); if (NODE_PACKAGES.has(moduleName)) { nodeUses.push(node); + } else if (source === 'react-dom/server') { + // no-op } else if ( DOM_PACKAGES.has(moduleName) || source === 'react-dom/client' ) { domUses.push(node); - } else if (source === 'react-dom/server') { - // no-op } else if (!STD_PACKAGES.has(moduleName)) { context.report({ node, @@ -490,8 +490,13 @@ module.exports = { expectedSuffix = 'std'; } - // All .std.tsx components should be .dom.tsx for now - if (expectedSuffix === 'std' && filename.endsWith('.tsx')) { + // All .tsx files should normally be .dom.tsx, but could also be + // .std.tsx. + if ( + expectedSuffix === 'std' && + filename.endsWith('.tsx') && + fileSuffix !== 'std' + ) { expectedSuffix = 'dom'; } diff --git a/.eslintrc.js b/.eslintrc.js index f0bd23e454..4f67a9207a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -332,6 +332,7 @@ module.exports = { 'ts/**/*.ts', 'ts/**/*.tsx', 'app/**/*.ts', + 'app/**/*.tsx', 'build/intl-linter/**/*.ts', ], parser: '@typescript-eslint/parser', diff --git a/app/WindowsNotifications.main.ts b/app/WindowsNotifications.main.ts index 0a53382bdf..516e6abe29 100644 --- a/app/WindowsNotifications.main.ts +++ b/app/WindowsNotifications.main.ts @@ -13,8 +13,7 @@ import { createLogger } from '../ts/logging/log.std.js'; import { AUMID } from './startup_config.main.js'; import type { WindowsNotificationData } from '../ts/services/notifications.preload.js'; import OS from '../ts/util/os/osMain.node.js'; -// eslint-disable-next-line local-rules/file-suffix -import { renderWindowsToast } from './renderWindowsToast.dom.js'; +import { renderWindowsToast } from './renderWindowsToast.std.js'; export { sendDummyKeystroke }; diff --git a/app/renderWindowsToast.dom.tsx b/app/renderWindowsToast.std.tsx similarity index 80% rename from app/renderWindowsToast.dom.tsx rename to app/renderWindowsToast.std.tsx index 3dcb1cab5c..ad914897ea 100644 --- a/app/renderWindowsToast.dom.tsx +++ b/app/renderWindowsToast.std.tsx @@ -19,21 +19,29 @@ function pathToUri(path: string) { return `file:///${encodeURI(path.replace(/\\/g, '/'))}`; } -const Toast = (props: { +function Toast(props: { launch: string; // Note: though React doesn't like it, Windows seems to require that this be camelcase activationType: string; children: React.ReactNode; -}) => React.createElement('toast', props); -const Visual = (props: { children: React.ReactNode }) => - React.createElement('visual', props); -const Binding = (props: { template: string; children: React.ReactNode }) => - React.createElement('binding', props); -const Text = (props: { id: string; children: React.ReactNode }) => - React.createElement('text', props); -const Image = (props: { id: string; src: string; 'hint-crop': string }) => - React.createElement('image', props); -const Audio = (props: { src: string }) => React.createElement('audio', props); +}) { + return React.createElement('toast', props); +} +function Visual(props: { children: React.ReactNode }) { + return React.createElement('visual', props); +} +function Binding(props: { template: string; children: React.ReactNode }) { + return React.createElement('binding', props); +} +function Text(props: { id: string; children: React.ReactNode }) { + return React.createElement('text', props); +} +function Image(props: { id: string; src: string; 'hint-crop': string }) { + return React.createElement('image', props); +} +function Audio(props: { src: string }) { + return React.createElement('audio', props); +} export function renderWindowsToast({ avatarPath, diff --git a/ts/test-node/app/renderWindowsToast_test.dom.tsx b/ts/test-node/app/renderWindowsToast_test.std.tsx similarity index 99% rename from ts/test-node/app/renderWindowsToast_test.dom.tsx rename to ts/test-node/app/renderWindowsToast_test.std.tsx index f08c4b37d6..9c1b6b1681 100644 --- a/ts/test-node/app/renderWindowsToast_test.dom.tsx +++ b/ts/test-node/app/renderWindowsToast_test.std.tsx @@ -3,7 +3,7 @@ import { assert } from 'chai'; -import { renderWindowsToast } from '../../../app/renderWindowsToast.dom.js'; +import { renderWindowsToast } from '../../../app/renderWindowsToast.std.js'; import { NotificationType } from '../../types/notifications.std.js'; describe('renderWindowsToast', () => {