Skip to content

Commit 1d98952

Browse files
rtibblesclaude
andcommitted
Remediate JSDoc violations in remaining plugins
Covers epub_viewer, qti_viewer, and user_auth. Strips a stray period on a URL in qti and fills the few missing JSDoc descriptions and @param descriptions to satisfy the new rules. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9f3aa7d commit 1d98952

12 files changed

Lines changed: 125 additions & 92 deletions

File tree

kolibri/plugins/epub_viewer/frontend/views/SearchSideBar.vue

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@
9696
* Searches through an entire book for a string, but caps after a certain amount of results is
9797
* exceeded
9898
* Helpful in preventing a CPU lockup for search queries with a lot of search results
99-
* @param {object} book Ebookjs book object
100-
* @param {string} searchQuery String to search for
101-
* @param {number} maxSearchResults Stop searching for matches after this is amount is exceeded,
99+
* @param {object} book - Epubjs book object
100+
* @param {string} searchQuery - String to search for
101+
* @param {number} maxSearchResults - Stop searching for matches after this is amount is exceeded,
102102
* e.g. 1000
103103
* @returns {Promise} A promise that resolves to the search results
104104
*/
@@ -174,6 +174,7 @@
174174
},
175175
methods: {
176176
/**
177+
* Move keyboard focus to the search input so the user can start typing.
177178
* @public
178179
*/
179180
focusOnInput() {
@@ -201,8 +202,8 @@
201202
/**
202203
* This method "marks" the match text to which the cfi refers in every result in the
203204
* search results list
204-
* @param {array} searchResults
205-
* @returns {array} searchResults with the excerpt split into before, match, and after
205+
* @param {Array} searchResults - Raw search results returned by the epub search
206+
* @returns {Array} searchResults with the excerpt split into before, match, and after
206207
* where the match is the text that will be highlighted
207208
*/
208209
selectMatchResult(searchResults) {
@@ -232,10 +233,10 @@
232233
* Identify the index of the match in the result excerpt based
233234
* on the distance between the cfis with the next result compared to
234235
* the distance of the result excerpt between a match and the next match.
235-
* @param {object} params
236-
* @param {string[]} params.textSplit The result excerpt split by the search query
237-
* @param {string} params.cfi The cfi of the current result
238-
* @param {object} params.nextResult The next result
236+
* @param {object} params - Arguments bundled as a single object
237+
* @param {string[]} params.textSplit - The result excerpt split by the search query
238+
* @param {string} params.cfi - The cfi of the current result
239+
* @param {object} params.nextResult - The result that immediately follows the current one
239240
* @returns {number} The index of the match in the result excerpt
240241
* @example If there are n matches in the same result excerpt, this method will
241242
* return 0 if the cfi refers to the first match, 1 for the second match, etc.
@@ -266,8 +267,8 @@
266267
* If two matches appears in the same result excerpt then they are in the same node.
267268
* So, this method finds the distance between the two matches and return -1 if they are
268269
* not in the same node.
269-
* @param {string} cfi1 The cfi of the first match
270-
* @param {string} cfi2 The cfi of the second match after the first one
270+
* @param {string} cfi1 - The cfi of the first match
271+
* @param {string} cfi2 - The cfi of the second match after the first one
271272
* @returns {number} The number of characters between the two matches or -1 if they are
272273
* not in the same node.
273274
*/
@@ -301,10 +302,10 @@
301302
/**
302303
* Divide the excerpt into before, match, and after based on the index of the match
303304
* where the match is the text that will be highlighted
304-
* @param {object} params
305-
* @param {string[]} params.textSplit The result excerpt split by the search query
306-
* @param {string} params.excerpt The result excerpt
307-
* @param {number} params.selectedIndex The index of the match in the result excerpt
305+
* @param {object} params - Arguments bundled as a single object
306+
* @param {string[]} params.textSplit - The result excerpt split by the search query
307+
* @param {string} params.excerpt - The result excerpt
308+
* @param {number} params.selectedIndex - The index of the match in the result excerpt
308309
* @returns {object} The excerpt divided into before, match, and after
309310
*/
310311
splitExcerpt({ textSplit, excerpt, selectedIndex }) {

kolibri/plugins/epub_viewer/frontend/views/TopBar.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,18 +84,21 @@
8484
},
8585
methods: {
8686
/**
87+
* Moves keyboard focus to the table of contents button.
8788
* @public
8889
*/
8990
focusOnTocButton() {
9091
this.$refs.tocButton.$el.focus();
9192
},
9293
/**
94+
* Moves keyboard focus to the settings button.
9395
* @public
9496
*/
9597
focusOnSettingsButton() {
9698
this.$refs.settingsButton.$el.focus();
9799
},
98100
/**
101+
* Moves keyboard focus to the search button.
99102
* @public
100103
*/
101104
focusOnSearchButton() {

kolibri/plugins/pdf_viewer/frontend/utils/event_utils.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,33 @@ class EventBus {
77

88
/**
99
* Proxy to the Vue object that is the global dispatcher.
10-
* @param {string} eventName
11-
* @param {...any} args
10+
* @param {string} eventName - Name of the event to emit.
11+
* @param {...unknown} args - Payload arguments forwarded to listeners.
1212
*/
1313
emit(eventName, ...args) {
1414
this._eventDispatcher.$emit(eventName, ...args);
1515
}
1616
/**
1717
* Proxy to the Vue object that is the global dispatcher.
18-
* @param {string} event
19-
* @param {function} callback
18+
* @param {string} event - Name of the event to subscribe to.
19+
* @param {Function} callback - Listener invoked when the event fires.
2020
*/
2121
on(event, callback) {
2222
this._eventDispatcher.$on(event, callback);
2323
}
2424
/**
2525
* Proxy to the Vue object that is the global dispatcher.
2626
* Takes any arguments and passes them on.
27-
* @param {string} event
28-
* @param {function} callback
27+
* @param {string} event - Name of the event to subscribe to once.
28+
* @param {Function} callback - Listener invoked once when the event fires.
2929
*/
3030
once(event, callback) {
3131
this._eventDispatcher.$once(event, callback);
3232
}
3333
/**
3434
* Proxy to the Vue object that is the global dispatcher.
35-
* @param {string} event
36-
* @param {function} callback
35+
* @param {string} event - Name of the event to unsubscribe from.
36+
* @param {Function} callback - The previously-subscribed listener to remove.
3737
*/
3838
off(event, callback) {
3939
this._eventDispatcher.$off(event, callback);

kolibri/plugins/pdf_viewer/frontend/utils/text_layer_builder.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,13 @@ const logging = logger.getLogger(__filename);
3030
const EXPAND_DIVS_TIMEOUT = 300; // ms
3131

3232
/**
33-
* @typedef {Object} TextLayerBuilderOptions
34-
* @property {HTMLDivElement} textLayerDiv - The text layer container.
35-
* @property {number} pageIndex - The page index.
36-
* @property {PageViewport} viewport - The viewport of the text layer.
37-
* @property {TextHighlighter} highlighter - Optional object that will handle
38-
* highlighting text from the find controller.
39-
* @property {boolean} enhanceTextSelection - Option to turn on improved
40-
* text selection.
33+
* @typedef {object} TextLayerBuilderOptions
34+
* @property {HTMLDivElement} textLayerDiv - The text layer container DOM node.
35+
* @property {number} pageIndex - Zero-based PDF page index.
36+
* @property {object} viewport - The pdf.js PageViewport for the text layer.
37+
* @property {?object} highlighter - Optional pdf.js TextHighlighter that will handle
38+
* highlighting text from the find controller.
39+
* @property {boolean} enhanceTextSelection - Option to turn on improved text selection.
4140
*/
4241

4342
/**
@@ -71,6 +70,8 @@ class TextLayerBuilder {
7170
}
7271

7372
/**
73+
* Mark rendering as complete and emit `textlayerrendered` once any post-render
74+
* teardown has run.
7475
* @private
7576
*/
7677
_finishRendering() {
@@ -95,7 +96,6 @@ class TextLayerBuilder {
9596

9697
/**
9798
* Renders the text layer.
98-
*
9999
* @param {number} [timeout] - Wait for a specified amount of milliseconds
100100
* before rendering.
101101
*/
@@ -190,7 +190,6 @@ class TextLayerBuilder {
190190
* Improves text selection by adding an additional div where the mouse was
191191
* clicked. This reduces flickering of the content if the mouse is slowly
192192
* dragged up or down.
193-
*
194193
* @private
195194
*/
196195
_bindMouse() {

kolibri/plugins/pdf_viewer/frontend/views/PdfRendererIndex.vue

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,8 @@
527527
* - https://github.com/mozilla/pdf.js/blob/v2.14.305/web/pdf_link_service.js#L237
528528
* - https://github.com/mozilla/pdf.js/blob/v2.14.305/web/pdf_link_service.js#L176
529529
* - https://github.com/mozilla/pdf.js/blob/v2.14.305/web/base_viewer.js#L1175
530+
* @param {string|Array} dest - A named destination string or an explicit
531+
* destination array as defined by the PDF specification.
530532
*/
531533
goToDestination(dest) {
532534
if (!this.pdfDocument) {
@@ -602,7 +604,11 @@
602604
);
603605
},
604606
/**
605-
* Focus a given pdf page and return true if the page was already rendered
607+
* Focus a given pdf page and return true if the page was already rendered.
608+
* @param {number} pageNumber - 1-based index of the page to focus.
609+
* @param {HTMLElement} bookmark - The bookmark element to return focus to
610+
* when the user shift-enters out of the page.
611+
* @returns {boolean} True if the page was rendered and successfully focused.
606612
*/
607613
focusPage(pageNumber, bookmark) {
608614
const page = document.querySelector('#pdf-page-' + pageNumber);
@@ -630,6 +636,11 @@
630636
* Get the page number from the explicit destination array.
631637
* Adaptation of the original function from pdf.js:
632638
* - https://github.com/mozilla/pdf.js/blob/v2.14.305/web/pdf_link_service.js#L181
639+
* @param {Array} explicitDest - Explicit destination array as defined by the
640+
* PDF specification; the first element is either a page reference object or
641+
* a numeric page index.
642+
* @returns {Promise<number|undefined>} Resolves to the 1-based page number,
643+
* or undefined when it cannot be determined.
633644
*/
634645
getDestinationPageNumber(explicitDest) {
635646
return new Promise(resolve => {

kolibri/plugins/perseus_viewer/frontend/views/PerseusRendererIndex.vue

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,17 @@
8383
* from the same file, but with different URLs. This also allows us to only monkey patch the Util
8484
* functions once, as it gives us a global register and prevents duelling components from
8585
* overriding each other.
86-
*
87-
* @type {
88-
* Object.<string, {zipFile: ZipFile, usageCounter: number, imageUrls: Object.<string, string>}>
89-
* }
90-
*
86+
* @type {{
87+
* [key: string]: {
88+
* zipFile: ZipFile,
89+
* usageCounter: number,
90+
* imageUrls: {[key: string]: string},
91+
* },
92+
* }}
9193
* @property {ZipFile} zipFile - A ZipFile object for the Perseus file.
9294
* @property {number} usageCounter - The number of components using this object.
93-
* @property {Object.<string, string>} imageUrls - A lookup object mapping from the image filename
94-
* to the URL generated for that image for display.
95+
* @property {{[key: string]: string}} imageUrls - A lookup object mapping from the image
96+
* filename to the URL generated for that image for display.
9597
*/
9698
const globalPerseusFileRegistry = {};
9799
@@ -601,6 +603,10 @@
601603
}
602604
},
603605
/**
606+
* Score the current answer state through the Perseus item renderer and
607+
* return the result, or null when the renderer is not yet ready.
608+
* @returns {?{correct: boolean, answerState: object, simpleAnswer: string}}
609+
* The check result, or null when no answer can be checked.
604610
* @public
605611
*/
606612
checkAnswer() {
@@ -640,6 +646,7 @@
640646
}
641647
},
642648
/**
649+
* Reveal the next hint and emit the updated answer state.
643650
* @public
644651
*/
645652
takeHint() {

kolibri/plugins/qti_viewer/frontend/components/AssessmentItem.vue

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,21 @@
2222
import TextEntryInteraction from './interactions/TextEntryInteraction.vue';
2323
2424
/**
25-
* Extract QTI declarations of a specific type from an XML document
26-
* @param {Document} xmlDocument - The QTI XML document
27-
* @param {string} declarationType - 'response', 'outcome', or 'context'
28-
* @param {Function} interactionHandler - a function that is called when a variable value is set
29-
* @param {Ref{Object}} injectedAnswerState - a computed ref that contains any injected answers
30-
* @returns {Object} Map of identifier -> QTIVariable
25+
* Extract QTI declarations of a specific type from an XML document.
26+
* @param {Document} xmlDocument - The QTI XML document.
27+
* @param {string} declarationType - 'response', 'outcome', or 'context'.
28+
* @param {Function} interactionHandler - A function called when a variable value is set.
29+
* @returns {object} Map of identifier to QTIVariable.
3130
*/
32-
function getQTIDeclarations(xmlDocument, declarationType, interactionHander) {
31+
function getQTIDeclarations(xmlDocument, declarationType, interactionHandler) {
3332
const declarations = {};
3433
3534
const selector = `qti-${declarationType}-declaration`;
3635
3736
const nodes = xmlDocument.querySelectorAll(selector);
3837
3938
for (const node of nodes) {
40-
const variable = new QTIVariable(node, interactionHander);
39+
const variable = new QTIVariable(node, interactionHandler);
4140
declarations[variable.identifier] = variable;
4241
}
4342
return declarations;

kolibri/plugins/qti_viewer/frontend/components/interactions/ChoiceInteraction.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
/**
2424
* Safely normalizes a response value to an array.
2525
* Handles null, undefined, scalars, and arrays uniformly.
26+
* @param {string|number|Array<string|number>|null|undefined} value - The QTI response
27+
* value, which may be a single identifier, an array of identifiers, or empty.
28+
* @returns {Array<string|number>} An array of selected identifiers (empty when value is empty).
2629
*/
2730
function getSelectionsArray(value) {
2831
if (value === null || value === undefined) {

kolibri/plugins/qti_viewer/frontend/utils/props.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,28 @@ import { coerceNumber, validateNumber, validateBoolean } from './qti/values';
44
const QTI_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_-]{0,31}$/;
55

66
/**
7-
* Validates QTI identifier format
8-
* @param {string|null} value - The value to validate
9-
* @returns {boolean} - True if valid QTI identifier or null
7+
* Validates QTI identifier format.
8+
* @param {string|null} value - The value to validate.
9+
* @returns {boolean} - True if valid QTI identifier or null.
1010
*/
1111
const validateQTIIdentifier = value => {
1212
return QTI_IDENTIFIER_PATTERN.test(value);
1313
};
1414

1515
/**
16-
* Validates non-negative integer
17-
* @param {string|number|null} value - The value to validate
18-
* @returns {boolean} - True if non-negative integer or null
16+
* Validates non-negative integer.
17+
* @param {string|number|null} value - The value to validate.
18+
* @returns {boolean} - True if non-negative integer or null.
1919
*/
2020
const validateNonNegativeInt = value => {
2121
value = coerceNumber(value);
2222
return Number.isInteger(value) && value >= 0;
2323
};
2424

2525
/**
26-
* Creates an enum validator function
27-
* @param {Object} enumObject - The enum object to validate against
28-
* @returns {Function} Validator function
26+
* Creates an enum validator function.
27+
* @param {object} enumObject - The enum object to validate against.
28+
* @returns {Function} Validator function.
2929
*/
3030
const createEnumValidator = enumObject => {
3131
return value => Object.values(enumObject).includes(value);
@@ -48,11 +48,11 @@ const validateOrientation = createEnumValidator(Orientation);
4848

4949
// Common factory function for creating props
5050
/**
51-
* Creates a Vue prop configuration from a base prop object
52-
* @param {Object} baseProp - Base prop configuration (type, validator, etc.)
53-
* @param {boolean} required - Whether the prop is required (default: true)
54-
* @param {*} defaultValue - Default value (default: null when not required)
55-
* @returns {Object} Vue prop configuration
51+
* Creates a Vue prop configuration from a base prop object.
52+
* @param {object} baseProp - Base prop configuration (type, validator, etc.).
53+
* @param {boolean} required - Whether the prop is required (default: true).
54+
* @param {unknown} defaultValue - Default value (default: null when not required).
55+
* @returns {object} Vue prop configuration.
5656
*/
5757
const createProp = (baseProp, required = true, defaultValue) => {
5858
const prop = { ...baseProp };

0 commit comments

Comments
 (0)