diff --git a/package.json b/package.json index 7905fa3..13bd2ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "syspell", - "version": "0.4.0", + "version": "0.3.0", "type": "module", "description": "This SiYuan plugin adds a fully featured grammar and spell checker, powered by LanguageTool.", "repository": "https://git.massive.box/massivebox/syspell", diff --git a/plugin.json b/plugin.json index 4f756c6..9671f15 100644 --- a/plugin.json +++ b/plugin.json @@ -2,7 +2,7 @@ "name": "syspell", "author": "massivebox", "url": "https://git.massive.box/massivebox/syspell", - "version": "0.4.0", + "version": "0.3.0", "minAppVersion": "3.0.12", "backends": [ "windows", diff --git a/public/i18n/en_US.json b/public/i18n/en_US.json index ab4e6f6..1e4a48f 100644 --- a/public/i18n/en_US.json +++ b/public/i18n/en_US.json @@ -1,5 +1,4 @@ { - "syspell": "SySpell", "settings":{ "info": { "title": "Information", diff --git a/src/index.ts b/src/index.ts index 8405f65..0b21f2f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -48,7 +48,6 @@ export default class SpellCheckPlugin extends Plugin { this.eventBus.on('ws-main', async (event) => { if (event.detail.cmd != 'transactions') { - void this.suggestions.forAllBlocksSuggest(false, true) return } diff --git a/src/menus.ts b/src/menus.ts index 0651e1b..6e89181 100644 --- a/src/menus.ts +++ b/src/menus.ts @@ -3,7 +3,6 @@ import SpellCheckPlugin from "@/index"; import {getBlockAttrs, setBlockAttrs} from "@/api"; import {Settings} from "@/settings"; import {ProtyleHelper} from "@/protyleHelper"; -import {Analytics} from "@/analytics"; export class Menus { @@ -68,9 +67,7 @@ export class Menus { public async addSettingsToDocMenu(docID: string, menu: subMenu) { - let submenu = [] - - submenu.push({ + menu.addItem({ icon: 'info', label: this.plugin.i18nx.docMenu.documentStatus, click: async () => { @@ -89,7 +86,7 @@ export class Menus { } }) - submenu.push({ + menu.addItem({ icon: 'toggle', label: this.plugin.i18nx.docMenu.toggleSpellCheck, click: async () => { @@ -107,17 +104,7 @@ export class Menus { } }) - async function setLang(lang: string, analytics: Analytics) { - const attrs = await getBlockAttrs(docID) - attrs[SpellCheckPlugin.LANGUAGE_ATTR] = lang - await setBlockAttrs(docID, attrs) - void analytics.sendEvent('docmenu-click-setlang-2', { - 'language': lang - }); - location.reload() - } - - submenu.push({ + menu.addItem({ icon: 'language', label: this.plugin.i18nx.docMenu.setDocumentLanguage, click: async (_, ev: MouseEvent) => { @@ -127,13 +114,29 @@ export class Menus { langMenu.addItem({ icon: 'autodetect', label: this.plugin.i18nx.docMenu.autodetectLanguage, - click: async () => setLang('auto', this.plugin.analytics) + click: async () => { + const attrs = await getBlockAttrs(docID) + attrs[SpellCheckPlugin.LANGUAGE_ATTR] = 'auto' + await setBlockAttrs(docID, attrs) + void this.plugin.analytics.sendEvent('docmenu-click-setlang-2', { + 'language': 'auto' + }); + location.reload() + } }); languages.forEach(language => { langMenu.addItem({ icon: 'language', label: language.name + ' [' + language.longCode + ']', - click: async () => setLang(language.longCode, this.plugin.analytics) + click: async () => { + const attrs = await getBlockAttrs(docID) + attrs[SpellCheckPlugin.LANGUAGE_ATTR] = language.longCode + await setBlockAttrs(docID, attrs) + void this.plugin.analytics.sendEvent('docmenu-click-setlang-2', { + 'language': language.longCode + }); + location.reload() + } }); }); langMenu.open({ x: ev.clientX, y: ev.clientY }); @@ -141,12 +144,6 @@ export class Menus { } }) - menu.addItem({ - icon: 'spellcheck', - label: this.plugin.i18nx.syspell, - submenu: submenu - }) - } } \ No newline at end of file diff --git a/src/protyleHelper.ts b/src/protyleHelper.ts index 742f7e5..a5ae0cc 100644 --- a/src/protyleHelper.ts +++ b/src/protyleHelper.ts @@ -41,28 +41,6 @@ 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; diff --git a/src/spellCheckerUI.ts b/src/spellCheckerUI.ts index d932fd5..a662687 100644 --- a/src/spellCheckerUI.ts +++ b/src/spellCheckerUI.ts @@ -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); + this.createUnderlineFromRange(range, endIndex - startIndex); } } @@ -101,7 +101,7 @@ export class SpellCheckerUI { return null; } - private createUnderlineFromRange(range: Range) { + private createUnderlineFromRange(range: Range, charsCount: number) { const rects = range.getClientRects(); const editorRect = this.block.getBoundingClientRect(); @@ -120,10 +120,19 @@ export class SpellCheckerUI { underline.style.top = (top + 2 + offset.v) + 'px'; underline.style.width = width + 'px'; - this.overlay.appendChild(underline); + if(!SpellCheckerUI.checkDontUnderline(width, charsCount)) { + 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 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(); diff --git a/src/suggestions.ts b/src/suggestions.ts index d43340a..eb95692 100644 --- a/src/suggestions.ts +++ b/src/suggestions.ts @@ -20,12 +20,6 @@ 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 } @@ -133,8 +127,7 @@ export class SuggestionEngine { thisBlock.spellChecker.clearUnderlines() thisBlock.suggestions?.forEach(suggestion => { - if(this.shouldSuggest(blockID, thisBlock, suggestion) && - !Settings.isInCustomDictionary(this.suggestionToWrongText(suggestion, blockID), this.plugin.settingsUtil)) { + if(!Settings.isInCustomDictionary(this.suggestionToWrongText(suggestion, blockID), this.plugin.settingsUtil)) { try { thisBlock.spellChecker.highlightCharacterRange(suggestion.offset, suggestion.offset + suggestion.length) }catch (_) { @@ -145,20 +138,6 @@ 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