generated from mirrors/plugin-sample-vite-svelte
Do not underline inline LaTeX, inline code, images
All checks were successful
Build on Push and create Release on Tag / build (push) Successful in 4m7s
All checks were successful
Build on Push and create Release on Tag / build (push) Successful in 4m7s
This commit is contained in:
parent
0442ac2bac
commit
8fcc1c76e9
3 changed files with 47 additions and 13 deletions
|
|
@ -41,6 +41,28 @@ export class ProtyleHelper {
|
|||
return document.querySelector(`div.underline-overlay[for-block-id="${blockID}"]`)
|
||||
}
|
||||
|
||||
public static getElementAtTextIndex(root: Element, index: number): Node {
|
||||
let currentOffset = 0;
|
||||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
|
||||
|
||||
while (walker.nextNode()) {
|
||||
let node = walker.currentNode
|
||||
const textLength = node.textContent.length;
|
||||
|
||||
if (currentOffset + textLength >= index) {
|
||||
let parent: Element = node.parentElement;
|
||||
while (parent && parent != root) {
|
||||
node = parent
|
||||
parent = node.parentElement
|
||||
}
|
||||
return node; // The element containing this text
|
||||
}
|
||||
currentOffset += textLength;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// given an element such as a span inside a block, return its blockID
|
||||
public static getNodeId(el: Element) {
|
||||
let i = 0;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export class SpellCheckerUI {
|
|||
// Find the text nodes and character positions
|
||||
const range = this.createRangeFromCharacterIndices(startIndex, endIndex);
|
||||
if (range) {
|
||||
this.createUnderlineFromRange(range, endIndex - startIndex);
|
||||
this.createUnderlineFromRange(range);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ export class SpellCheckerUI {
|
|||
return null;
|
||||
}
|
||||
|
||||
private createUnderlineFromRange(range: Range, charsCount: number) {
|
||||
private createUnderlineFromRange(range: Range) {
|
||||
const rects = range.getClientRects();
|
||||
const editorRect = this.block.getBoundingClientRect();
|
||||
|
||||
|
|
@ -120,19 +120,10 @@ export class SpellCheckerUI {
|
|||
underline.style.top = (top + 2 + offset.v) + 'px';
|
||||
underline.style.width = width + 'px';
|
||||
|
||||
if(!SpellCheckerUI.checkDontUnderline(width, charsCount)) {
|
||||
this.overlay.appendChild(underline);
|
||||
}
|
||||
this.overlay.appendChild(underline);
|
||||
}
|
||||
}
|
||||
|
||||
// if the underline is too wide for the number of characters that are underlined, we don't render it
|
||||
// this is a consequence of using .innerText: things like <img> tags are only a character
|
||||
private static checkDontUnderline(width: number, charsCount: number) {
|
||||
const maxWidthPerChar = 16;
|
||||
return width > maxWidthPerChar * charsCount
|
||||
}
|
||||
|
||||
private static distance(elA: HTMLElement, elB: HTMLElement): {h: number, v: number} {
|
||||
const rectA = elA.getBoundingClientRect();
|
||||
const rectB = elB.getBoundingClientRect();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ export class SuggestionEngine {
|
|||
private blockStorage: BlockStorage = {};
|
||||
private plugin: SpellCheckPlugin;
|
||||
|
||||
private static blacklisted: string[] = [
|
||||
"span[data-type='inline-math']",
|
||||
"span[data-type='img']",
|
||||
"span[data-type='code']"
|
||||
];
|
||||
|
||||
constructor(plugin: SpellCheckPlugin) {
|
||||
this.plugin = plugin
|
||||
}
|
||||
|
|
@ -127,7 +133,8 @@ export class SuggestionEngine {
|
|||
thisBlock.spellChecker.clearUnderlines()
|
||||
|
||||
thisBlock.suggestions?.forEach(suggestion => {
|
||||
if(!Settings.isInCustomDictionary(this.suggestionToWrongText(suggestion, blockID), this.plugin.settingsUtil)) {
|
||||
if(this.shouldSuggest(blockID, thisBlock, suggestion) &&
|
||||
!Settings.isInCustomDictionary(this.suggestionToWrongText(suggestion, blockID), this.plugin.settingsUtil)) {
|
||||
try {
|
||||
thisBlock.spellChecker.highlightCharacterRange(suggestion.offset, suggestion.offset + suggestion.length)
|
||||
}catch (_) {
|
||||
|
|
@ -138,6 +145,20 @@ export class SuggestionEngine {
|
|||
|
||||
}
|
||||
|
||||
private shouldSuggest(blockID: string, block: StoredBlock, suggestion: Suggestion): boolean {
|
||||
|
||||
const element = block.protyle.fastGetBlockElement(blockID)
|
||||
const eai = ProtyleHelper.getElementAtTextIndex(element, suggestion.offset + suggestion.length)
|
||||
|
||||
for(let blacklisted of SuggestionEngine.blacklisted) {
|
||||
if(eai instanceof Element && eai.matches(blacklisted)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
public suggestionToWrongText(suggestion: Suggestion, blockID: string): string {
|
||||
if(!(blockID in this.blockStorage)) {
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue