From 65ce6ab9a46407b1b4e2b9df6812a711d5c07027 Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 30 May 2025 20:20:26 +0530 Subject: [PATCH 1/4] feat: wire spell check marker api to code inspector --- src/language/CodeInspection.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/language/CodeInspection.js b/src/language/CodeInspection.js index 8cbb15d89f..d9b455895b 100644 --- a/src/language/CodeInspection.js +++ b/src/language/CodeInspection.js @@ -84,7 +84,9 @@ define(function (require, exports, module) { /** Maintainability issue, probable error / bad smell, etc. */ WARNING: "warning", /** Inspector unable to continue, code too complex for static analysis, etc. Not counted in err/warn tally. */ - META: "meta" + META: "meta", + /** For spelling or grammatical error */ + SPELL: "spell" }; function _getIconClassForType(type, isFixable) { @@ -98,6 +100,9 @@ define(function (require, exports, module) { case Type.META: return isFixable ? "line-icon-problem_type_info fa-solid fa-wrench": "line-icon-problem_type_info fa-solid fa-info-circle"; + case Type.SPELL: return isFixable ? + "line-icon-problem_type_spell fa-solid fa-wrench": + "line-icon-problem_type_spell fa-solid fa-book"; default: return isFixable ? "line-icon-problem_type_info fa-solid fa-wrench": "line-icon-problem_type_info fa-solid fa-info-circle"; @@ -430,6 +435,7 @@ define(function (require, exports, module) { case Type.ERROR: return Editor.getMarkOptionUnderlineError(); case Type.WARNING: return Editor.getMarkOptionUnderlineWarn(); case Type.META: return Editor.getMarkOptionUnderlineInfo(); + case Type.SPELL: return Editor.getMarkOptionUnderlineSpellcheck(); } } @@ -438,6 +444,7 @@ define(function (require, exports, module) { case Type.ERROR: return 3; case Type.WARNING: return 2; case Type.META: return 1; + case Type.SPELL: return 1; } } From 0ebf0e8c7ff92995435128edabc3687728aaed13 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 31 May 2025 00:45:45 +0530 Subject: [PATCH 2/4] refactor: update type marker priorities --- src/language/CodeInspection.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/language/CodeInspection.js b/src/language/CodeInspection.js index d9b455895b..2c3a9c7b87 100644 --- a/src/language/CodeInspection.js +++ b/src/language/CodeInspection.js @@ -441,10 +441,10 @@ define(function (require, exports, module) { function _getMarkTypePriority(type){ switch (type) { - case Type.ERROR: return 3; - case Type.WARNING: return 2; + case Type.ERROR: return 4; + case Type.WARNING: return 3; + case Type.SPELL: return 2; case Type.META: return 1; - case Type.SPELL: return 1; } } From d58e21d52dd2ed810cdb98a5b8f20ae318da9cd6 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 31 May 2025 01:27:54 +0530 Subject: [PATCH 3/4] feat: working demo prototype of spell grammar check --- src/extensions/default/DefaultExtensions.json | 1 + .../SpellGrammarCheck/grammar-checker.js | 105 +++++++++++++++ .../default/SpellGrammarCheck/main.js | 30 +++++ .../default/SpellGrammarCheck/package.json | 5 + .../SpellGrammarCheck/spell-checker.js | 123 ++++++++++++++++++ 5 files changed, 264 insertions(+) create mode 100644 src/extensions/default/SpellGrammarCheck/grammar-checker.js create mode 100644 src/extensions/default/SpellGrammarCheck/main.js create mode 100644 src/extensions/default/SpellGrammarCheck/package.json create mode 100644 src/extensions/default/SpellGrammarCheck/spell-checker.js diff --git a/src/extensions/default/DefaultExtensions.json b/src/extensions/default/DefaultExtensions.json index fd1fc5483f..bd5390cd99 100644 --- a/src/extensions/default/DefaultExtensions.json +++ b/src/extensions/default/DefaultExtensions.json @@ -21,6 +21,7 @@ "Phoenix-prettier", "PrefsCodeHints", "QuickView", + "SpellGrammarCheck", "SVGCodeHints", "UrlCodeHints", "HealthData" diff --git a/src/extensions/default/SpellGrammarCheck/grammar-checker.js b/src/extensions/default/SpellGrammarCheck/grammar-checker.js new file mode 100644 index 0000000000..bf131b04bb --- /dev/null +++ b/src/extensions/default/SpellGrammarCheck/grammar-checker.js @@ -0,0 +1,105 @@ +define(function (require, exports, module) { + const CodeInspection = brackets.getModule("language/CodeInspection"); + + const GRAMMAR_CHECKER_NAME = "GrammarChecker"; + const supportedExtensions = [ + "txt", + "md", + "markdown", + "html", + "htm", + "js", + "ts", + "jsx", + "tsx", + "css", + "less", + "scss" + ]; + + const GRAMMAR_ERRORS = [ + { pattern: /\bthere\s+house\b/gi, suggestion: "their house", message: "Did you mean 'their house'?" }, + { pattern: /\bits\s+self\b/gi, suggestion: "itself", message: "Did you mean 'itself'?" }, + { pattern: /\byour\s+welcome\b/gi, suggestion: "you're welcome", message: "Did you mean 'you're welcome'?" }, + { pattern: /\bto\s+many\b/gi, suggestion: "too many", message: "Did you mean 'too many'?" }, + { pattern: /\bwould\s+of\b/gi, suggestion: "would have", message: "Did you mean 'would have'?" }, + { pattern: /\bcould\s+of\b/gi, suggestion: "could have", message: "Did you mean 'could have'?" }, + { pattern: /\bshould\s+of\b/gi, suggestion: "should have", message: "Did you mean 'should have'?" }, + { pattern: /\balot\b/gi, suggestion: "a lot", message: "Did you mean 'a lot'?" } + ]; + + /** + * Check for grammar errors in the text + * + * @param {string} text - the text to check + * @param {number} lineNumber - the line number (0-based) + * @returns {Array} Array of spell error objects + */ + function checkGrammar(text, lineNumber) { + const errors = []; + + GRAMMAR_ERRORS.forEach(function (rule) { + let match; + while ((match = rule.pattern.exec(text)) !== null) { + errors.push({ + pos: { line: lineNumber, ch: match.index }, + endPos: { line: lineNumber, ch: match.index + match[0].length }, + message: rule.message, + type: CodeInspection.Type.META // META type for blue underline + }); + } + }); + + return errors; + } + + /** + * This function is responsible to run grammar check on the given text + * TODO: right now we just check the whole file. later need to make it efficient + * + * @param {string} text - The text content to check + * @param {string} fullPath - The full path to the file + * @returns {Object} Results object with errors array + */ + function lintOneFile(text, fullPath) { + const fileExtension = fullPath.split(".").pop().toLowerCase(); + + if (!supportedExtensions.includes(fileExtension)) { + return null; + } + + const lines = text.split("\n"); + const allErrors = []; + + lines.forEach(function (line, lineIndex) { + const grammarErrors = checkGrammar(line, lineIndex); + allErrors.push(...grammarErrors); + }); + + if (allErrors.length > 0) { + return { errors: allErrors }; + } + + return null; + } + + /** + * Initialize the grammar checker + * this function is called inside main.js + */ + function init() { + CodeInspection.register("text", { + name: GRAMMAR_CHECKER_NAME, + scanFile: lintOneFile + }); + + supportedExtensions.forEach(function (languageId) { + CodeInspection.register(languageId, { + name: GRAMMAR_CHECKER_NAME, + scanFile: lintOneFile + }); + }); + } + + exports.init = init; +}); diff --git a/src/extensions/default/SpellGrammarCheck/main.js b/src/extensions/default/SpellGrammarCheck/main.js new file mode 100644 index 0000000000..0af78b8eb3 --- /dev/null +++ b/src/extensions/default/SpellGrammarCheck/main.js @@ -0,0 +1,30 @@ +/* + * GNU AGPL-3.0 License + * + * Copyright (c) 2021 - present core.ai . All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://opensource.org/licenses/AGPL-3.0. + * + */ + +/** + * Spell and Grammar Check Extension + */ +define(function (require, exports, module) { + const SpellChecker = require("./spell-checker"); + const GrammarChecker = require("./grammar-checker"); + + SpellChecker.init(); + GrammarChecker.init(); +}); diff --git a/src/extensions/default/SpellGrammarCheck/package.json b/src/extensions/default/SpellGrammarCheck/package.json new file mode 100644 index 0000000000..5b136b2fca --- /dev/null +++ b/src/extensions/default/SpellGrammarCheck/package.json @@ -0,0 +1,5 @@ +{ + "name": "SpellGrammarCheck", + "version": "1.0.0", + "dependencies": {} +} diff --git a/src/extensions/default/SpellGrammarCheck/spell-checker.js b/src/extensions/default/SpellGrammarCheck/spell-checker.js new file mode 100644 index 0000000000..e8e986cbf1 --- /dev/null +++ b/src/extensions/default/SpellGrammarCheck/spell-checker.js @@ -0,0 +1,123 @@ +define(function (require, exports, module) { + const CodeInspection = brackets.getModule("language/CodeInspection"); + + const SPELL_CHECKER_NAME = "SpellChecker"; + const supportedExtensions = [ + "txt", + "md", + "markdown", + "html", + "htm", + "js", + "ts", + "jsx", + "tsx", + "css", + "less", + "scss" + ]; + + const MISSPELLED_WORDS = ["teh", "adn", "wich", "thier"]; + + /** + * This function is responsible for giving spelling suggestions for a misspelled word + * + * @param {string} word - The misspelled word + * @returns {Array} Array of suggestions + */ + function getSuggestions(word) { + const suggestions = { + teh: ["the"], + adn: ["and"], + wich: ["which"], + thier: ["their"] + }; + + return suggestions[word] || [word]; + } + + /** + * Check for spelling errors in the text + * + * @param {string} text - the text to check + * @param {number} lineNumber - the line number (0-based) + * @returns {Array} Array of spell error objects + */ + function checkSpelling(text, lineNumber) { + const errors = []; + const words = text.split(/\s+/); + let currentPos = 0; + + words.forEach(function (word) { + // remove punctuation for checking + const cleanWord = word.replace(/[^\w]/g, "").toLowerCase(); + + if (cleanWord && MISSPELLED_WORDS.includes(cleanWord)) { + const wordStart = text.indexOf(word, currentPos); + const wordEnd = wordStart + word.length; + + errors.push({ + pos: { line: lineNumber, ch: wordStart }, + endPos: { line: lineNumber, ch: wordEnd }, + message: ` + "${word}" may be misspelled. Did you mean one of: ${getSuggestions(cleanWord).join(", ")}? + `, + type: CodeInspection.Type.SPELL + }); + } + currentPos = text.indexOf(word, currentPos) + word.length; + }); + + return errors; + } + + /** + * This function is responsible to run spell check on the given text + * TODO: right now we just check the whole file. later need to make it efficient + * + * @param {string} text - The text content to check + * @param {string} fullPath - The full path to the file + * @returns {Object} Results object with errors array + */ + function lintOneFile(text, fullPath) { + const fileExtension = fullPath.split(".").pop().toLowerCase(); + + if (!supportedExtensions.includes(fileExtension)) { + return null; + } + + const lines = text.split("\n"); + const allErrors = []; + + lines.forEach(function (line, lineIndex) { + const spellErrors = checkSpelling(line, lineIndex); + allErrors.push(...spellErrors); + }); + + if (allErrors.length > 0) { + return { errors: allErrors }; + } + + return null; + } + + /** + * Initialize the spell checker + * this function is called inside main.js + */ + function init() { + CodeInspection.register("text", { + name: SPELL_CHECKER_NAME, + scanFile: lintOneFile + }); + + supportedExtensions.forEach(function (languageId) { + CodeInspection.register(languageId, { + name: SPELL_CHECKER_NAME, + scanFile: lintOneFile + }); + }); + } + + exports.init = init; +}); From f6f894ff91866d70d002a4bc46e45611fb18f192 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 31 May 2025 01:37:12 +0530 Subject: [PATCH 4/4] chore: auto update API docs --- docs/API-Reference/language/CodeInspection.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/API-Reference/language/CodeInspection.md b/docs/API-Reference/language/CodeInspection.md index 3993007c05..ba029906f5 100644 --- a/docs/API-Reference/language/CodeInspection.md +++ b/docs/API-Reference/language/CodeInspection.md @@ -34,6 +34,7 @@ Values for problem's 'type' property * [.ERROR](#Type.ERROR) * [.WARNING](#Type.WARNING) * [.META](#Type.META) + * [.SPELL](#Type.SPELL) @@ -52,6 +53,12 @@ Maintainability issue, probable error / bad smell, etc. ### Type.META Inspector unable to continue, code too complex for static analysis, etc. Not counted in err/warn tally. +**Kind**: static property of [Type](#Type) + + +### Type.SPELL +For spelling or grammatical error + **Kind**: static property of [Type](#Type)