Skip to content

Commit

Permalink
Convert tsdoc annotations to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
jimrandomh committed May 3, 2024
1 parent c9aac5b commit c104ac5
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 261 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// @ts-check
import { Command, Plugin } from '@ckeditor/ckeditor5-core';
import { Command, Plugin, Editor } from '@ckeditor/ckeditor5-core';
import { ButtonView } from '@ckeditor/ckeditor5-ui';
import { Widget, toWidgetEditable, toWidget } from '@ckeditor/ckeditor5-widget';
import { ELEMENTS as FOOTNOTE_ELEMENTS } from '../ckeditor5-footnote/src/constants';
import type { DowncastWriter, Element, Conversion, Model } from '@ckeditor/ckeditor5-engine';
import type RootElement from '@ckeditor/ckeditor5-engine/src/model/rootelement';
import type ContainerElement from '@ckeditor/ckeditor5-engine/src/view/containerelement';
import type { DowncastConversionApi } from '@ckeditor/ckeditor5-engine/src/conversion/downcastdispatcher';

type DialoguesConfig = AnyBecauseTodo;

Expand All @@ -17,9 +20,6 @@ export default class DialogueCommentBox extends Plugin {
*/
class SimpleBoxUI extends Plugin {
init() {
/**
* @type {EditorWithUI}
*/
const editor = this.editor;
const t = editor.t;

Expand Down Expand Up @@ -375,25 +375,7 @@ class SubmitDialogueMessageCommand extends Command {
}
}

/**
* @typedef {import('@ckeditor/ckeditor5-core/src/editor/editorwithui').EditorWithUI} EditorWithUI
* @typedef {import('@ckeditor/ckeditor5-core/src/editor/editor').default} Editor
* @typedef {import('@ckeditor/ckeditor5-engine').DowncastWriter} DowncastWriter
* @typedef {import('@ckeditor/ckeditor5-engine/src/model/writer').default} ModelWriter
* @typedef {Exclude<ReturnType<import('@ckeditor/ckeditor5-engine').Model['document']['getRoot']>, null>} RootElement
* @typedef {import('@ckeditor/ckeditor5-engine').Element} Element
* @typedef {import('@ckeditor/ckeditor5-engine/src/model/text').default} Text
* @typedef {import('@ckeditor/ckeditor5-engine/src/view/containerelement').default} ContainerElement
* @typedef {Exclude<Parameters<ReturnType<import('@ckeditor/ckeditor5-engine').Conversion['for']>['elementToElement']>[0], undefined>['view']} ViewElementDefinition
* @typedef {Extract<ViewElementDefinition, (_0, _1) => ContainerElement>} ContainerElementDefinitionGenerator
*/

/**
* @param {DowncastWriter} viewWriter
* @param {Record<string, any>} buttonAttributes
* @param {Editor | EditorWithUI} editor
*/
function createButtonElement(viewWriter, buttonAttributes, editor) {
function createButtonElement(viewWriter: DowncastWriter, buttonAttributes: Record<string,any>, editor: Editor) {
return viewWriter.createUIElement('button', buttonAttributes, function (domDocument) {
const domElement = this.toDomElement(domDocument);
domElement.contentEditable = 'false';
Expand All @@ -404,13 +386,7 @@ function createButtonElement(viewWriter, buttonAttributes, editor) {
});
}

/**
* @param {DowncastWriter} viewWriter
* @param {string} elementName
* @param {Record<string, any>} headerAttributes
* @param {string} userDisplayName
*/
function createHeaderElement(viewWriter, elementName, headerAttributes, userDisplayName) {
function createHeaderElement(viewWriter: DowncastWriter, elementName: string, headerAttributes: Record<string,any>, userDisplayName: string) {
return viewWriter.createUIElement(elementName, headerAttributes, function (domDocument) {
const domElement = this.toDomElement(domDocument);
domElement.contentEditable = 'false';
Expand All @@ -420,10 +396,7 @@ function createHeaderElement(viewWriter, elementName, headerAttributes, userDisp
});
}

/**
* @param {RootElement} root
*/
function findMessageInputs(root) {
function findMessageInputs(root: RootElement) {
const rootChildren = Array.from(root.getChildren());
// For backwards compatibility, when we didn't have a wrapper around the message inputs
const rootInputs = rootChildren.filter((child: AnyBecauseTodo) => child.is('element', 'dialogueMessageInput'));
Expand All @@ -435,23 +408,18 @@ function findMessageInputs(root) {
return [...rootInputs, ...wrapperInputs];
}

/**
*
* @param {string} className
* @param {string[]} attributeList
* @returns {ContainerElementDefinitionGenerator}
*/
function getDataDowncastViewGenerator(className, attributeList) {
function getDataDowncastViewGenerator(className: string, attributeList: string[]) {
return (modelElement, { writer: viewWriter }) => {
const sectionAttributes = Object.fromEntries(attributeList.map(attribute => [attribute, modelElement.getAttribute(attribute)]));
return viewWriter.createContainerElement('section', { class: className, ...sectionAttributes });
};
}

/**
* @type {ContainerElementDefinitionGenerator}
*/
function inputEditingDowncastViewGenerator(modelElement, { writer: viewWriter }) {
function inputEditingDowncastViewGenerator(
this: SimpleBoxEditing,
modelElement: Element,
{ writer: viewWriter }: DowncastConversionApi
): ContainerElement {
const editor = this.editor;

const buttonAttributes = { type: 'button', class: 'CommentsNewForm-formButton MuiButton-root MuiButtonBase-root' };
Expand All @@ -464,18 +432,18 @@ function inputEditingDowncastViewGenerator(modelElement, { writer: viewWriter })
const userOrder = getUserOrder(modelElement);
const userId = modelElement.getAttribute('user-id');
const sectionAttributes = { class: 'dialogue-message-input ContentStyles-debateResponseBody', 'user-order': userOrder, 'user-id': userId, 'display-name': userDisplayName };
const section = viewWriter.createContainerElement( 'section', sectionAttributes );
const section = viewWriter.createContainerElement( 'section', sectionAttributes ) as AnyBecauseTodo;

viewWriter.insert(viewWriter.createPositionAt(section, 0), button);
viewWriter.insert(viewWriter.createPositionAt(section, 0), headerElement);

return toWidgetEditable(section, viewWriter);
}

/**
* @type {ContainerElementDefinitionGenerator}
*/
function messageEditingDowncastViewGenerator(modelElement, { writer: viewWriter }) {
function messageEditingDowncastViewGenerator(
modelElement: Element,
{ writer: viewWriter }: DowncastConversionApi
) {
const userOrder = getUserOrder(modelElement);
const sectionAttributes = { class: 'dialogue-message ContentStyles-debateResponseBody', 'user-order': userOrder };
const section = viewWriter.createContainerElement( 'section', sectionAttributes );
Expand All @@ -492,24 +460,18 @@ function messageEditingDowncastViewGenerator(modelElement, { writer: viewWriter
return toWidget(section, viewWriter, { hasSelectionHandle: true });
}

/**
* @type {ContainerElementDefinitionGenerator}
*/
function messageContentDowncastViewGenerator(modelElement, { writer: viewWriter }) {
function messageContentDowncastViewGenerator(
modelElement: Element,
{ writer: viewWriter }: DowncastConversionApi
) {
const contentElement = viewWriter.createEditableElement('div', { class: 'dialogue-message-content' });
return toWidgetEditable(contentElement, viewWriter);
}

/**
* @param {Element} modelElement
*/
function getUserOrder(modelElement) {
function getUserOrder(modelElement: Element) {
return (modelElement.getAttribute('user-order') || '1').toString();
}

/**
* @param {Element} modelElement
*/
function getUserDisplayName(modelElement) {
function getUserDisplayName(modelElement: Element) {
return (modelElement.getAttribute('display-name') || '').toString();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check (uses JSDoc types for type checking)

import inlineAutoformatEditing from '@ckeditor/ckeditor5-autoformat/src/inlineautoformatediting';
import { Editor } from '@ckeditor/ckeditor5-core';
import Element from '@ckeditor/ckeditor5-engine/src/model/element';
Expand All @@ -8,19 +6,18 @@ import TextProxy from '@ckeditor/ckeditor5-engine/src/model/textproxy';
import Range from '@ckeditor/ckeditor5-engine/src/view/range';
import { modelQueryElement, modelQueryElementsAll } from '../utils';
import { COMMANDS, ELEMENTS } from '../constants';
import type Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';

/**
* Adds functionality to support creating footnotes using markdown syntax, e.g. `[^1]`.
* @param {Editor} editor
* @param {Element} rootElement
*/
export const addFootnoteAutoformatting = (editor, rootElement) => {
export const addFootnoteAutoformatting = (editor: Editor, rootElement: Element) => {
if(editor.plugins.has('Autoformat')) {
const autoformatPluginInstance = editor.plugins.get('Autoformat');
const autoformatPluginInstance = editor.plugins.get('Autoformat') as Autoformat;
inlineAutoformatEditing(editor, autoformatPluginInstance,
text => regexMatchCallback(editor, text),
// @ts-ignore Pretty sure definitely typed is wrong
(_, /**@type Range[]*/ ranges) => formatCallback(ranges, editor, rootElement)
(_, ranges: Range[]) => formatCallback(ranges, editor, rootElement)
);
}
}
Expand All @@ -40,12 +37,11 @@ export const addFootnoteAutoformatting = (editor, rootElement) => {
* matched text, while passing the range of the numeric text on to the formatting callback.
*
* If 0 or more than 1 match is found, it returns empty ranges for both format and remove, which is a no-op.
*
* @param {Editor} editor
* @param {string} text
* @returns {{remove: [number, number][], format: [number, number][]}}
*/
const regexMatchCallback = (editor, text) => {
const regexMatchCallback = (editor: Editor, text: string): {
remove: [number, number][],
format: [number, number][]
} => {
const selectionStart = editor.model.document.selection.anchor;
// get the text node containing the cursor's position, or the one ending at `the cursor's position
const surroundingText = selectionStart && (selectionStart.textNode || selectionStart.getShiftedBy(-1).textNode);
Expand Down Expand Up @@ -87,13 +83,8 @@ const regexMatchCallback = (editor, text) => {
*
* Footnotes only get inserted if the matching range is an integer between 1
* and the number of existing footnotes + 1.
*
* @param {Range[]} ranges
* @param {Editor} editor
* @param {Element} rootElement
* @returns {boolean|void}
*/
const formatCallback = (ranges, editor, rootElement) => {
const formatCallback = (ranges: Range[], editor: Editor, rootElement: Element): boolean|undefined => {
const command = editor.commands.get(COMMANDS.insertFootnote);
if(!command || !command.isEnabled) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ import { ATTRIBUTES, CLASSES, ELEMENTS } from '../constants';

/**
* Defines methods for converting between model, data view, and editing view representations of each element type.
* @param {Editor} editor
* @returns {void}
* */
export const defineConverters = (editor) => {
*/
export const defineConverters = (editor: Editor): void => {
const conversion = editor.conversion;

/***********************************Attribute Conversion************************************/
Expand Down Expand Up @@ -237,11 +235,8 @@ export const defineConverters = (editor) => {
* Creates and returns a view element for a footnote backlink,
* which navigates back to the inline reference in the text. Used
* for both data and editing downcasts.
* @param {ModelElement} modelElement
* @param {DowncastConversionApi} conversionApi
* @returns {ContainerElement}
*/
function createFootnoteBackLinkViewElement(modelElement, conversionApi) {
function createFootnoteBackLinkViewElement(modelElement: ModelElement, conversionApi: DowncastConversionApi): ContainerElement {
const viewWriter = conversionApi.writer;
const id = `${modelElement.getAttribute(ATTRIBUTES.footnoteId)}`;
if(id === undefined) {
Expand Down Expand Up @@ -269,11 +264,8 @@ function createFootnoteBackLinkViewElement(modelElement, conversionApi) {
/**
* Creates and returns a view element for an inline footnote reference. Used for both
* data downcast and editing downcast conversions.
* @param {ModelElement} modelElement
* @param {DowncastConversionApi} conversionApi
* @returns {ContainerElement}
*/
function createFootnoteReferenceViewElement(modelElement, conversionApi) {
function createFootnoteReferenceViewElement(modelElement: ModelElement, conversionApi: DowncastConversionApi): ContainerElement {
const viewWriter = conversionApi.writer;
const index = `${modelElement.getAttribute(ATTRIBUTES.footnoteIndex)}`;
const id = `${modelElement.getAttribute(ATTRIBUTES.footnoteId)}`;
Expand Down Expand Up @@ -306,11 +298,8 @@ function createFootnoteReferenceViewElement(modelElement, conversionApi) {
/**
* Creates and returns a view element for an inline footnote reference. Used for both
* data downcast and editing downcast conversions.
* @param {ModelElement} modelElement
* @param {DowncastConversionApi} conversionApi
* @returns {ContainerElement}
*/
function createFootnoteItemViewElement(modelElement, conversionApi) {
function createFootnoteItemViewElement(modelElement: ModelElement, conversionApi: DowncastConversionApi): ContainerElement {
const viewWriter = conversionApi.writer;
const index = modelElement.getAttribute(ATTRIBUTES.footnoteIndex);
const id = modelElement.getAttribute(ATTRIBUTES.footnoteId);
Expand All @@ -331,22 +320,19 @@ function createFootnoteItemViewElement(modelElement, conversionApi) {
});
}

/**
* @typedef {Object} Data
* @property {ModelElement} item
* @property {string} attributeOldValue
* @property {string} attributeNewValue
*/

/**
* Triggers when the index attribute of a footnote changes, and
* updates the editor display of footnote references accordingly.
* @param {Data} data
* @param {DowncastConversionApi} conversionApi
* @param {Editor} editor
* @returns
*/
function updateFootnoteReferenceView (data, conversionApi, editor) {
function updateFootnoteReferenceView (
data: {
item: ModelElement,
attributeOldValue: string,
attributeNewValue: string,
},
conversionApi: DowncastConversionApi,
editor: Editor
) {
const { item, attributeNewValue: newIndex } = data;
if (!(item instanceof ModelElement) || !conversionApi.consumable.consume(item, `attribute:${ATTRIBUTES.footnoteIndex}:${ELEMENTS.footnoteReference}`)) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export default class FootnoteEditing extends Plugin {
}

/**
* @type {RootElement} The root element of the document.
* The root element of the document.
*/
get rootElement() {
get rootElement(): RootElement {
const rootElement = this.editor.model.document.getRoot();
if(!rootElement) {
throw new Error('Document has no rootElement element.');
Expand Down Expand Up @@ -153,9 +153,8 @@ export default class FootnoteEditing extends Plugin {
* a footnote without deleting it. modelWriter is passed in to
* batch these changes with the ones that instantiated them,
* such that the set can be undone with a single action.
* @param {ModelElement} footnoteContent
*/
_clearContents(modelWriter, footnoteContent) {
_clearContents(modelWriter: ModelWriter, footnoteContent: ModelElement) {
const contents = modelWriter.createRangeIn(footnoteContent);
modelWriter.appendElement("paragraph", footnoteContent);
modelWriter.remove(contents);
Expand All @@ -166,10 +165,8 @@ export default class FootnoteEditing extends Plugin {
* id attribute changes, it's references automatically update from a dispatcher event in converters.js,
* which triggers the `updateReferenceIds` method. modelWriter is passed in to batch these changes with
* the ones that instantiated them, such that the set can be undone with a single action.
* @param {ModelWriter} modelWriter
* @param {ModelElement} footnote
*/
_removeFootnote(modelWriter, footnote) {
_removeFootnote(modelWriter: ModelWriter, footnote: ModelElement) {
// delete the current footnote and its references,
// and renumber subsequent footnotes.
if(!this.editor) {
Expand Down Expand Up @@ -222,11 +219,9 @@ export default class FootnoteEditing extends Plugin {
* Deletes all references to the footnote with the given id. If no id is provided,
* all references are deleted. modelWriter is passed in to batch these changes with
* the ones that instantiated them, such that the set can be undone with a single action.
* @param {ModelWriter} modelWriter
* @param {string|undefined} footnoteId
*/
_removeReferences(modelWriter, footnoteId=undefined) {
const removeList = [];
_removeReferences(modelWriter: ModelWriter, footnoteId: string|undefined=undefined) {
const removeList: AnyBecauseTodo[] = [];
if(!this.rootElement) throw new Error('Document has no root element.');
const footnoteReferences = modelQueryElementsAll(this.editor, this.rootElement, e => e.is('element', ELEMENTS.footnoteReference));
footnoteReferences.forEach((footnoteReference) => {
Expand All @@ -245,11 +240,8 @@ export default class FootnoteEditing extends Plugin {
* the index attribute of an existing footnote changes, which happens when a footnote
* with a lower index is deleted. batch is passed in to group these changes with
* the ones that instantiated them.
* @param {Batch} batch
* @param {string} footnoteId
* @param {string} newFootnoteIndex
*/
_updateReferenceIndices(batch, footnoteId, newFootnoteIndex) {
_updateReferenceIndices(batch: Batch, footnoteId: string, newFootnoteIndex: string) {
const footnoteReferences = modelQueryElementsAll(
this.editor,
this.rootElement,
Expand All @@ -266,9 +258,8 @@ export default class FootnoteEditing extends Plugin {
* Reindexes footnotes such that footnote references occur in order, and reorders
* footnote items in the footer section accordingly. batch is passed in to group changes with
* the ones that instantiated them.
* @param {Batch} batch
*/
_orderFootnotes(batch) {
_orderFootnotes(batch: Batch) {
const footnoteReferences = modelQueryElementsAll(this.editor, this.rootElement, e => e.is('element', ELEMENTS.footnoteReference));
const uniqueIds = new Set(footnoteReferences.map(e => e.getAttribute(ATTRIBUTES.footnoteId)));
const orderedFootnotes = [...uniqueIds].map(id => (
Expand Down

0 comments on commit c104ac5

Please sign in to comment.