├── .DS_Store ├── .github └── workflows │ └── release.yml ├── .gitignore ├── .hotreload ├── CHANGELOG.md ├── DEV_NOTES.MD ├── FeaturePreview.gif ├── LICENSE ├── LICENSE-WordNet ├── README.md ├── biome.json ├── dict-WordNet.json ├── esbuild.config.mjs ├── manifest.json ├── package.json ├── src ├── EditSuggest.ts ├── main.ts ├── settings.ts └── suggester.ts ├── styles.css ├── tsconfig.json ├── version-bump.mjs ├── version-github-action.mjs ├── versions.json └── wordnet.sqlite /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TfTHacker/Obsidian-WordNet/e1fe397f672c1e71cd49349a7e5369e79f1bfafc/.DS_Store -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Obsidian plugin 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | 15 | - name: Use Node.js 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: '21.x' 19 | 20 | - name: Build plugin 21 | run: | 22 | npm install 23 | npm run build 24 | 25 | - name: Create release 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | run: | 29 | tag="${GITHUB_REF#refs/tags/}" 30 | 31 | gh release create "$tag" \ 32 | --title="$tag" \ 33 | build/main.js manifest.json styles.css 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # vscode 2 | .vscode 3 | 4 | # npm 5 | node_modules 6 | package-lock.json 7 | 8 | # build 9 | build 10 | main.js 11 | *.js.map 12 | dict-MyDict.json 13 | 14 | # obsidian 15 | data.json 16 | @updates.md 17 | -------------------------------------------------------------------------------- /.hotreload: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TfTHacker/Obsidian-WordNet/e1fe397f672c1e71cd49349a7e5369e79f1bfafc/.hotreload -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.0.5 2 | 3 | ### Updates 4 | - Updating plugin to newest Obsidian recommendations https://docs.obsidian.md/oo24/plugin. 5 | - Transition to Biome from EsLint and Prettier. 6 | -------------------------------------------------------------------------------- /DEV_NOTES.MD: -------------------------------------------------------------------------------- 1 | DEV_NOTES.MD 2 | 3 | # Updating the version 4 | 5 | 1. update pacakage.json version number 6 | 2. npm run version (updates the manifest and version file) 7 | 3. commit repo 8 | 4. npm run githubaction (commits the version number tag to the repo and pushes it, which kicks of the github action to prepare the release) 9 | -------------------------------------------------------------------------------- /FeaturePreview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TfTHacker/Obsidian-WordNet/e1fe397f672c1e71cd49349a7e5369e79f1bfafc/FeaturePreview.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 TfTHacker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE-WordNet: -------------------------------------------------------------------------------- 1 | # WordNet 3.0 license: 2 | 3 | WordNet Release 3.0 This software and database is being provided to you, the LICENSEE, by Princeton University under the following license. By obtaining, using and/or copying this software and database, you agree that you have read, understood, and will comply with these terms and conditions.: Permission to use, copy, modify and distribute this software and database and its documentation for any purpose and without fee or royalty is hereby granted, provided that you agree to comply with the following copyright notice and statements, including the disclaimer, and that the same appear on ALL copies of the software, database and documentation, including modifications that you make for internal use or for distribution. WordNet 3.0 Copyright 2006 by Princeton University. All rights reserved. THIS SOFTWARE AND DATABASE IS PROVIDED "AS IS" AND PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANT- ABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE, DATABASE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. The name of Princeton University or Princeton may not be used in advertising or publicity pertaining to distribution of the software and/or database. Title to copyright in this software, database and any associated documentation shall at all times remain with Princeton University and LICENSEE agrees to preserve same. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WordNet dictionary plugin for Obsidian 2 | 3 | WordNet plugin for Obsidian. WordNet is a large lexical database of English terms developed by Princeton University and its license allows use in other applications. 4 | 5 | Learn more by reading the documentation: https://tfthacker.com/wordnet 6 | 7 | # Instructions 8 | 9 | The WordNet dictionary can be accessed either through the command palette or the WordNet button on the ribbon. 10 | 11 | Once invoked, WordNet will allow you to input the word you want to look up. As you type, options are shown. Once you find the word that interests you, you can press enter to have it inserted into the current document. If the current document is in preview mode, the definition will be displayed in a notification window for about 10 seconds. 12 | 13 | ![Feature Preview](FeaturePreview.gif) 14 | 15 | ## Ways to connect with me and more information on my work 16 | You might also be interested in a few products I have made for Obsidian: 17 | 18 | - [JournalCraft](https://tfthacker.com/jco) - A curated collection of 10 powerful journaling templates designed to enhance your journaling experience. Whether new to journaling or looking to step up your game, JournalCraft has something for you. 19 | - [Cornell Notes Learning Vault](https://tfthacker.com/cornell-notes) - This vault teaches you how to use the Cornell Note-Taking System in your Obsidian vault. It includes learning material, samples, and Obsidian configuration files to enable Cornell Notes in your vault. 20 | 21 | 22 | You can find me on Twitter [@TfTHacker](https://x.com/TfTHacker) 23 | 24 | My website https://tfthacker.com/ 25 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", 3 | "vcs": { 4 | "enabled": false, 5 | "clientKind": "git", 6 | "useIgnoreFile": false 7 | }, 8 | "files": { 9 | "ignoreUnknown": false, 10 | "ignore": ["./src/dict-WordNet.json"] 11 | }, 12 | "formatter": { 13 | "enabled": true, 14 | "indentStyle": "tab" 15 | }, 16 | "organizeImports": { 17 | "enabled": true 18 | }, 19 | "linter": { 20 | "enabled": true, 21 | "rules": { 22 | "recommended": true 23 | } 24 | }, 25 | "javascript": { 26 | "formatter": { 27 | "quoteStyle": "double" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /esbuild.config.mjs: -------------------------------------------------------------------------------- 1 | import console from "console"; 2 | import fs from "fs"; 3 | import builtins from "builtin-modules"; 4 | import esbuild from "esbuild"; 5 | import process from "process"; 6 | 7 | fs.copyFile("manifest.json", "build/manifest.json", (err) => { 8 | if (err) console.log(err); 9 | }); 10 | fs.copyFile("styles.css", "build/styles.css", (err) => { 11 | if (err) console.log(err); 12 | }); 13 | 14 | const prod = process.argv[2] === "production"; 15 | 16 | const context = await esbuild.context({ 17 | entryPoints: ["src/main.ts"], 18 | bundle: true, 19 | external: [ 20 | "obsidian", 21 | "electron", 22 | "@codemirror/autocomplete", 23 | "@codemirror/collab", 24 | "@codemirror/commands", 25 | "@codemirror/language", 26 | "@codemirror/lint", 27 | "@codemirror/search", 28 | "@codemirror/state", 29 | "@codemirror/view", 30 | "@lezer/common", 31 | "@lezer/highlight", 32 | "@lezer/lr", 33 | ...builtins, 34 | ], 35 | format: "cjs", 36 | target: "es2018", 37 | logLevel: "info", 38 | sourcemap: prod ? false : "inline", 39 | treeShaking: true, 40 | outfile: "build/main.js", 41 | }); 42 | 43 | if (prod) { 44 | await context.rebuild(); 45 | process.exit(0); 46 | } else { 47 | await context.watch(); 48 | } 49 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "obsidian-wordnet-plugin", 3 | "name": "WordNet Dictionary", 4 | "version": "2.0.5", 5 | "minAppVersion": "1.7.2", 6 | "description": "WordNet is a large lexical database of English developed by Princeton University.", 7 | "author": "TfT Hacker", 8 | "authorUrl": "https://github.com/TfTHacker/Obsidian-WordNet", 9 | "helpUrl": "https://tfthacker.com/wordnet", 10 | "isDesktopOnly": false, 11 | "fundingUrl": { 12 | "Visit my site": "https://tfthacker.com" 13 | } 14 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "obsidian-wordnet-plugin", 3 | "ime": "obsidian-wordnet-plugin", 4 | "version": "2.0.5", 5 | "description": "WordNet plugin for Obsidian. WordNet is a large lexical database of English developed by Princeton University and its license allows use in other applications.", 6 | "main": "main.js", 7 | "scripts": { 8 | "dev": "node --no-warnings esbuild.config.mjs", 9 | "build": "node --no-warnings esbuild.config.mjs production", 10 | "lint": "biome check ./src", 11 | "version": "node version-bump.mjs", 12 | "githubaction": "node version-github-action.mjs" 13 | }, 14 | "author": "TfT Hacker", 15 | "license": "MIT", 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/TfTHacker/Obsidian-WordNet.git" 19 | }, 20 | "devDependencies": { 21 | "@biomejs/biome": "1.9.4", 22 | "@types/node": "^22.8.7", 23 | "builtin-modules": "4.0.0", 24 | "esbuild": "0.24.0", 25 | "obsidian": "1.7.2", 26 | "tslib": "^2.6.2", 27 | "typescript": "^5.3.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/EditSuggest.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type Editor, 3 | type EditorPosition, 4 | EditorSuggest, 5 | type EditorSuggestContext, 6 | type EditorSuggestTriggerInfo, 7 | MarkdownView, 8 | Notice, 9 | type TFile, 10 | } from "obsidian"; 11 | import type WordNetPlugin from "./main"; 12 | import type { Definition } from "./suggester"; 13 | 14 | export default class TheEditorSuggestor extends EditorSuggest { 15 | plugin: WordNetPlugin; 16 | pattern: RegExp; 17 | lastEditorSuggestTriggerInfo: EditorSuggestTriggerInfo; 18 | 19 | constructor(plugin: WordNetPlugin) { 20 | super(plugin.app); 21 | this.plugin = plugin; 22 | this.updatePattern(); 23 | } 24 | 25 | updatePattern(): void { 26 | this.pattern = new RegExp( 27 | `.*${this.plugin.settings.slashCommandShortcut}(.*)$`, 28 | ); 29 | } 30 | 31 | onTrigger( 32 | cursor: EditorPosition, 33 | editor: Editor, 34 | _file: TFile, 35 | ): EditorSuggestTriggerInfo { 36 | if (this.plugin.settings.slashCommandEnabled === false) return; 37 | const range = editor.getRange( 38 | { line: cursor.line, ch: 0 }, 39 | { line: cursor.line, ch: cursor.ch }, 40 | ); 41 | 42 | const testResults = this.pattern.exec(range); 43 | if (!testResults) return null; 44 | 45 | const suggestText = testResults[1]; 46 | this.lastEditorSuggestTriggerInfo = { 47 | start: { 48 | line: cursor.line, 49 | ch: 50 | cursor.ch - 51 | suggestText.length - 52 | this.plugin.settings.slashCommandShortcut.length, 53 | }, 54 | end: { line: cursor.line, ch: cursor.ch }, 55 | query: testResults[1], 56 | }; 57 | return this.lastEditorSuggestTriggerInfo; 58 | } 59 | 60 | getSuggestions(context: EditorSuggestContext): Promise { 61 | return this.plugin.dictionarySuggestor.query(context.query); 62 | } 63 | 64 | renderSuggestion(item: Definition, el: HTMLElement): void { 65 | el.createEl("b", { text: item.Term }); 66 | el.createEl("br"); 67 | el.appendText(item.Definition); 68 | } 69 | 70 | selectSuggestion(item: Definition, evt: MouseEvent | KeyboardEvent): void { 71 | const currentView = 72 | this.plugin.app.workspace.getActiveViewOfType(MarkdownView); 73 | this.close(); 74 | if (evt.ctrlKey) { 75 | new Notice(`${item.Term} \n${item.Definition}`, 60000); 76 | currentView.editor.replaceRange( 77 | "", 78 | this.lastEditorSuggestTriggerInfo.start, 79 | this.lastEditorSuggestTriggerInfo.end, 80 | ); 81 | } else 82 | currentView.editor.replaceRange( 83 | this.plugin.renderDefinitionFromTemplate(item.Term, item.Definition), 84 | this.lastEditorSuggestTriggerInfo.start, 85 | this.lastEditorSuggestTriggerInfo.end, 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { Plugin } from "obsidian"; 2 | import TheEditorSuggestor from "./EditSuggest"; 3 | import { 4 | DEFAULT_SETTINGS, 5 | WordNetSettingTab, 6 | type WordNetSettings, 7 | } from "./settings"; 8 | import DictionarySuggester from "./suggester"; 9 | 10 | export default class WordNetPlugin extends Plugin { 11 | settings: WordNetSettings; 12 | ribbonIcon: HTMLElement; 13 | dictionarySuggestor: DictionarySuggester; 14 | editSuggester: TheEditorSuggestor; 15 | 16 | configureRibbonCommand(): void { 17 | this.ribbonIcon = this.addRibbonIcon( 18 | "book-open-check", 19 | "WordNet Dictionary", 20 | async () => { 21 | this.dictionarySuggestor.open(); 22 | }, 23 | ); 24 | } 25 | 26 | async onload(): Promise { 27 | console.log("loading WordNet plugin"); 28 | 29 | await this.loadSettings(); 30 | 31 | this.addSettingTab(new WordNetSettingTab(this.app, this)); 32 | 33 | this.dictionarySuggestor = new DictionarySuggester(this); 34 | 35 | if (this.settings.enableRibbon) this.configureRibbonCommand(); 36 | 37 | this.addCommand({ 38 | id: "open-wordnet-suggestor", 39 | name: "Look up a word", 40 | callback: () => { 41 | this.dictionarySuggestor.open(); 42 | }, 43 | }); 44 | 45 | this.editSuggester = new TheEditorSuggestor(this); 46 | this.registerEditorSuggest(this.editSuggester); 47 | } 48 | 49 | onunload(): void { 50 | console.log("unloading WordNet plugin"); 51 | } 52 | 53 | renderDefinitionFromTemplate(term: string, definition: string): string { 54 | return this.settings.insertTemplate 55 | .replace("{term}", term) 56 | .replace("{definition}", definition); 57 | } 58 | 59 | async loadSettings(): Promise { 60 | this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); 61 | } 62 | 63 | async saveSettings(): Promise { 64 | await this.saveData(this.settings); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/settings.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type App, 3 | Setting, 4 | type TextAreaComponent, 5 | type TextComponent, 6 | type ToggleComponent, 7 | } from "obsidian"; 8 | import { PluginSettingTab } from "obsidian"; 9 | import type WordNetPlugin from "./main"; 10 | 11 | export interface WordNetSettings { 12 | slashCommandEnabled: boolean; 13 | slashCommandShortcut: string; 14 | insertTemplate: string; 15 | } 16 | 17 | export const DEFAULT_SETTINGS: WordNetSettings = { 18 | slashCommandEnabled: true, 19 | slashCommandShortcut: ";;", 20 | insertTemplate: "**{term}**\n{definition}\n", 21 | }; 22 | 23 | export class WordNetSettingTab extends PluginSettingTab { 24 | plugin: WordNetPlugin; 25 | 26 | constructor(app: App, plugin: WordNetPlugin) { 27 | super(app, plugin); 28 | this.plugin = plugin; 29 | } 30 | 31 | display(): void { 32 | const { containerEl } = this; 33 | containerEl.empty(); 34 | 35 | new Setting(containerEl) 36 | .setName("Slash command") 37 | .setDesc("Enable the slash command for WordNet.") 38 | .addToggle((cb: ToggleComponent) => { 39 | cb.setValue(this.plugin.settings.slashCommandEnabled); 40 | cb.onChange(async (value: boolean) => { 41 | this.plugin.settings.slashCommandEnabled = value; 42 | await this.plugin.saveSettings(); 43 | }); 44 | }); 45 | 46 | let cbShortcut: TextComponent; 47 | new Setting(containerEl) 48 | .setName("Slash command characters") 49 | .setDesc( 50 | "The characters that will invoke the slash command. The command character cannot be a space.", 51 | ) 52 | .addExtraButton((b) => { 53 | b.setIcon("reset") 54 | .setTooltip("Reset to default") 55 | .onClick(async () => { 56 | this.plugin.settings.slashCommandShortcut = 57 | DEFAULT_SETTINGS.slashCommandShortcut; 58 | await this.plugin.saveSettings(); 59 | this.plugin.editSuggester.updatePattern(); 60 | cbShortcut.setValue(this.plugin.settings.slashCommandShortcut); 61 | }); 62 | }) 63 | .addText((cb: TextComponent) => { 64 | cbShortcut = cb; 65 | cb.setValue(this.plugin.settings.slashCommandShortcut); 66 | cb.onChange(async (value: string) => { 67 | const newValue = 68 | value.trim().length === 0 69 | ? DEFAULT_SETTINGS.slashCommandShortcut 70 | : value; 71 | this.plugin.settings.slashCommandShortcut = newValue; 72 | await this.plugin.saveSettings(); 73 | this.plugin.editSuggester.updatePattern(); 74 | }); 75 | }); 76 | 77 | let cbTemplate: TextAreaComponent; 78 | new Setting(containerEl) 79 | .setName("Template for inserting a definition") 80 | .setDesc( 81 | "The template used for inserting a WordNet definition. Use {term} for the term looked up and {definition} for the defintion of that term.", 82 | ) 83 | .addExtraButton((b) => { 84 | b.setIcon("reset") 85 | .setTooltip("Reset to default") 86 | .onClick(async () => { 87 | this.plugin.settings.insertTemplate = 88 | DEFAULT_SETTINGS.insertTemplate; 89 | await this.plugin.saveSettings(); 90 | cbTemplate.setValue(this.plugin.settings.insertTemplate); 91 | }); 92 | }) 93 | .addTextArea((cb: TextAreaComponent) => { 94 | cbTemplate = cb; 95 | cb.setValue(this.plugin.settings.insertTemplate); 96 | cb.onChange(async (value: string) => { 97 | const newValue = 98 | value.trim().length === 0 ? DEFAULT_SETTINGS.insertTemplate : value; 99 | this.plugin.settings.insertTemplate = newValue; 100 | await this.plugin.saveSettings(); 101 | }); 102 | cb.inputEl.rows = 2; 103 | cb.inputEl.cols = 40; 104 | }); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/suggester.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type DataAdapter, 3 | type FuzzyMatch, 4 | FuzzySuggestModal, 5 | MarkdownView, 6 | Notice, 7 | request, 8 | } from "obsidian"; 9 | import type WordNetPlugin from "./main"; 10 | 11 | export interface Definition { 12 | SearchTerm: string; 13 | Term: string; 14 | Definition: string; 15 | } 16 | 17 | export default class DictionarySuggester extends FuzzySuggestModal { 18 | plugin: WordNetPlugin; 19 | adapter: DataAdapter; 20 | wordNet: Definition[]; 21 | customDict: Definition[]; 22 | 23 | constructor(plugin: WordNetPlugin) { 24 | super(plugin.app); 25 | this.plugin = plugin; 26 | 27 | this.setPlaceholder("type word to lookup in WordNet"); 28 | 29 | setTimeout(async () => { 30 | //load the WordNet dictionary 31 | const pathWordNetJson = `${this.plugin.manifest.dir}/dict-WordNet.json`; 32 | const adapter = this.app.vault.adapter; 33 | 34 | if (await adapter.exists(pathWordNetJson)) { 35 | const fileWordNet = await adapter.read(pathWordNetJson); 36 | this.wordNet = await JSON.parse(fileWordNet); 37 | } else { 38 | if (navigator.onLine === false) { 39 | new Notice( 40 | "You do not have an internet connection, and the WordNet dictionary cannot be downloaded. Please restore your interent connection and resteart Obsidian", 41 | 30000, 42 | ); 43 | this.plugin.unload(); 44 | } else { 45 | const downloadMessage = new Notice( 46 | "WordNet dictionary is being downloaded, this may take a few minutes. This message will disappear when the process is complete.", 47 | 0, 48 | ); 49 | try { 50 | const response = await request({ 51 | url: "https://github.com/TfTHacker/Obsidian-WordNet/releases/download/WordNetJson/dict-WordNet.json", 52 | }); 53 | downloadMessage.hide(); 54 | if ( 55 | response === "Not Found" || 56 | response === `{"error":"Not Found"}` 57 | ) { 58 | new Notice( 59 | "The WordNet dictionary file is not currently available for download. Please try again later or contact the developer on Twitter: @TfThacker for support.", 60 | 30000, 61 | ); 62 | this.plugin.unload(); 63 | } else { 64 | this.wordNet = await JSON.parse(response); 65 | await adapter.write( 66 | pathWordNetJson, 67 | JSON.stringify(this.wordNet), 68 | ); 69 | } 70 | } catch (e) { 71 | new Notice( 72 | `An error has occured with the download, please try again later: ${e}`, 73 | ); 74 | this.plugin.unload(); 75 | } 76 | } 77 | } 78 | 79 | // users can define their own custom dictionary and place it in the plugins directory. 80 | if ( 81 | await adapter.exists(`${this.plugin.manifest.dir}/dict-MyDict.json`) 82 | ) { 83 | const fileCustomDict = await adapter.read( 84 | `${this.plugin.manifest.dir}/dict-MyDict.json`, 85 | ); 86 | this.customDict = await JSON.parse(fileCustomDict); 87 | } else this.customDict = null; 88 | }, 10); 89 | } 90 | 91 | query(term: string) { 92 | const results = []; 93 | const searchTerm = term.toLocaleLowerCase(); 94 | let countOfFoundMatches = 0; 95 | if (this.customDict != null) { 96 | for ( 97 | let i = 0; 98 | i < this.customDict.length && countOfFoundMatches < 30; 99 | i++ 100 | ) { 101 | const item = this.customDict[i]; 102 | if (item.SearchTerm.startsWith(searchTerm)) { 103 | results.push(this.customDict[i]); 104 | countOfFoundMatches++; 105 | } 106 | } 107 | } 108 | countOfFoundMatches = 0; 109 | for (let i = 0; i < this.wordNet.length && countOfFoundMatches < 20; i++) { 110 | const item = this.wordNet[i]; 111 | if (item.SearchTerm.startsWith(searchTerm)) { 112 | results.push(this.wordNet[i]); 113 | countOfFoundMatches++; 114 | } 115 | } 116 | return results; 117 | } 118 | 119 | getItems(): Definition[] { 120 | let searchTerm = ""; 121 | 122 | if (this.inputEl.value.trim().length === 0) { 123 | const currentView = this.app.workspace.getActiveViewOfType(MarkdownView); 124 | if ( 125 | currentView != null && 126 | currentView.getMode() !== undefined && 127 | currentView.editor.somethingSelected() 128 | ) { 129 | searchTerm = currentView.editor.getSelection(); 130 | this.inputEl.value = searchTerm; 131 | this.inputEl.setSelectionRange(0, searchTerm.length); 132 | } 133 | } else searchTerm = this.inputEl.value.trim(); 134 | 135 | return searchTerm === "" ? [] : this.query(searchTerm); 136 | } 137 | 138 | getItemText(item: Definition): string { 139 | return item.SearchTerm; 140 | } 141 | 142 | // @ts-ignore 143 | onChooseItem(item: Definition, evt: MouseEvent | KeyboardEvent): void {} 144 | 145 | renderSuggestion(item: FuzzyMatch, el: HTMLElement): void { 146 | el.createEl("b", { text: item.item.Term }); 147 | el.createEl("br"); 148 | el.appendText(item.item.Definition); 149 | } 150 | 151 | onChooseSuggestion( 152 | item: FuzzyMatch, 153 | evt: MouseEvent | KeyboardEvent, 154 | ): void { 155 | const currentView = 156 | this.plugin.app.workspace.getActiveViewOfType(MarkdownView); 157 | if (currentView != null && currentView.getMode() === "source") 158 | currentView.editor.replaceSelection( 159 | this.plugin.renderDefinitionFromTemplate( 160 | item.item.Term, 161 | item.item.Definition, 162 | ), 163 | ); 164 | else new Notice(`${item.item.Term} \n${item.item.Definition}`, 10000); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | /* Empty file */ -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "es6", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "allowSyntheticDefaultImports": true, 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "lib": ["dom", "es5", "scripthost", "es2015"] 14 | }, 15 | "include": ["**/*.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /version-bump.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync, writeFileSync } from "fs"; 2 | 3 | const targetVersion = process.env.npm_package_version; 4 | 5 | // read minAppVersion from manifest.json and bump version to target version 6 | const manifest = JSON.parse(readFileSync("manifest.json", "utf8")); 7 | const { minAppVersion } = manifest; 8 | manifest.version = targetVersion; 9 | writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t")); 10 | 11 | // update versions.json with target version and minAppVersion from manifest.json 12 | const versions = JSON.parse(readFileSync("versions.json", "utf8")); 13 | versions[targetVersion] = minAppVersion; 14 | writeFileSync("versions.json", JSON.stringify(versions, null, "\t")); 15 | -------------------------------------------------------------------------------- /version-github-action.mjs: -------------------------------------------------------------------------------- 1 | import { exec } from "child_process"; 2 | import fs from "fs"; 3 | 4 | // Read the manifest.json file 5 | fs.readFile("manifest.json", "utf8", (err, data) => { 6 | if (err) { 7 | console.error(`Error reading file from disk: ${err}`); 8 | } else { 9 | // Parse the file content to a JavaScript object 10 | const manifest = JSON.parse(data); 11 | 12 | // Extract the version 13 | const version = manifest.version; 14 | 15 | // Execute the git commands 16 | exec( 17 | `git tag -a ${version} -m "${version}" && git push origin ${version}`, 18 | (error, stdout, stderr) => { 19 | if (error) { 20 | console.error(`exec error: ${error}`); 21 | return; 22 | } 23 | console.log(`stdout: ${stdout}`); 24 | console.error(`stderr: ${stderr}`); 25 | }, 26 | ); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "1.0.2": "0.9.7", 3 | "2.0.1": "0.9.12", 4 | "2.0.2": "1.1.1", 5 | "2.0.5": "1.7.2" 6 | } 7 | -------------------------------------------------------------------------------- /wordnet.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TfTHacker/Obsidian-WordNet/e1fe397f672c1e71cd49349a7e5369e79f1bfafc/wordnet.sqlite --------------------------------------------------------------------------------