Skip to content

Commit 8a25a90

Browse files
committed
add type annotations
1 parent 4664c22 commit 8a25a90

File tree

1 file changed

+170
-6
lines changed

1 file changed

+170
-6
lines changed

examples/rich-text-editor/rich_text_editor.js

Lines changed: 170 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
11
import Quill from "https://esm.sh/quill@2.0.3";
22
import { toMarkdown as mdastUtilToMarkdown } from "https://esm.sh/mdast-util-to-markdown@2.1.2";
33

4+
/**
5+
* @typedef {Object} QuillAttributes
6+
* @property {boolean} [bold] - Whether the text is bold.
7+
* @property {boolean} [italic] - Whether the text is italic.
8+
* @property {string} [link] - URL if the text is a link.
9+
* @property {number} [header] - Header level (1-3).
10+
* @property {string} [list] - List type ('ordered' or 'bullet').
11+
* @property {boolean} [blockquote] - Whether the text is in a blockquote.
12+
* @property {string} [code-block] - Code language if in a code block.
13+
* @property {string} [alt] - Alt text for images.
14+
*/
15+
16+
/**
17+
* @typedef {Object} QuillOperation
18+
* @property {string|Object} [insert] - Content to insert (string or object with image URL).
19+
* @property {number} [delete] - Number of characters to delete.
20+
* @property {number} [retain] - Number of characters to retain.
21+
* @property {QuillAttributes} [attributes] - Formatting attributes.
22+
*/
23+
24+
/**
25+
* @typedef {Object} QuillDelta
26+
* @property {Array<QuillOperation>} ops - Array of operations in the delta.
27+
*/
28+
429
/**
530
* Converts Quill Delta object to a Markdown string using mdast.
6-
* @param {object} delta - Quill Delta object (https://quilljs.com/docs/delta/).
31+
* @param {QuillDelta} delta - Quill Delta object (https://quilljs.com/docs/delta/).
732
* @returns {string} - Markdown representation.
833
*/
934
function deltaToMarkdown(delta) {
@@ -26,6 +51,11 @@ function deltaToMarkdown(delta) {
2651
}
2752
}
2853

54+
/**
55+
* Extracts plain text from a Quill Delta object.
56+
* @param {QuillDelta} delta - Quill Delta object.
57+
* @returns {string} - Plain text extracted from the delta.
58+
*/
2959
function extractPlainTextFromDelta(delta) {
3060
try {
3161
return delta.ops
@@ -60,7 +90,7 @@ function createAndReplaceTextarea(textarea) {
6090

6191
/**
6292
* Returns the toolbar options array configured for Markdown compatibility.
63-
* @returns {Array} - Quill toolbar options.
93+
* @returns {Array<Array<any>>} - Quill toolbar options.
6494
*/
6595
function getMarkdownToolbarOptions() {
6696
return [
@@ -75,7 +105,7 @@ function getMarkdownToolbarOptions() {
75105
/**
76106
* Initializes a Quill editor instance on a given div.
77107
* @param {HTMLDivElement} editorDiv - The div element for the editor.
78-
* @param {Array} toolbarOptions - The toolbar configuration.
108+
* @param {Array<Array<any>>} toolbarOptions - The toolbar configuration.
79109
* @param {string} initialValue - The initial content for the editor.
80110
* @returns {Quill} - The initialized Quill instance.
81111
*/
@@ -94,9 +124,10 @@ function initializeQuillEditor(editorDiv, toolbarOptions, initialValue) {
94124

95125
/**
96126
* Attaches a submit event listener to the form to update the hidden textarea.
97-
* @param {HTMLFormElement} form - The form containing the editor.
127+
* @param {HTMLFormElement|null} form - The form containing the editor.
98128
* @param {HTMLTextAreaElement} textarea - The original (hidden) textarea.
99129
* @param {Quill} quill - The Quill editor instance.
130+
* @returns {void}
100131
*/
101132
function updateTextareaOnSubmit(form, textarea, quill) {
102133
if (!form) {
@@ -113,13 +144,23 @@ function updateTextareaOnSubmit(form, textarea, quill) {
113144
});
114145
}
115146

147+
/**
148+
* Loads the Quill CSS stylesheet.
149+
* @returns {void}
150+
*/
116151
function loadQuillStylesheet() {
117152
const link = document.createElement("link");
118153
link.rel = "stylesheet";
119154
link.href = "https://esm.sh/quill@2.0.3/dist/quill.snow.css";
120155
document.head.appendChild(link);
121156
}
122157

158+
/**
159+
* Handles errors during editor initialization.
160+
* @param {HTMLTextAreaElement} textarea - The textarea that failed initialization.
161+
* @param {Error} error - The error that occurred.
162+
* @returns {void}
163+
*/
123164
function handleEditorInitError(textarea, error) {
124165
console.error("Failed to initialize Quill for textarea:", textarea, error);
125166
textarea.style.display = "";
@@ -129,6 +170,12 @@ function handleEditorInitError(textarea, error) {
129170
textarea.parentNode.insertBefore(errorMsg, textarea.nextSibling);
130171
}
131172

173+
/**
174+
* Sets up a single editor for a textarea.
175+
* @param {HTMLTextAreaElement} textarea - The textarea to replace with an editor.
176+
* @param {Array<Array<any>>} toolbarOptions - The toolbar configuration.
177+
* @returns {boolean} - Whether the setup was successful.
178+
*/
132179
function setupSingleEditor(textarea, toolbarOptions) {
133180
if (textarea.dataset.quillInitialized === "true") {
134181
return false;
@@ -152,6 +199,10 @@ function setupSingleEditor(textarea, toolbarOptions) {
152199
}
153200
}
154201

202+
/**
203+
* Initializes Quill editors for all textareas in the document.
204+
* @returns {void}
205+
*/
155206
function initializeEditors() {
156207
loadQuillStylesheet();
157208

@@ -177,9 +228,30 @@ function initializeEditors() {
177228
}
178229

179230
// MDAST conversion functions
231+
/**
232+
* @typedef {Object} MdastNode
233+
* @property {string} type - The type of the node.
234+
* @property {Array<MdastNode>} [children] - Child nodes.
235+
* @property {string} [value] - Text value for text nodes.
236+
* @property {string} [url] - URL for link and image nodes.
237+
* @property {string} [title] - Title for image nodes.
238+
* @property {string} [alt] - Alt text for image nodes.
239+
* @property {number} [depth] - Depth for heading nodes.
240+
* @property {boolean} [ordered] - Whether the list is ordered.
241+
* @property {boolean} [spread] - Whether the list is spread.
242+
* @property {string} [lang] - Language for code blocks.
243+
*/
244+
245+
/**
246+
* Converts a Quill Delta to a MDAST (Markdown Abstract Syntax Tree).
247+
* @param {QuillDelta} delta - The Quill Delta to convert.
248+
* @returns {MdastNode} - The root MDAST node.
249+
*/
180250
function deltaToMdast(delta) {
181251
const mdast = createRootNode();
252+
/** @type {MdastNode|null} */
182253
let currentParagraph = null;
254+
/** @type {MdastNode|null} */
183255
let currentList = null;
184256
let textBuffer = "";
185257

@@ -239,24 +311,42 @@ function deltaToMdast(delta) {
239311
return mdast;
240312
}
241313

314+
/**
315+
* Creates a root MDAST node.
316+
* @returns {MdastNode} - The root node.
317+
*/
242318
function createRootNode() {
243319
return {
244320
type: "root",
245321
children: [],
246322
};
247323
}
248324

325+
/**
326+
* Creates a paragraph MDAST node.
327+
* @returns {MdastNode} - The paragraph node.
328+
*/
249329
function createParagraphNode() {
250330
return {
251331
type: "paragraph",
252332
children: [],
253333
};
254334
}
255335

336+
/**
337+
* Checks if an operation is an image insertion.
338+
* @param {Object} op - The operation to check.
339+
* @returns {boolean} - Whether the operation is an image insertion.
340+
*/
256341
function isImageInsert(op) {
257342
return typeof op.insert === "object" && op.insert.image;
258343
}
259344

345+
/**
346+
* Creates an image MDAST node.
347+
* @param {Object} op - The operation containing the image.
348+
* @returns {MdastNode} - The image node.
349+
*/
260350
function createImageNode(op) {
261351
return {
262352
type: "image",
@@ -266,6 +356,12 @@ function createImageNode(op) {
266356
};
267357
}
268358

359+
/**
360+
* Creates a text MDAST node with optional formatting.
361+
* @param {string} text - The text content.
362+
* @param {Object} attributes - The formatting attributes.
363+
* @returns {MdastNode} - The formatted text node.
364+
*/
269365
function createTextNode(text, attributes) {
270366
let node = {
271367
type: "text",
@@ -291,13 +387,28 @@ function createTextNode(text, attributes) {
291387
return node;
292388
}
293389

390+
/**
391+
* Wraps a node with a formatting container.
392+
* @param {MdastNode} node - The node to wrap.
393+
* @param {string} type - The type of container.
394+
* @returns {MdastNode} - The wrapped node.
395+
*/
294396
function wrapNodeWith(node, type) {
295397
return {
296398
type: type,
297399
children: [node],
298400
};
299401
}
300402

403+
/**
404+
* Processes a line break in the Delta.
405+
* @param {MdastNode} mdast - The root MDAST node.
406+
* @param {MdastNode|null} currentParagraph - The current paragraph being built.
407+
* @param {Object} attributes - The attributes for the line.
408+
* @param {string} textBuffer - The text buffer for the current line.
409+
* @param {MdastNode|null} currentList - The current list being built.
410+
* @returns {void}
411+
*/
301412
function processLineBreak(
302413
mdast,
303414
currentParagraph,
@@ -323,6 +434,13 @@ function processLineBreak(
323434
}
324435
}
325436

437+
/**
438+
* Handles an empty line with special attributes.
439+
* @param {MdastNode} mdast - The root MDAST node.
440+
* @param {Object} attributes - The attributes for the line.
441+
* @param {MdastNode|null} currentList - The current list being built.
442+
* @returns {void}
443+
*/
326444
function handleEmptyLineWithAttributes(mdast, attributes, currentList) {
327445
if (attributes["code-block"]) {
328446
mdast.children.push(createEmptyCodeBlock(attributes));
@@ -334,6 +452,11 @@ function handleEmptyLineWithAttributes(mdast, attributes, currentList) {
334452
}
335453
}
336454

455+
/**
456+
* Creates an empty code block MDAST node.
457+
* @param {Object} attributes - The attributes for the code block.
458+
* @returns {MdastNode} - The code block node.
459+
*/
337460
function createEmptyCodeBlock(attributes) {
338461
return {
339462
type: "code",
@@ -343,6 +466,10 @@ function createEmptyCodeBlock(attributes) {
343466
};
344467
}
345468

469+
/**
470+
* Creates an empty list item MDAST node.
471+
* @returns {MdastNode} - The list item node.
472+
*/
346473
function createEmptyListItem() {
347474
return {
348475
type: "listItem",
@@ -351,13 +478,24 @@ function createEmptyListItem() {
351478
};
352479
}
353480

481+
/**
482+
* Creates an empty blockquote MDAST node.
483+
* @returns {MdastNode} - The blockquote node.
484+
*/
354485
function createEmptyBlockquote() {
355486
return {
356487
type: "blockquote",
357488
children: [{ type: "paragraph", children: [] }],
358489
};
359490
}
360491

492+
/**
493+
* Processes a header line break.
494+
* @param {MdastNode} mdast - The root MDAST node.
495+
* @param {string} textBuffer - The text buffer for the current line.
496+
* @param {Object} attributes - The attributes for the line.
497+
* @returns {void}
498+
*/
361499
function processHeaderLineBreak(mdast, textBuffer, attributes) {
362500
const lines = textBuffer.split("\n");
363501

@@ -386,6 +524,13 @@ function processHeaderLineBreak(mdast, textBuffer, attributes) {
386524
}
387525
}
388526

527+
/**
528+
* Processes a code block line break.
529+
* @param {MdastNode} mdast - The root MDAST node.
530+
* @param {string} textBuffer - The text buffer for the current line.
531+
* @param {Object} attributes - The attributes for the line.
532+
* @returns {void}
533+
*/
389534
function processCodeBlockLineBreak(mdast, textBuffer, attributes) {
390535
mdast.children.push({
391536
type: "code",
@@ -395,6 +540,13 @@ function processCodeBlockLineBreak(mdast, textBuffer, attributes) {
395540
});
396541
}
397542

543+
/**
544+
* Ensures a list exists in the MDAST.
545+
* @param {MdastNode} mdast - The root MDAST node.
546+
* @param {Object} attributes - The attributes for the line.
547+
* @param {MdastNode|null} currentList - The current list being built.
548+
* @returns {MdastNode} - The list node.
549+
*/
398550
function ensureList(mdast, attributes, currentList) {
399551
if (!currentList || currentList.ordered !== (attributes.list === "ordered")) {
400552
const newList = {
@@ -409,6 +561,14 @@ function ensureList(mdast, attributes, currentList) {
409561
return currentList;
410562
}
411563

564+
/**
565+
* Processes a list line break.
566+
* @param {MdastNode} mdast - The root MDAST node.
567+
* @param {MdastNode} currentParagraph - The current paragraph being built.
568+
* @param {Object} attributes - The attributes for the line.
569+
* @param {MdastNode|null} currentList - The current list being built.
570+
* @returns {void}
571+
*/
412572
function processListLineBreak(
413573
mdast,
414574
currentParagraph,
@@ -426,6 +586,12 @@ function processListLineBreak(
426586
list.children.push(listItem);
427587
}
428588

589+
/**
590+
* Processes a blockquote line break.
591+
* @param {MdastNode} mdast - The root MDAST node.
592+
* @param {MdastNode} currentParagraph - The current paragraph being built.
593+
* @returns {void}
594+
*/
429595
function processBlockquoteLineBreak(mdast, currentParagraph) {
430596
mdast.children.push({
431597
type: "blockquote",
@@ -435,5 +601,3 @@ function processBlockquoteLineBreak(mdast, currentParagraph) {
435601

436602
// Main execution
437603
document.addEventListener("DOMContentLoaded", initializeEditors);
438-
439-
export { deltaToMdast };

0 commit comments

Comments
 (0)