mirror of
https://github.com/codex-team/editor.js
synced 2026-03-18 08:29:52 +01:00
fix: lint issues in inline-tool-bold.ts
This commit is contained in:
parent
c489d020c6
commit
1a6049c97d
1 changed files with 164 additions and 7 deletions
|
|
@ -34,11 +34,6 @@ export default class BoldInlineTool implements InlineTool {
|
|||
} as SanitizerConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Native Document's command that uses for Bold
|
||||
*/
|
||||
private readonly commandName: string = 'bold';
|
||||
|
||||
/**
|
||||
* Create button for Inline Toolbar
|
||||
*/
|
||||
|
|
@ -47,12 +42,174 @@ export default class BoldInlineTool implements InlineTool {
|
|||
icon: IconBold,
|
||||
name: 'bold',
|
||||
onActivate: () => {
|
||||
document.execCommand(this.commandName);
|
||||
this.toggleBold();
|
||||
},
|
||||
isActive: () => {
|
||||
const selection = window.getSelection();
|
||||
|
||||
return selection ? this.isSelectionBold(selection) : false;
|
||||
},
|
||||
isActive: () => document.queryCommandState(this.commandName),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply or remove bold formatting using modern Selection API
|
||||
*/
|
||||
private toggleBold(): void {
|
||||
const selection = window.getSelection();
|
||||
|
||||
if (!selection || selection.rangeCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
if (range.collapsed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if selection is already wrapped in <b> tag
|
||||
const isBold = this.isSelectionBold(selection);
|
||||
|
||||
if (isBold) {
|
||||
// Unwrap: remove <b> tags while preserving content
|
||||
this.unwrapBoldTags(range);
|
||||
} else {
|
||||
// Wrap: surround selection with <b> tag
|
||||
this.wrapWithBold(range);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current selection is within a <b> tag
|
||||
*
|
||||
* @param selection - The Selection object to check
|
||||
*/
|
||||
private isSelectionBold(selection: Selection): boolean {
|
||||
if (!selection || selection.rangeCount === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
const container = range.commonAncestorContainer;
|
||||
|
||||
// Check if container itself is a <b> tag
|
||||
if (container.nodeType === Node.ELEMENT_NODE && (container as Element).tagName === 'B') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if container is inside a <b> tag
|
||||
let parent: Node | null = container.nodeType === Node.TEXT_NODE ? container.parentElement : container as Element;
|
||||
|
||||
while (parent && parent.nodeType === Node.ELEMENT_NODE) {
|
||||
if ((parent as Element).tagName === 'B') {
|
||||
return true;
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap selection with <b> tag
|
||||
*
|
||||
* @param range - The Range object containing the selection to wrap
|
||||
*/
|
||||
private wrapWithBold(range: Range): void {
|
||||
const bElement = document.createElement('b');
|
||||
|
||||
try {
|
||||
range.surroundContents(bElement);
|
||||
} catch (error) {
|
||||
// If surroundContents fails (e.g., range spans multiple elements),
|
||||
// extract content and wrap it
|
||||
const contents = range.extractContents();
|
||||
|
||||
bElement.appendChild(contents);
|
||||
range.insertNode(bElement);
|
||||
}
|
||||
|
||||
// Restore selection
|
||||
const selection = window.getSelection();
|
||||
|
||||
if (selection) {
|
||||
selection.removeAllRanges();
|
||||
const newRange = document.createRange();
|
||||
|
||||
newRange.selectNodeContents(bElement);
|
||||
selection.addRange(newRange);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove <b> tags while preserving content
|
||||
*
|
||||
* @param range - The Range object containing the selection to unwrap
|
||||
*/
|
||||
private unwrapBoldTags(range: Range): void {
|
||||
const container = range.commonAncestorContainer;
|
||||
let boldElement: HTMLElement | null = null;
|
||||
|
||||
// Find the <b> element
|
||||
if (container.nodeType === Node.ELEMENT_NODE && (container as Element).tagName === 'B') {
|
||||
boldElement = container as HTMLElement;
|
||||
} else {
|
||||
let parent: Node | null = container.nodeType === Node.TEXT_NODE ? container.parentElement : container as Element;
|
||||
|
||||
while (parent && parent.nodeType === Node.ELEMENT_NODE) {
|
||||
if ((parent as Element).tagName === 'B') {
|
||||
boldElement = parent as HTMLElement;
|
||||
break;
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (boldElement) {
|
||||
const selection = window.getSelection();
|
||||
|
||||
if (!selection || selection.rangeCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save references to first and last child before unwrapping
|
||||
const firstChild = boldElement.firstChild;
|
||||
const lastChild = boldElement.lastChild;
|
||||
|
||||
// Replace <b> with its contents
|
||||
const parent = boldElement.parentNode;
|
||||
|
||||
if (parent && firstChild && lastChild) {
|
||||
// Insert all children before the bold element
|
||||
while (boldElement.firstChild) {
|
||||
parent.insertBefore(boldElement.firstChild, boldElement);
|
||||
}
|
||||
parent.removeChild(boldElement);
|
||||
|
||||
// Restore selection to the unwrapped content
|
||||
selection.removeAllRanges();
|
||||
const newRange = document.createRange();
|
||||
|
||||
if (firstChild === lastChild && firstChild.nodeType === Node.TEXT_NODE) {
|
||||
// Single text node: try to preserve offsets
|
||||
const textLength = firstChild.textContent?.length ?? 0;
|
||||
const start = Math.min(range.startOffset, textLength);
|
||||
const end = Math.min(range.endOffset, textLength);
|
||||
|
||||
newRange.setStart(firstChild, start);
|
||||
newRange.setEnd(firstChild, end);
|
||||
} else {
|
||||
// Multiple nodes: select from first to last
|
||||
newRange.setStartBefore(firstChild);
|
||||
newRange.setEndAfter(lastChild);
|
||||
}
|
||||
|
||||
selection.addRange(newRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a shortcut
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue