From fe4c2fb7d631a441f2698fc2c5a5e9e66e87223d Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 9 Mar 2024 14:04:27 -0700 Subject: [PATCH] chore: Add eslint rule for `no-shadow` (#6658) * chore: Add eslint rule for no-shadow * fix --- .eslintrc | 8 ++++++++ app/editor/index.tsx | 2 +- server/routes/api/index.ts | 7 ++----- server/utils/decorators/Public.ts | 4 ++-- server/utils/fetch.ts | 4 ++-- server/utils/prefetchTags.tsx | 8 ++++---- server/utils/validators.ts | 4 ++-- shared/editor/components/hooks/useDragResize.ts | 4 ++-- shared/editor/lib/ExtensionManager.ts | 2 +- shared/editor/lib/markdown/rules.ts | 4 ++-- shared/editor/lib/markdown/serializer.ts | 12 ++++++------ shared/editor/plugins/Suggestions.ts | 6 +++--- shared/editor/rules/breaks.ts | 5 ++--- shared/editor/rules/checkboxes.ts | 6 +++--- shared/types.ts | 4 ++-- shared/utils/ProsemirrorHelper.ts | 4 ++-- shared/utils/date.ts | 12 ++++++------ shared/utils/files.ts | 4 ++-- 18 files changed, 52 insertions(+), 48 deletions(-) diff --git a/.eslintrc b/.eslintrc index 0db0ef19d..65c2d868e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -32,11 +32,19 @@ "object-shorthand": "error", "no-mixed-operators": "off", "no-useless-escape": "off", + "no-shadow": "off", "es/no-regexp-lookbehind-assertions": "error", "react/self-closing-comp": ["error", { "component": true, "html": true }], + "@typescript-eslint/no-shadow": [ + "warn", + { + "hoist": "all", + "ignoreTypeValueShadow": true + } + ], "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/await-thenable": "error", diff --git a/app/editor/index.tsx b/app/editor/index.tsx index 0154691fd..3bc65698f 100644 --- a/app/editor/index.tsx +++ b/app/editor/index.tsx @@ -390,7 +390,7 @@ export class Editor extends React.PureComponent< private createPasteParser() { return this.extensions.parser({ schema: this.schema, - rules: { linkify: true, emoji: false }, + rules: { linkify: true }, plugins: this.rulePlugins, }); } diff --git a/server/routes/api/index.ts b/server/routes/api/index.ts index 20a923b50..970d6b4a4 100644 --- a/server/routes/api/index.ts +++ b/server/routes/api/index.ts @@ -59,12 +59,9 @@ api.use(apiResponse()); api.use(editor()); // Register plugin API routes before others to allow for overrides -const plugins = PluginManager.getEnabledPlugins(PluginType.API).map( - (plugin) => plugin.value +PluginManager.getEnabledPlugins(PluginType.API).forEach((plugin) => + router.use("/", plugin.value.routes()) ); -for (const plugin of plugins) { - router.use("/", plugin.routes()); -} // routes router.use("/", auth.routes()); diff --git a/server/utils/decorators/Public.ts b/server/utils/decorators/Public.ts index b1c606d83..7f9106986 100644 --- a/server/utils/decorators/Public.ts +++ b/server/utils/decorators/Public.ts @@ -22,8 +22,8 @@ export class PublicEnvironmentRegister { static registerEnv(env: Environment) { process.nextTick(() => { - const vars: string[] = Reflect.getMetadata(key, env); - (vars ?? []).forEach((key: string) => { + const vars: string[] = Reflect.getMetadata(key, env) ?? []; + vars.forEach((key: string) => { if (isUndefined(this.publicEnv[key])) { this.publicEnv[key] = env[key]; } diff --git a/server/utils/fetch.ts b/server/utils/fetch.ts index 2a66bb1c3..854d24b49 100644 --- a/server/utils/fetch.ts +++ b/server/utils/fetch.ts @@ -19,9 +19,9 @@ export default function fetch( ): Promise { // In self-hosted, webhooks support proxying and are also allowed to connect // to internal services, so use fetchWithProxy without the filtering agent. - const fetch = env.isCloudHosted ? nodeFetch : fetchWithProxy; + const fetchMethod = env.isCloudHosted ? nodeFetch : fetchWithProxy; - return fetch(url, { + return fetchMethod(url, { ...init, agent: env.isCloudHosted ? useAgent(url) : undefined, }); diff --git a/server/utils/prefetchTags.tsx b/server/utils/prefetchTags.tsx index 11f8a8170..4ea5d2101 100644 --- a/server/utils/prefetchTags.tsx +++ b/server/utils/prefetchTags.tsx @@ -32,12 +32,12 @@ if (env.isProduction) { const manifest = readManifestFile(); const returnFileAndImportsFromManifest = ( - manifest: ManifestStructure, + manifestStructure: ManifestStructure, file: string ): string[] => [ - manifest[file]["file"], - ...(manifest[file]["imports"] ?? []).map( - (entry: string) => manifest[entry]["file"] + manifestStructure[file]["file"], + ...(manifestStructure[file]["imports"] ?? []).map( + (entry: string) => manifestStructure[entry]["file"] ), ]; diff --git a/server/utils/validators.ts b/server/utils/validators.ts index 4b85c542c..5a97f5aad 100644 --- a/server/utils/validators.ts +++ b/server/utils/validators.ts @@ -18,9 +18,9 @@ export function CannotUseWithout( options: validationOptions, validator: { validate(value: T, args: ValidationArguments) { - const object = args.object as unknown as T; + const obj = args.object as unknown as T; const required = args.constraints[0] as string; - return object[required] !== undefined; + return obj[required] !== undefined; }, defaultMessage(args: ValidationArguments) { return `${propertyName} cannot be used without ${args.constraints[0]}.`; diff --git a/shared/editor/components/hooks/useDragResize.ts b/shared/editor/components/hooks/useDragResize.ts index 0d41374d5..5ae85404b 100644 --- a/shared/editor/components/hooks/useDragResize.ts +++ b/shared/editor/components/hooks/useDragResize.ts @@ -84,7 +84,7 @@ export default function useDragResize(props: Props): ReturnValue { }; const handlePointerDown = - (dragging: "left" | "right") => + (dragDirection: "left" | "right") => (event: React.PointerEvent) => { event.preventDefault(); event.stopPropagation(); @@ -93,7 +93,7 @@ export default function useDragResize(props: Props): ReturnValue { height: size.height, }); setOffset(event.pageX); - setDragging(dragging); + setDragging(dragDirection); }; React.useEffect(() => { diff --git a/shared/editor/lib/ExtensionManager.ts b/shared/editor/lib/ExtensionManager.ts index e99103fd1..ca0a9846a 100644 --- a/shared/editor/lib/ExtensionManager.ts +++ b/shared/editor/lib/ExtensionManager.ts @@ -134,7 +134,7 @@ export default class ExtensionManager { plugins, }: { schema: Schema; - rules?: Record; + rules?: markdownit.Options; plugins?: PluginSimple[]; }): MarkdownParser { const tokens = this.extensions diff --git a/shared/editor/lib/markdown/rules.ts b/shared/editor/lib/markdown/rules.ts index ec1415abe..f4209fd54 100644 --- a/shared/editor/lib/markdown/rules.ts +++ b/shared/editor/lib/markdown/rules.ts @@ -1,10 +1,10 @@ import markdownit, { PluginSimple } from "markdown-it"; -export default function rules({ +export default function makeRules({ rules = {}, plugins = [], }: { - rules?: Record; + rules?: markdownit.Options; plugins?: PluginSimple[]; }) { const markdownIt = markdownit("default", { diff --git a/shared/editor/lib/markdown/serializer.ts b/shared/editor/lib/markdown/serializer.ts index 635d39113..c453e173e 100644 --- a/shared/editor/lib/markdown/serializer.ts +++ b/shared/editor/lib/markdown/serializer.ts @@ -221,7 +221,7 @@ export class MarkdownSerializerState { }) ) { // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars - const [_, lead, inner, trail] = /^(\s*)(.*?)(\s*)$/m.exec(node.text); + const [, lead, inner, trail] = /^(\s*)(.*?)(\s*)$/m.exec(node.text); leading += lead; trailing = trail; if (lead || trail) { @@ -366,20 +366,20 @@ export class MarkdownSerializerState { row.forEach((cell, _, j) => { this.out += j === 0 ? "| " : " | "; - cell.forEach((node) => { + cell.forEach((cellNode) => { // just padding the output so that empty cells take up the same space // as headings. // TODO: Ideally we'd calc the longest cell length and use that // to pad all the others. if ( - node.textContent === "" && - node.content.size === 0 && - node.type.name === "paragraph" + cellNode.textContent === "" && + cellNode.content.size === 0 && + cellNode.type.name === "paragraph" ) { this.out += " "; } else { this.closed = false; - this.render(node, row, j); + this.render(cellNode, row, j); } }); diff --git a/shared/editor/plugins/Suggestions.ts b/shared/editor/plugins/Suggestions.ts index dbfd8d1ef..ffc953f47 100644 --- a/shared/editor/plugins/Suggestions.ts +++ b/shared/editor/plugins/Suggestions.ts @@ -28,11 +28,11 @@ export class SuggestionsMenuPlugin extends Plugin { // timeout ensures that the delete has been handled by prosemirror // and any characters removed, before we evaluate the rule. setTimeout(() => { - const { pos } = view.state.selection.$from; + const { pos: fromPos } = view.state.selection.$from; return this.execute( view, - pos, - pos, + fromPos, + fromPos, options.openRegex, action((_, match) => { if (match) { diff --git a/shared/editor/rules/breaks.ts b/shared/editor/rules/breaks.ts index fd2863f70..6876e71ed 100644 --- a/shared/editor/rules/breaks.ts +++ b/shared/editor/rules/breaks.ts @@ -11,7 +11,6 @@ function isHardbreak(token: Token) { export default function markdownBreakToParagraphs(md: MarkdownIt) { // insert a new rule after the "inline" rules are parsed md.core.ruler.after("inline", "breaks", (state) => { - const { Token } = state; const tokens = state.tokens; // work backwards through the tokens and find text that looks like a br @@ -30,8 +29,8 @@ export default function markdownBreakToParagraphs(md: MarkdownIt) { count++; } - for (let i = 0; i < count; i++) { - const isLast = i === count - 1; + for (let j = 0; j < count; j++) { + const isLast = j === count - 1; token = new Token("paragraph_open", "p", 1); nodes.push(token); diff --git a/shared/editor/rules/checkboxes.ts b/shared/editor/rules/checkboxes.ts index 806861f08..8a3fbd17f 100644 --- a/shared/editor/rules/checkboxes.ts +++ b/shared/editor/rules/checkboxes.ts @@ -56,9 +56,9 @@ export default function markdownItCheckbox(md: MarkdownIt): void { // work backwards through the tokens and find text that looks like a checkbox for (let i = tokens.length - 1; i > 0; i--) { - const matches = looksLikeChecklist(tokens, i); - if (matches) { - const value = matches[1]; + const matchesChecklist = looksLikeChecklist(tokens, i); + if (matchesChecklist) { + const value = matchesChecklist[1]; const checked = value.toLowerCase() === "x"; // convert surrounding list tokens diff --git a/shared/types.ts b/shared/types.ts index 88916428f..5d8a13912 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -218,9 +218,9 @@ export enum NotificationChannelType { } export type NotificationSettings = { - [key in NotificationEventType]?: + [event in NotificationEventType]?: | { - [key in NotificationChannelType]?: boolean; + [type in NotificationChannelType]?: boolean; } | boolean; }; diff --git a/shared/utils/ProsemirrorHelper.ts b/shared/utils/ProsemirrorHelper.ts index 7c4f17998..938c20a8e 100644 --- a/shared/utils/ProsemirrorHelper.ts +++ b/shared/utils/ProsemirrorHelper.ts @@ -35,14 +35,14 @@ export default class ProsemirrorHelper { * @param schema The schema to use. * @returns The document content as plain text without formatting. */ - static toPlainText(node: Node, schema: Schema) { + static toPlainText(root: Node, schema: Schema) { const textSerializers = Object.fromEntries( Object.entries(schema.nodes) .filter(([, node]) => node.spec.toPlainText) .map(([name, node]) => [name, node.spec.toPlainText]) ); - return textBetween(node, 0, node.content.size, textSerializers); + return textBetween(root, 0, root.content.size, textSerializers); } /** diff --git a/shared/utils/date.ts b/shared/utils/date.ts index dcd9ed1eb..e6a5e0ec3 100644 --- a/shared/utils/date.ts +++ b/shared/utils/date.ts @@ -121,8 +121,8 @@ export function unicodeCLDRtoISO639(locale: string) { * * @returns The current date */ -export function getCurrentDateAsString(locales?: Intl.LocalesArgument) { - return new Date().toLocaleDateString(locales, { +export function getCurrentDateAsString(locale?: Intl.LocalesArgument) { + return new Date().toLocaleDateString(locale, { year: "numeric", month: "long", day: "numeric", @@ -134,8 +134,8 @@ export function getCurrentDateAsString(locales?: Intl.LocalesArgument) { * * @returns The current time */ -export function getCurrentTimeAsString(locales?: Intl.LocalesArgument) { - return new Date().toLocaleTimeString(locales, { +export function getCurrentTimeAsString(locale?: Intl.LocalesArgument) { + return new Date().toLocaleTimeString(locale, { hour: "numeric", minute: "numeric", }); @@ -147,8 +147,8 @@ export function getCurrentTimeAsString(locales?: Intl.LocalesArgument) { * * @returns The current date and time */ -export function getCurrentDateTimeAsString(locales?: Intl.LocalesArgument) { - return new Date().toLocaleString(locales, { +export function getCurrentDateTimeAsString(locale?: Intl.LocalesArgument) { + return new Date().toLocaleString(locale, { year: "numeric", month: "long", day: "numeric", diff --git a/shared/utils/files.ts b/shared/utils/files.ts index 63833944f..02e0119f2 100644 --- a/shared/utils/files.ts +++ b/shared/utils/files.ts @@ -44,8 +44,8 @@ export function getDataTransferFiles( return dt.items ? Array.prototype.slice .call(dt.items) - .filter((dt: DataTransferItem) => dt.kind !== "string") - .map((dt: DataTransferItem) => dt.getAsFile()) + .filter((dti: DataTransferItem) => dti.kind !== "string") + .map((dti: DataTransferItem) => dti.getAsFile()) .filter(Boolean) : []; }