From e5ac0877609eb7c8e868fa038d89a68520e562bb Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Tue, 26 May 2026 17:37:02 -0300 Subject: [PATCH] refactor(types): drain 85 type-bearing JSDoc entries from .ts source (SD-673) Drains the jsdoc-hygiene-ts baseline from 85 entries to 0. Companion to the scanner PR (#3511) that grandfathered these entries; this is the bulk mechanical cleanup. The zero-baseline flip lands in a third PR after this. declaration-doc-type (78 entries): - @param {T} name description -> @param name description (drop braces, keep prose). - @returns {T} description -> @returns description (drop braces, keep prose). - @template T - description -> @typeParam T - description. TSDoc-canonical replacement; prose preserved (16 entries across Mark / Node / OxmlNode / defineMark / defineNode / Extension / EventEmitter / helpers). - @extends {Base} / @implements {Iface} -> deleted (TS has native extends / implements syntax on the declaration). - Empty @returns tags removed (10 dead documentation lines across both EventEmitters and PresentationEditor where the brace strip left a tag carrying no information). inline-fake-cast (6 entries: 5 from original baseline + 1 new on Editor.ts:219 that landed post-#3511): - #abortUpgrade, readyEditors, pendingCollaborationSaves: the @type was redundant next to the TS field annotation. Dropped the tag, kept the prose. - /** @type {RuntimeDocument} */ ... and /** @type {string} */ doc.id in SuperDoc.ts: real-intent casts that did nothing in .ts. Converted to 'as RuntimeDocument' and 'as string'. - /** @type {YMapEvent} */ on a Yjs observe callback param in SuperDoc.ts: converted to a TS param annotation (event: Y.YMapEvent). - /** @type {Mark[]} */ on insertionMarks in Editor.ts:219 (new in main since the scanner PR): converted to a TS local var annotation (PmMark[] is already imported). - The InternalConfig doc example in types/index.ts was teaching the /** @type */ cast pattern explicitly. Rewrote to teach '(value as Type)' instead. typedef-style (2 entries): rewrites. The @typedef tags lived inside @example blocks in defineMark.ts / defineNode.ts teaching JS consumers how to type-hint. Replaced literal /** @typedef */ syntax with prose describing the pattern; preserves teaching value without triggering the scanner. Verified: - node check-jsdoc-hygiene-ts.cjs -> OK, 0 violations - node check-jsdoc-hygiene-ts-tests.cjs -> 13/13 pass - pnpm check:types -> PASS - pnpm check:public:superdoc --skip-build -> PASS (11 ran, 1 skipped, 135.3s) - pnpm --filter superdoc test --run -> PASS (1064/1064, 79 files) --- .../src/editors/v1/core/Editor.ts | 4 +- .../src/editors/v1/core/EventEmitter.ts | 7 +- .../src/editors/v1/core/Extension.ts | 5 +- .../super-editor/src/editors/v1/core/Mark.ts | 14 +-- .../super-editor/src/editors/v1/core/Node.ts | 14 +-- .../src/editors/v1/core/OxmlNode.ts | 16 ++-- .../src/editors/v1/core/defineMark.ts | 19 ++-- .../src/editors/v1/core/defineNode.ts | 19 ++-- .../core/helpers/getExtensionConfigField.ts | 3 +- .../presentation-editor/PresentationEditor.ts | 2 - .../scripts/jsdoc-hygiene-ts-baseline.json | 88 +------------------ packages/superdoc/src/core/EventEmitter.ts | 5 -- packages/superdoc/src/core/SuperDoc.ts | 87 +++++++++--------- packages/superdoc/src/core/types/index.ts | 4 +- 14 files changed, 96 insertions(+), 191 deletions(-) diff --git a/packages/super-editor/src/editors/v1/core/Editor.ts b/packages/super-editor/src/editors/v1/core/Editor.ts index 16e66dbd28..3e4e024364 100644 --- a/packages/super-editor/src/editors/v1/core/Editor.ts +++ b/packages/super-editor/src/editors/v1/core/Editor.ts @@ -216,8 +216,7 @@ const rangeIsTrackedInsertionOnly = (doc: PmNode, from: number, to: number): boo const getSingleTrackedInsertionMarkInRange = (doc: PmNode, from: number, to: number): PmMark | null => { if (!rangeIsTrackedInsertionOnly(doc, from, to)) return null; - /** @type {import('prosemirror-model').Mark[]} */ - const insertionMarks = []; + const insertionMarks: PmMark[] = []; const seenIds = new Set(); doc.nodesBetween(from, to, (node, pos) => { if (!node.isInline || !node.isLeaf) return; @@ -993,7 +992,6 @@ export class Editor extends EventEmitter { * This prevents race conditions and ensures the editor is always in a valid state, * even when operations fail. * - * @template T - The return type of the operation * @param during - State to set while the operation is running * @param success - State to set if the operation succeeds * @param failure - State to set if the operation fails diff --git a/packages/super-editor/src/editors/v1/core/EventEmitter.ts b/packages/super-editor/src/editors/v1/core/EventEmitter.ts index 63e1b630de..df613eb8b4 100644 --- a/packages/super-editor/src/editors/v1/core/EventEmitter.ts +++ b/packages/super-editor/src/editors/v1/core/EventEmitter.ts @@ -23,7 +23,8 @@ export type EventCallback = (...args: Args) /** * EventEmitter class is used to emit and subscribe to events. - * @template EventMap - Map of event names to their argument types + * + * @typeParam EventMap - Map of event names to their argument types. */ export class EventEmitter { #events = new Map(); @@ -32,7 +33,6 @@ export class EventEmitter { * Subscribe to the event. * @param name Event name. * @param fn Callback. - * @returns {void} */ on(name: K, fn: EventCallback): void { const callbacks = this.#events.get(name); @@ -44,7 +44,6 @@ export class EventEmitter { * Emit event. * @param name Event name. * @param args Arguments to pass to each listener. - * @returns {void} */ emit(name: K, ...args: EventMap[K]): void { const callbacks = this.#events.get(name); @@ -78,7 +77,6 @@ export class EventEmitter { * or all event subscriptions. * @param name Event name. * @param fn Callback. - * @returns {void} */ off(name: K, fn?: EventCallback): void { const callbacks = this.#events.get(name); @@ -94,7 +92,6 @@ export class EventEmitter { * Subscribe to an event that will be called only once. * @param name Event name. * @param fn Callback. - * @returns {void} */ once(name: K, fn: EventCallback): void { const wrapper = (...args: EventMap[K]) => { diff --git a/packages/super-editor/src/editors/v1/core/Extension.ts b/packages/super-editor/src/editors/v1/core/Extension.ts index 28f1d06962..95223fb595 100644 --- a/packages/super-editor/src/editors/v1/core/Extension.ts +++ b/packages/super-editor/src/editors/v1/core/Extension.ts @@ -4,6 +4,9 @@ import type { MaybeGetter } from './utilities/callOrGet.js'; /** * Base configuration for extensions. + * + * @typeParam Options - Type for extension options. + * @typeParam Storage - Type for extension storage. */ export interface ExtensionConfig< Options extends Record = Record, @@ -24,8 +27,6 @@ export interface ExtensionConfig< /** * Extension class is used to create extensions. - * @template Options - Type for extension options - * @template Storage - Type for extension storage */ export class Extension< Options extends Record = Record, diff --git a/packages/super-editor/src/editors/v1/core/Mark.ts b/packages/super-editor/src/editors/v1/core/Mark.ts index b6557a60ed..b9d2334af9 100644 --- a/packages/super-editor/src/editors/v1/core/Mark.ts +++ b/packages/super-editor/src/editors/v1/core/Mark.ts @@ -6,9 +6,10 @@ import type { AttributeSpec } from './Attribute.js'; /** * Configuration for Mark extensions. - * @template Options - Type for mark options - * @template Storage - Type for mark storage - * @template Attrs - Type for mark attributes (optional, enables typed addAttributes) + * + * @typeParam Options - Type for mark options. + * @typeParam Storage - Type for mark storage. + * @typeParam Attrs - Type for mark attributes (optional, enables typed addAttributes). */ export interface MarkConfig< Options extends Record = Record, @@ -39,9 +40,10 @@ export interface MarkConfig< /** * Mark class is used to create Mark extensions. - * @template Options - Type for mark options - * @template Storage - Type for mark storage - * @template Attrs - Type for mark attributes (enables typed attribute access) + * + * @typeParam Options - Type for mark options. + * @typeParam Storage - Type for mark storage. + * @typeParam Attrs - Type for mark attributes (enables typed attribute access). */ export class Mark< Options extends Record = Record, diff --git a/packages/super-editor/src/editors/v1/core/Node.ts b/packages/super-editor/src/editors/v1/core/Node.ts index 4e5fd164e9..0cb1e6c433 100644 --- a/packages/super-editor/src/editors/v1/core/Node.ts +++ b/packages/super-editor/src/editors/v1/core/Node.ts @@ -69,9 +69,10 @@ export type RenderDOMFn = (props: { /** * Configuration for Node extensions. - * @template Options - Type for node options - * @template Storage - Type for node storage - * @template Attrs - Type for node attributes (optional, enables typed addAttributes) + * + * @typeParam Options - Type for node options. + * @typeParam Storage - Type for node storage. + * @typeParam Attrs - Type for node attributes (optional, enables typed addAttributes). */ export interface NodeConfig< Options extends Record = Record, @@ -189,9 +190,10 @@ export interface NodeConfig< /** * Node class is used to create Node extensions. - * @template Options - Type for node options - * @template Storage - Type for node storage - * @template Attrs - Type for node attributes (enables typed attribute access) + * + * @typeParam Options - Type for node options. + * @typeParam Storage - Type for node storage. + * @typeParam Attrs - Type for node attributes (enables typed attribute access). */ export class Node< Options extends Record = Record, diff --git a/packages/super-editor/src/editors/v1/core/OxmlNode.ts b/packages/super-editor/src/editors/v1/core/OxmlNode.ts index 949042b9d5..0c86734c52 100644 --- a/packages/super-editor/src/editors/v1/core/OxmlNode.ts +++ b/packages/super-editor/src/editors/v1/core/OxmlNode.ts @@ -2,10 +2,11 @@ import { Node } from './Node.js'; import type { NodeConfig } from './Node.js'; /** - * Configuration for OXML Node extensions (extends NodeConfig) - * @template Options - Type for node options - * @template Storage - Type for node storage - * @template Attrs - Type for node attributes (optional, enables typed addAttributes) + * Configuration for OXML Node extensions (extends NodeConfig). + * + * @typeParam Options - Type for node options. + * @typeParam Storage - Type for node storage. + * @typeParam Attrs - Type for node attributes (optional, enables typed addAttributes). */ export interface OxmlNodeConfig< Options extends Record = Record, @@ -21,9 +22,10 @@ export interface OxmlNodeConfig< /** * OxmlNode class extends Node with OXML-specific properties. - * @template Options - Type for node options - * @template Storage - Type for node storage - * @template Attrs - Type for node attributes (enables typed attribute access) + * + * @typeParam Options - Type for node options. + * @typeParam Storage - Type for node storage. + * @typeParam Attrs - Type for node attributes (enables typed attribute access). */ export class OxmlNode< Options extends Record = Record, diff --git a/packages/super-editor/src/editors/v1/core/defineMark.ts b/packages/super-editor/src/editors/v1/core/defineMark.ts index f1ce80f3bf..89748581b1 100644 --- a/packages/super-editor/src/editors/v1/core/defineMark.ts +++ b/packages/super-editor/src/editors/v1/core/defineMark.ts @@ -29,13 +29,12 @@ * * @example * ```javascript - * // In a JavaScript file with JSDoc: + * // In a JavaScript file with JSDoc: alias the BoldAttrs type at the top + * // of the file via a standard `typedef` JSDoc block pointing at + * // '@extensions/types/mark-attributes.js', then defineMark picks up the + * // attribute shape from there. * import { defineMark } from '@core/defineMark.js'; * - * /** - * * @typedef {import('@extensions/types/mark-attributes.js').BoldAttrs} BoldAttrs - * *\/ - * * export const Bold = defineMark({ * name: 'bold', * // ... @@ -50,11 +49,11 @@ import { Mark, type MarkConfig } from './Mark.js'; /** * Type-safe factory for creating Mark extensions. * - * @template Options - Extension options type - * @template Storage - Extension storage type - * @template Attrs - Mark attributes type - * @param config - Mark configuration object - * @returns A new Mark instance with the specified types + * @typeParam Options - Extension options type. + * @typeParam Storage - Extension storage type. + * @typeParam Attrs - Mark attributes type. + * @param config - Mark configuration object. + * @returns A new Mark instance with the specified types. */ export function defineMark< Options extends Record = Record, diff --git a/packages/super-editor/src/editors/v1/core/defineNode.ts b/packages/super-editor/src/editors/v1/core/defineNode.ts index b81093481b..ed32750575 100644 --- a/packages/super-editor/src/editors/v1/core/defineNode.ts +++ b/packages/super-editor/src/editors/v1/core/defineNode.ts @@ -28,13 +28,12 @@ * * @example * ```javascript - * // In a JavaScript file with JSDoc: + * // In a JavaScript file with JSDoc: alias ParagraphAttrs at the top of + * // the file via a standard `typedef` JSDoc block pointing at + * // '@extensions/types/node-attributes.js', then defineNode picks up the + * // attribute shape from there. * import { defineNode } from '@core/defineNode.js'; * - * /** - * * @typedef {import('@extensions/types/node-attributes.js').ParagraphAttrs} ParagraphAttrs - * *\/ - * * export const Paragraph = defineNode({ * name: 'paragraph', * // ... @@ -49,11 +48,11 @@ import { Node, type NodeConfig } from './Node.js'; /** * Type-safe factory for creating Node extensions. * - * @template Options - Extension options type - * @template Storage - Extension storage type - * @template Attrs - Node attributes type - * @param config - Node configuration object - * @returns A new Node instance with the specified types + * @typeParam Options - Extension options type. + * @typeParam Storage - Extension storage type. + * @typeParam Attrs - Node attributes type. + * @param config - Node configuration object. + * @returns A new Node instance with the specified types. */ export function defineNode< Options extends Record = Record, diff --git a/packages/super-editor/src/editors/v1/core/helpers/getExtensionConfigField.ts b/packages/super-editor/src/editors/v1/core/helpers/getExtensionConfigField.ts index cf0565e604..1cac56e327 100644 --- a/packages/super-editor/src/editors/v1/core/helpers/getExtensionConfigField.ts +++ b/packages/super-editor/src/editors/v1/core/helpers/getExtensionConfigField.ts @@ -27,11 +27,12 @@ export interface ExtensionLike { /** * Get extension config field. * If the field is a function, it will be bound to the provided context. + * + * @typeParam T - The expected return type of the config field. * @param extension The Editor extension. * @param field The config field name. * @param context The context object to bind to function. * @returns The config field value or bound function. - * @template T The expected return type of the config field. */ export function getExtensionConfigField( extension: ExtensionLike, diff --git a/packages/super-editor/src/editors/v1/core/presentation-editor/PresentationEditor.ts b/packages/super-editor/src/editors/v1/core/presentation-editor/PresentationEditor.ts index 803e8d459e..a8f54c81fd 100644 --- a/packages/super-editor/src/editors/v1/core/presentation-editor/PresentationEditor.ts +++ b/packages/super-editor/src/editors/v1/core/presentation-editor/PresentationEditor.ts @@ -4940,7 +4940,6 @@ export class PresentationEditor extends EventEmitter { * This method encapsulates the common focus and blur logic used when * selecting both inline and block images. * @private - * @returns {void} */ #focusEditorAfterImageSelection(): void { this.#shouldScrollSelectionIntoView = true; @@ -6918,7 +6917,6 @@ export class PresentationEditor extends EventEmitter { * This method is called after layout completes to ensure cursor positioning * is based on stable layout data. * - * @returns {void} * * @remarks * Edge cases handled: diff --git a/packages/superdoc/scripts/jsdoc-hygiene-ts-baseline.json b/packages/superdoc/scripts/jsdoc-hygiene-ts-baseline.json index fadeef1522..a86c1abd54 100644 --- a/packages/superdoc/scripts/jsdoc-hygiene-ts-baseline.json +++ b/packages/superdoc/scripts/jsdoc-hygiene-ts-baseline.json @@ -1,90 +1,4 @@ { "$comment": "Auto-managed by packages/superdoc/scripts/check-jsdoc-hygiene-ts.cjs. Each entry is \"file::enclosingSymbol::tagName::class::occurrenceIndex\"; line numbers are NOT part of the key, so the baseline survives unrelated edits that shift line numbers. The gate grandfathers these and fails on net-new violations. Refresh after intentional cleanup with --write. Goal is to drain to zero, then flip to \"zero allowed\" in a separate PR. See packages/superdoc/scripts/type-hygiene.md.", - "knownViolations": [ - "packages/super-editor/src/editors/v1/core/Editor.ts::#withState::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/EventEmitter.ts::EventEmitter::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/EventEmitter.ts::emit::returns::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/EventEmitter.ts::off::returns::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/EventEmitter.ts::on::returns::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/EventEmitter.ts::once::returns::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/Extension.ts::Extension::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/Extension.ts::Extension::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/Mark.ts::Mark::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/Mark.ts::Mark::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/Mark.ts::Mark::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/Mark.ts::MarkConfig::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/Mark.ts::MarkConfig::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/Mark.ts::MarkConfig::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/Node.ts::Node::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/Node.ts::Node::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/Node.ts::Node::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/Node.ts::NodeConfig::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/Node.ts::NodeConfig::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/Node.ts::NodeConfig::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/OxmlNode.ts::OxmlNode::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/OxmlNode.ts::OxmlNode::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/OxmlNode.ts::OxmlNode::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/OxmlNode.ts::OxmlNodeConfig::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/OxmlNode.ts::OxmlNodeConfig::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/OxmlNode.ts::OxmlNodeConfig::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/defineMark.ts::::typedef::typedef-style::0", - "packages/super-editor/src/editors/v1/core/defineMark.ts::defineMark::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/defineMark.ts::defineMark::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/defineMark.ts::defineMark::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/defineNode.ts::::typedef::typedef-style::0", - "packages/super-editor/src/editors/v1/core/defineNode.ts::defineNode::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/defineNode.ts::defineNode::template::declaration-doc-type::1", - "packages/super-editor/src/editors/v1/core/defineNode.ts::defineNode::template::declaration-doc-type::2", - "packages/super-editor/src/editors/v1/core/helpers/getExtensionConfigField.ts::getExtensionConfigField::template::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/presentation-editor/PresentationEditor.ts::#focusEditorAfterImageSelection::returns::declaration-doc-type::0", - "packages/super-editor/src/editors/v1/core/presentation-editor/PresentationEditor.ts::#updateSelection::returns::declaration-doc-type::0", - "packages/superdoc/src/core/EventEmitter.ts::EventEmitter::template::declaration-doc-type::0", - "packages/superdoc/src/core/EventEmitter.ts::emit::returns::declaration-doc-type::0", - "packages/superdoc/src/core/EventEmitter.ts::off::returns::declaration-doc-type::0", - "packages/superdoc/src/core/EventEmitter.ts::on::returns::declaration-doc-type::0", - "packages/superdoc/src/core/EventEmitter.ts::once::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#abortUpgrade::type::inline-fake-cast::0", - "packages/superdoc/src/core/SuperDoc.ts::#applyDocumentMode::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#applyDocumentMode::param::declaration-doc-type::1", - "packages/superdoc/src/core/SuperDoc.ts::#initCollaboration::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#log::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#patchNaiveUIStyles::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#requireSuperdocStore::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#resolveSourceEditor::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#triggerCollaborationSaves::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::#validateUpgradePrerequisites::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::SuperDoc::extends::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::SuperDoc::implements::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::addCommentsList::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::addSharedUser::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::broadcastEditorBeforeCreate::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::broadcastEditorCreate::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::event::type::inline-fake-cast::0", - "packages/superdoc/src/core/SuperDoc.ts::export::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::exportEditorsToDOCX::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::getHTML::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::getZoom::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::goToSearchResult::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::goToSearchResult::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::lockSuperdoc::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::lockSuperdoc::param::declaration-doc-type::1", - "packages/superdoc/src/core/SuperDoc.ts::navigateTo::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::openSurface::template::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::pendingCollaborationSaves::type::inline-fake-cast::0", - "packages/superdoc/src/core/SuperDoc.ts::readyEditors::type::inline-fake-cast::0", - "packages/superdoc/src/core/SuperDoc.ts::removeSharedUser::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::requiredNumberOfEditors::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::scrollToComment::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::scrollToComment::param::declaration-doc-type::1", - "packages/superdoc/src/core/SuperDoc.ts::scrollToComment::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::scrollToElement::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::scrollToElement::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::search::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::search::returns::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::setActiveEditor::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::setTrackedChangesPreferences::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::setZoom::param::declaration-doc-type::0", - "packages/superdoc/src/core/SuperDoc.ts::upgradeToCollaboration::returns::declaration-doc-type::0", - "packages/superdoc/src/core/types/index.ts::InternalConfig::type::inline-fake-cast::0" - ] + "knownViolations": [] } diff --git a/packages/superdoc/src/core/EventEmitter.ts b/packages/superdoc/src/core/EventEmitter.ts index 6bce2438fb..1295087820 100644 --- a/packages/superdoc/src/core/EventEmitter.ts +++ b/packages/superdoc/src/core/EventEmitter.ts @@ -22,7 +22,6 @@ export type EventCallback = (...args: Args) /** * EventEmitter class is used to emit and subscribe to events. - * @template EventMap - Map of event names to their argument types */ export class EventEmitter { #events = new Map(); @@ -31,7 +30,6 @@ export class EventEmitter { * Subscribe to the event. * @param name Event name. * @param fn Callback. - * @returns {void} */ on(name: K, fn: EventCallback): void { const callbacks = this.#events.get(name); @@ -46,7 +44,6 @@ export class EventEmitter { * Emit event. * @param name Event name. * @param args Arguments to pass to each listener. - * @returns {void} */ emit(name: K, ...args: EventMap[K]): void { const callbacks = this.#events.get(name); @@ -61,7 +58,6 @@ export class EventEmitter { * or all event subscriptions. * @param name Event name. * @param fn Callback. - * @returns {void} */ off(name: K, fn?: EventCallback): void { const callbacks = this.#events.get(name); @@ -77,7 +73,6 @@ export class EventEmitter { * Subscribe to an event that will be called only once. * @param name Event name. * @param fn Callback. - * @returns {void} */ once(name: K, fn: EventCallback): void { const wrapper = (...args: EventMap[K]) => { diff --git a/packages/superdoc/src/core/SuperDoc.ts b/packages/superdoc/src/core/SuperDoc.ts index 77834f1817..8e62fb5fc3 100644 --- a/packages/superdoc/src/core/SuperDoc.ts +++ b/packages/superdoc/src/core/SuperDoc.ts @@ -173,8 +173,6 @@ interface SuperDocEventMap { * Expects a config object * * @class - * @extends {EventEmitter} - * @implements {SuperDocLike} */ export class SuperDoc extends EventEmitter { static allowedTypes = [DOCX, PDF, HTML]; @@ -183,7 +181,7 @@ export class SuperDoc extends EventEmitter { #isUpgrading = false; - /** @type {(() => void) | null} — aborts an in-flight upgrade (sync wait or ready wait) */ + /** Aborts an in-flight upgrade (sync wait or ready wait). */ #abortUpgrade: (() => void) | null = null; #mountWrapper: HTMLDivElement | null = null; @@ -318,10 +316,10 @@ export class SuperDoc extends EventEmitter { /** Pinia store root for the SuperDoc Vue app. Set in `#initVueApp`. */ pinia: ReturnType['pinia'] | undefined; - /** @type {number} Count of editors that have signaled `editorCreate`. */ + /** Count of editors that have signaled `editorCreate`. */ readyEditors = 0; - /** @type {number} Outstanding async saves waiting for collaboration ack. */ + /** Outstanding async saves waiting for collaboration ack. */ pendingCollaborationSaves = 0; // ─── Runtime fields populated by `#init` ────────────────────────────── @@ -631,7 +629,7 @@ export class SuperDoc extends EventEmitter { /** * Get the number of editors that are required for this superdoc - * @returns {number} The number of required editors + * @returns The number of required editors */ get requiredNumberOfEditors() { return this.#requireSuperdocStore('requiredNumberOfEditors').documents.filter( @@ -698,7 +696,7 @@ export class SuperDoc extends EventEmitter { const cspNonce = this.config.cspNonce; const originalCreateElement = document.createElement; - /** @param {string} tagName */ + /** @param tagName */ document.createElement = function (tagName: string) { const element = originalCreateElement.call(this, tagName); if (tagName.toLowerCase() === 'style') { @@ -858,7 +856,7 @@ export class SuperDoc extends EventEmitter { * Initialize collaboration if configured. Accepts the full * `Config.modules` block so it can read both the collaboration * subkey and the comments subkey at once. - * @returns {Promise} The processed documents with collaboration enabled. Caller awaits for side effects; the return value is informational. + * @returns The processed documents with collaboration enabled. Caller awaits for side effects; the return value is informational. */ async #initCollaboration( { collaboration: collaborationModuleConfig, comments: commentsConfig = {} }: Modules = {} as Modules, @@ -1031,7 +1029,7 @@ export class SuperDoc extends EventEmitter { * - External `{ ydoc, provider }` collaboration * - Overwrite-and-upgrade only (no merge semantics) * - * @returns {Promise} Resolves once the collaborative runtime is ready + * @returns Resolves once the collaborative runtime is ready */ async upgradeToCollaboration({ ydoc, provider }: UpgradeToCollaborationOptions): Promise { this.#validateUpgradePrerequisites({ ydoc, provider }); @@ -1112,7 +1110,7 @@ export class SuperDoc extends EventEmitter { * "instance not yet ready" failure mode explicit instead of a * generic TypeError on `.documents`. * - * @param {string} methodName The public method name surfaced in + * @param methodName The public method name surfaced in * the error so consumers know which call needed the ready state. */ #requireSuperdocStore(methodName: string) { @@ -1328,7 +1326,7 @@ export class SuperDoc extends EventEmitter { * Validate that the instance is in a valid state for a collaboration upgrade. * Throws descriptive errors for each invalid condition. * - * @param {{ ydoc: unknown, provider: unknown }} options + * @param options */ #validateUpgradePrerequisites({ ydoc, provider }: UpgradeToCollaborationOptions) { if (this.#destroyed) { @@ -1360,7 +1358,7 @@ export class SuperDoc extends EventEmitter { /** * Resolve the source editor from the DOCX document entry. * - * @returns {Editor} The editor instance for the source document + * @returns The editor instance for the source document * @throws {Error} If the editor is not yet created */ #resolveSourceEditor() { @@ -1384,7 +1382,7 @@ export class SuperDoc extends EventEmitter { * ready; pre-ready mutations would be silently overwritten by the * `this.users = this.config.users || []` re-seed inside `#init`. * - * @param {User} user The user to add + * @param user The user to add */ addSharedUser(user: User) { this.#requireReady('addSharedUser'); @@ -1398,7 +1396,7 @@ export class SuperDoc extends EventEmitter { * to be ready for the same reason as `addSharedUser`. Accepts * either a user-like object or a legacy email string. * - * @param {User | string} userOrEmail The user or email of the user to remove + * @param userOrEmail The user or email of the user to remove */ removeSharedUser(userOrEmail: User | string) { this.#requireReady('removeSharedUser'); @@ -1427,9 +1425,9 @@ export class SuperDoc extends EventEmitter { // The errored editor came from `superdocStore.documents`, so the find // by its `documentId` is expected to hit. Cast the find result to a // RuntimeDocument to assert non-null at the consumer callback. - const doc = /** @type {RuntimeDocument} */ this.#requireSuperdocStore('onContentError').documents.find( + const doc = this.#requireSuperdocStore('onContentError').documents.find( (d: RuntimeDocument) => d.id === documentId, - ); + ) as RuntimeDocument; // `onContentError` is typed as optional on the public Config typedef // because consumers don't have to wire a handler. The class field // initializer installs a `() => null` default, but `#init` spreads @@ -1444,7 +1442,7 @@ export class SuperDoc extends EventEmitter { this.config.onContentError?.({ error, editor, - documentId: /** @type {string} */ doc.id, + documentId: doc.id as string, file: doc.data, }); } @@ -1467,7 +1465,7 @@ export class SuperDoc extends EventEmitter { /** * Triggered before an editor is created - * @param {Editor} editor The editor that is about to be created + * @param editor The editor that is about to be created */ broadcastEditorBeforeCreate(editor: Editor) { this.emit('editorBeforeCreate', { editor: createDeprecatedEditorProxy(editor) }); @@ -1475,7 +1473,7 @@ export class SuperDoc extends EventEmitter { /** * Triggered when an editor is created - * @param {Editor} editor The editor that was created + * @param editor The editor that was created */ broadcastEditorCreate(editor: Editor) { this.readyEditors++; @@ -1497,14 +1495,14 @@ export class SuperDoc extends EventEmitter { this.emit('sidebar-toggle', isOpened); } - /** @param {unknown[]} args */ + /** @param args */ #log(...args: unknown[]) { (console.debug ? console.debug : console.log)('🦋 🦸‍♀️ [superdoc]', ...args); } /** * Set the active editor - * @param {Editor} editor The editor to set as active + * @param editor The editor to set as active */ setActiveEditor(editor: Editor) { this.activeEditor = editor; @@ -1635,7 +1633,7 @@ export class SuperDoc extends EventEmitter { /** * Add a comments list to the superdoc * Requires the comments module to be enabled - * @param {HTMLElement} element The DOM element to render the comments list in + * @param element The DOM element to render the comments list in */ addCommentsList(element: HTMLElement) { if (!this.config?.modules?.comments || this.config.role === 'viewer') return; @@ -1658,9 +1656,9 @@ export class SuperDoc extends EventEmitter { /** * Scroll the document to a given comment by id. * - * @param {string} commentId The comment id - * @param {{ behavior?: ScrollBehavior, block?: ScrollLogicalPosition }} [options] - * @returns {boolean} Whether a matching element was found + * @param commentId The comment id + * @param [options] + * @returns Whether a matching element was found */ scrollToComment(commentId: string, options: { behavior?: ScrollBehavior; block?: ScrollLogicalPosition } = {}) { const commentsConfig = this.config?.modules?.comments; @@ -1687,7 +1685,7 @@ export class SuperDoc extends EventEmitter { * Story-aware navigation is currently supported for bookmark and tracked * change targets. Block and comment targets are body-only. * - * @returns {Promise} Whether the target was found and navigated to. + * @returns Whether the target was found and navigated to. */ async navigateTo(target: NavigableAddress): Promise { const storeDocs = this.superdocStore?.documents; @@ -1704,8 +1702,8 @@ export class SuperDoc extends EventEmitter { * change entityId. The method resolves the element type automatically * and scrolls to it. * - * @param {string} elementId - The element's stable ID. - * @returns {Promise} Whether the element was found and scrolled to. + * @param elementId - The element's stable ID. + * @returns Whether the element was found and scrolled to. * * @example * // Navigate to a paragraph by its nodeId @@ -1817,8 +1815,8 @@ export class SuperDoc extends EventEmitter { /** * Set the document mode on a document's editor (PresentationEditor or Editor). * Tries PresentationEditor first, falls back to Editor for backward compatibility. - * @param {RuntimeDocument} doc - The document object - * @param {DocumentMode} mode - The document mode ('editing', 'viewing', 'suggesting') + * @param doc - The document object + * @param mode - The document mode ('editing', 'viewing', 'suggesting') */ #applyDocumentMode(doc: RuntimeDocument, mode: DocumentMode) { const presentationEditor = typeof doc.getPresentationEditor === 'function' ? doc.getPresentationEditor() : null; @@ -1836,7 +1834,7 @@ export class SuperDoc extends EventEmitter { * Force PresentationEditor instances to render a specific tracked-changes mode * or disable tracked-change metadata entirely. * - * @param {{ mode?: 'review' | 'original' | 'final' | 'off', enabled?: boolean }} [preferences] + * @param [preferences] */ setTrackedChangesPreferences(preferences?: { mode?: 'review' | 'original' | 'final' | 'off'; enabled?: boolean }) { const normalized = preferences && Object.keys(preferences).length ? { ...preferences } : undefined; @@ -1956,8 +1954,8 @@ export class SuperDoc extends EventEmitter { * returns the array of matches the underlying search command produced * (possibly empty). * - * @param {string | RegExp} text The text or regex to search for - * @returns {import('./types/index.js').SearchMatch[] | undefined} The search results + * @param text The text or regex to search for + * @returns The search results */ search(text: string | RegExp): SearchMatch[] | undefined { return this.activeEditor?.commands.search(text, { searchModel: 'visible' }); @@ -1970,8 +1968,8 @@ export class SuperDoc extends EventEmitter { * runtime resolves its current document position via the embedded * tracker ids. * - * @param {import('./types/index.js').SearchMatch} match The match object returned by `superdoc.search()`. - * @returns {boolean | undefined} Whether the command dispatched, or `undefined` if no active editor. + * @param match The match object returned by `superdoc.search()`. + * @returns Whether the command dispatched, or `undefined` if no active editor. */ goToSearchResult(match: SearchMatch) { return this.activeEditor?.commands.goToSearchResult(match); @@ -1979,7 +1977,7 @@ export class SuperDoc extends EventEmitter { /** * Get the current zoom level as a percentage (e.g., 100 for 100%) - * @returns {number} The current zoom level as a percentage + * @returns The current zoom level as a percentage * @example * const zoom = superdoc.getZoom(); // Returns 100, 150, 200, etc. */ @@ -1991,7 +1989,7 @@ export class SuperDoc extends EventEmitter { * Set the zoom level for all documents. * Updates the centralized activeZoom state, which propagates to all * presentation editors, PDF viewers, and whiteboard layers via the Vue watcher. - * @param {number} percent - The zoom level as a percentage (e.g., 100, 150, 200) + * @param percent - The zoom level as a percentage (e.g., 100, 150, 200) * @example * superdoc.setZoom(150); // Set zoom to 150% * superdoc.setZoom(50); // Set zoom to 50% @@ -2031,7 +2029,7 @@ export class SuperDoc extends EventEmitter { /** * Get the HTML content of all editors - * @returns {Array} The HTML content of all editors + * @returns The HTML content of all editors */ getHTML(options: Parameters[0] = {}) { const editors: Editor[] = []; @@ -2048,8 +2046,8 @@ export class SuperDoc extends EventEmitter { /** * Lock the current superdoc and emit the `locked` event. * - * @param {boolean} [isLocked] Whether the superdoc is locked. Defaults to `false`. - * @param {User | null} [lockedBy] The user who locked the superdoc, or `null` + * @param [isLocked] Whether the superdoc is locked. Defaults to `false`. + * @param [lockedBy] The user who locked the superdoc, or `null` * when unlocking (or when no user is known). Defaults to `null`. */ lockSuperdoc(isLocked: boolean = false, lockedBy: User | null = null): void { @@ -2061,7 +2059,7 @@ export class SuperDoc extends EventEmitter { /** * Export the superdoc to a file - * @param {ExportParams} params - Export configuration + * @param params - Export configuration */ async export( { @@ -2111,7 +2109,7 @@ export class SuperDoc extends EventEmitter { /** * Export editors to DOCX format. - * @param {{ commentsType?: string, isFinalDoc?: boolean, fieldsHighlightColor?: string | null }} [options] + * @param [options] */ async exportEditorsToDOCX({ commentsType, @@ -2201,7 +2199,7 @@ export class SuperDoc extends EventEmitter { /** * Request an immediate save from all collaboration documents - * @returns {Promise} Resolves when all documents have saved + * @returns Resolves when all documents have saved */ async #triggerCollaborationSaves() { this.#log('🦋 [superdoc] Triggering collaboration saves'); @@ -2214,7 +2212,7 @@ export class SuperDoc extends EventEmitter { this.pendingCollaborationSaves++; this.#log(`After increment - Doc ${index}: pending = ${this.pendingCollaborationSaves}`); const metaMap = doc.ydoc.getMap('meta'); - metaMap.observe((/** @type {import('yjs').YMapEvent} */ event) => { + metaMap.observe((event: Y.YMapEvent) => { if (event.changes.keys.has('immediate-save-finished')) { this.pendingCollaborationSaves--; if (this.pendingCollaborationSaves <= 0) { @@ -2285,7 +2283,6 @@ export class SuperDoc extends EventEmitter { /** * Open a surface (dialog or floating) above the document content. * - * @template [TResult=unknown] */ openSurface(request: SurfaceRequest): SurfaceHandle { return this.#surfaceManager.open(request) as SurfaceHandle; diff --git a/packages/superdoc/src/core/types/index.ts b/packages/superdoc/src/core/types/index.ts index 6674145a2b..cf3835b6a8 100644 --- a/packages/superdoc/src/core/types/index.ts +++ b/packages/superdoc/src/core/types/index.ts @@ -1759,8 +1759,8 @@ export interface Config { * call sites cast `this.config` to this type so they can access these * invariants without per-site null guards. * - * Use this from internal SuperDoc callsites that need the augmented shape - * (e.g. `/** @type {InternalConfig} *\/ (this.config).socket = ...`). + * Use this from internal SuperDoc callsites that need the augmented + * shape, e.g. `(this.config as InternalConfig).socket = ...`. */ export interface InternalConfig extends Config { /**