@power-seo/readability
Advanced tools
+21
| MIT License | ||
| Copyright (c) 2026 CCBD SEO Contributors | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
+66
-34
@@ -1,6 +0,34 @@ | ||
| 'use strict'; | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var core = require('@power-seo/core'); | ||
| // src/index.ts | ||
| var index_exports = {}; | ||
| __export(index_exports, { | ||
| analyzeReadability: () => analyzeReadability, | ||
| automatedReadability: () => automatedReadability, | ||
| colemanLiau: () => colemanLiau, | ||
| fleschKincaidGrade: () => fleschKincaidGrade, | ||
| fleschReadingEase: () => fleschReadingEase, | ||
| gunningFog: () => gunningFog | ||
| }); | ||
| module.exports = __toCommonJS(index_exports); | ||
| // src/analyzer.ts | ||
| var import_core = require("@power-seo/core"); | ||
@@ -100,6 +128,6 @@ // src/algorithms/flesch-kincaid.ts | ||
| const { content } = input; | ||
| const stats = core.getTextStatistics(content); | ||
| const text = core.stripHtml(content); | ||
| const sentences = core.getSentences(content); | ||
| const paragraphs = core.getParagraphs(content); | ||
| const stats = (0, import_core.getTextStatistics)(content); | ||
| const text = (0, import_core.stripHtml)(content); | ||
| const sentences = (0, import_core.getSentences)(content); | ||
| const paragraphs = (0, import_core.getParagraphs)(content); | ||
| const fre = fleschReadingEase(stats); | ||
@@ -111,3 +139,3 @@ const fkg = fleschKincaidGrade(stats); | ||
| const wordCount = s.split(/\s+/).filter((w) => w.length > 0).length; | ||
| return wordCount > core.READABILITY.MAX_SENTENCE_LENGTH; | ||
| return wordCount > import_core.READABILITY.MAX_SENTENCE_LENGTH; | ||
| }); | ||
@@ -117,3 +145,3 @@ const longSentencePercentage = sentences.length > 0 ? Math.round(longSentences.length / sentences.length * 1e3) / 10 : 0; | ||
| const wordCount = p.split(/\s+/).filter((w) => w.length > 0).length; | ||
| return wordCount > core.READABILITY.MAX_PARAGRAPH_WORDS; | ||
| return wordCount > import_core.READABILITY.MAX_PARAGRAPH_WORDS; | ||
| }).length; | ||
@@ -125,3 +153,3 @@ const transitionCount = countTransitionSentences(sentences); | ||
| const recommendations = []; | ||
| if (fre >= core.READABILITY.FLESCH_EASE_GOOD) { | ||
| if (fre >= import_core.READABILITY.FLESCH_EASE_GOOD) { | ||
| results.push({ | ||
@@ -135,3 +163,3 @@ id: "flesch-reading-ease", | ||
| }); | ||
| } else if (fre >= core.READABILITY.FLESCH_EASE_FAIR) { | ||
| } else if (fre >= import_core.READABILITY.FLESCH_EASE_FAIR) { | ||
| results.push({ | ||
@@ -165,3 +193,3 @@ id: "flesch-reading-ease", | ||
| title: "Sentence length", | ||
| description: `${longSentencePercentage}% of sentences are longer than ${core.READABILITY.MAX_SENTENCE_LENGTH} words. Good variety.`, | ||
| description: `${longSentencePercentage}% of sentences are longer than ${import_core.READABILITY.MAX_SENTENCE_LENGTH} words. Good variety.`, | ||
| status: "good", | ||
@@ -175,3 +203,3 @@ score: 5, | ||
| title: "Sentence length", | ||
| description: `${longSentencePercentage}% of sentences are longer than ${core.READABILITY.MAX_SENTENCE_LENGTH} words. Try to shorten some.`, | ||
| description: `${longSentencePercentage}% of sentences are longer than ${import_core.READABILITY.MAX_SENTENCE_LENGTH} words. Try to shorten some.`, | ||
| status: "ok", | ||
@@ -182,3 +210,3 @@ score: 3, | ||
| recommendations.push( | ||
| `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${core.READABILITY.MAX_SENTENCE_LENGTH} words.` | ||
| `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${import_core.READABILITY.MAX_SENTENCE_LENGTH} words.` | ||
| ); | ||
@@ -189,3 +217,3 @@ } else { | ||
| title: "Sentence length", | ||
| description: `${longSentencePercentage}% of sentences are longer than ${core.READABILITY.MAX_SENTENCE_LENGTH} words. Many sentences need to be shortened.`, | ||
| description: `${longSentencePercentage}% of sentences are longer than ${import_core.READABILITY.MAX_SENTENCE_LENGTH} words. Many sentences need to be shortened.`, | ||
| status: "poor", | ||
@@ -196,6 +224,6 @@ score: 1, | ||
| recommendations.push( | ||
| `${longSentencePercentage}% of your sentences exceed ${core.READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.` | ||
| `${longSentencePercentage}% of your sentences exceed ${import_core.READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.` | ||
| ); | ||
| } | ||
| if (passiveVoicePercentage <= core.READABILITY.MAX_PASSIVE_VOICE_PERCENT) { | ||
| if (passiveVoicePercentage <= import_core.READABILITY.MAX_PASSIVE_VOICE_PERCENT) { | ||
| results.push({ | ||
@@ -209,3 +237,3 @@ id: "passive-voice", | ||
| }); | ||
| } else if (passiveVoicePercentage <= core.READABILITY.MAX_PASSIVE_VOICE_PERCENT * 2) { | ||
| } else if (passiveVoicePercentage <= import_core.READABILITY.MAX_PASSIVE_VOICE_PERCENT * 2) { | ||
| results.push({ | ||
@@ -235,3 +263,3 @@ id: "passive-voice", | ||
| } | ||
| if (transitionWordPercentage >= core.READABILITY.MIN_TRANSITION_WORD_PERCENT) { | ||
| if (transitionWordPercentage >= import_core.READABILITY.MIN_TRANSITION_WORD_PERCENT) { | ||
| results.push({ | ||
@@ -245,3 +273,3 @@ id: "transition-words", | ||
| }); | ||
| } else if (transitionWordPercentage >= core.READABILITY.MIN_TRANSITION_WORD_PERCENT / 2) { | ||
| } else if (transitionWordPercentage >= import_core.READABILITY.MIN_TRANSITION_WORD_PERCENT / 2) { | ||
| results.push({ | ||
@@ -284,3 +312,3 @@ id: "transition-words", | ||
| title: "Paragraph length", | ||
| description: `${longParagraphCount} paragraph${longParagraphCount === 1 ? "" : "s"} exceed${longParagraphCount === 1 ? "s" : ""} ${core.READABILITY.MAX_PARAGRAPH_WORDS} words. Break them up for better readability.`, | ||
| description: `${longParagraphCount} paragraph${longParagraphCount === 1 ? "" : "s"} exceed${longParagraphCount === 1 ? "s" : ""} ${import_core.READABILITY.MAX_PARAGRAPH_WORDS} words. Break them up for better readability.`, | ||
| status: longParagraphCount <= 2 ? "ok" : "poor", | ||
@@ -291,3 +319,3 @@ score: longParagraphCount <= 2 ? 3 : 1, | ||
| recommendations.push( | ||
| `${longParagraphCount} paragraph${longParagraphCount === 1 ? " is" : "s are"} too long. Keep paragraphs under ${core.READABILITY.MAX_PARAGRAPH_WORDS} words.` | ||
| `${longParagraphCount} paragraph${longParagraphCount === 1 ? " is" : "s are"} too long. Keep paragraphs under ${import_core.READABILITY.MAX_PARAGRAPH_WORDS} words.` | ||
| ); | ||
@@ -309,6 +337,9 @@ } | ||
| } | ||
| // src/algorithms/gunning-fog.ts | ||
| var import_core2 = require("@power-seo/core"); | ||
| function gunningFog(content) { | ||
| const text = core.stripHtml(content); | ||
| const words = core.getWords(content); | ||
| const sentences = core.getSentences(content); | ||
| const text = (0, import_core2.stripHtml)(content); | ||
| const words = (0, import_core2.getWords)(content); | ||
| const sentences = (0, import_core2.getSentences)(content); | ||
| if (words.length === 0 || sentences.length === 0) return 0; | ||
@@ -327,6 +358,6 @@ const complexWords = countComplexWords(text); | ||
| if (!cleaned) continue; | ||
| const syllables = core.countSyllables(cleaned); | ||
| const syllables = (0, import_core2.countSyllables)(cleaned); | ||
| if (syllables < 3) continue; | ||
| const withoutSuffix = cleaned.replace(/ing$/, "").replace(/ed$/, "").replace(/es$/, ""); | ||
| if (withoutSuffix !== cleaned && core.countSyllables(withoutSuffix) < 3) { | ||
| if (withoutSuffix !== cleaned && (0, import_core2.countSyllables)(withoutSuffix) < 3) { | ||
| continue; | ||
@@ -357,10 +388,11 @@ } | ||
| } | ||
| exports.analyzeReadability = analyzeReadability; | ||
| exports.automatedReadability = automatedReadability; | ||
| exports.colemanLiau = colemanLiau; | ||
| exports.fleschKincaidGrade = fleschKincaidGrade; | ||
| exports.fleschReadingEase = fleschReadingEase; | ||
| exports.gunningFog = gunningFog; | ||
| //# sourceMappingURL=index.cjs.map | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| analyzeReadability, | ||
| automatedReadability, | ||
| colemanLiau, | ||
| fleschKincaidGrade, | ||
| fleschReadingEase, | ||
| gunningFog | ||
| }); | ||
| //# sourceMappingURL=index.cjs.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/algorithms/flesch-kincaid.ts","../src/analyzer.ts","../src/algorithms/gunning-fog.ts","../src/algorithms/coleman-liau.ts","../src/algorithms/automated-readability.ts"],"names":["getTextStatistics","stripHtml","getSentences","getParagraphs","READABILITY","getWords","countSyllables"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/readability — Flesch-Kincaid Algorithms\n// ============================================================================\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Flesch Reading Ease score.\n *\n * Formula: 206.835 - 1.015 * (words/sentences) - 84.6 * (syllables/words)\n *\n * Scale:\n * - 90-100: Very Easy (5th grade)\n * - 80-89: Easy (6th grade)\n * - 70-79: Fairly Easy (7th grade)\n * - 60-69: Standard (8th-9th grade)\n * - 50-59: Fairly Difficult (10th-12th grade)\n * - 30-49: Difficult (College)\n * - 0-29: Very Confusing (Graduate)\n */\nexport function fleschReadingEase(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const score = 206.835 - 1.015 * stats.avgWordsPerSentence - 84.6 * stats.avgSyllablesPerWord;\n\n return Math.round(Math.max(0, Math.min(100, score)) * 100) / 100;\n}\n\n/**\n * Calculate the Flesch-Kincaid Grade Level.\n *\n * Formula: 0.39 * (words/sentences) + 11.8 * (syllables/words) - 15.59\n *\n * Returns a US school grade level (e.g., 8.0 = 8th grade).\n */\nexport function fleschKincaidGrade(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const grade = 0.39 * stats.avgWordsPerSentence + 11.8 * stats.avgSyllablesPerWord - 15.59;\n\n return Math.round(Math.max(0, grade) * 100) / 100;\n}\n","// ============================================================================\n// @power-seo/readability — Combined Readability Analyzer\n// ============================================================================\n\nimport type { ReadabilityInput, ReadabilityOutput, AnalysisResult } from '@power-seo/core';\nimport {\n getTextStatistics,\n getSentences,\n getParagraphs,\n stripHtml,\n READABILITY,\n} from '@power-seo/core';\nimport { fleschReadingEase, fleschKincaidGrade } from './algorithms/flesch-kincaid.js';\n\n// --- Passive Voice Detection ---\n\nconst PASSIVE_AUXILIARIES = ['am', 'is', 'are', 'was', 'were', 'be', 'been', 'being'];\nconst PASSIVE_REGEX = new RegExp(\n `\\\\b(${PASSIVE_AUXILIARIES.join('|')})\\\\s+\\\\w+(?:ed|en|t)\\\\b`,\n 'gi',\n);\n\nfunction countPassiveVoice(text: string): number {\n const matches = text.match(PASSIVE_REGEX);\n return matches?.length ?? 0;\n}\n\n// --- Transition Word Detection ---\n\nconst TRANSITION_WORDS = [\n 'accordingly',\n 'additionally',\n 'also',\n 'although',\n 'as a result',\n 'because',\n 'besides',\n 'but',\n 'certainly',\n 'consequently',\n 'conversely',\n 'equally',\n 'eventually',\n 'finally',\n 'first',\n 'for example',\n 'for instance',\n 'furthermore',\n 'hence',\n 'however',\n 'in addition',\n 'in conclusion',\n 'in contrast',\n 'in fact',\n 'in other words',\n 'in particular',\n 'in summary',\n 'indeed',\n 'instead',\n 'likewise',\n 'meanwhile',\n 'moreover',\n 'namely',\n 'nevertheless',\n 'next',\n 'nonetheless',\n 'notably',\n 'on the other hand',\n 'otherwise',\n 'overall',\n 'particularly',\n 'rather',\n 'second',\n 'similarly',\n 'since',\n 'specifically',\n 'still',\n 'subsequently',\n 'such as',\n 'then',\n 'therefore',\n 'third',\n 'thus',\n 'to illustrate',\n 'ultimately',\n 'whereas',\n 'yet',\n];\n\nfunction countTransitionSentences(sentences: string[]): number {\n let count = 0;\n for (const sentence of sentences) {\n const lower = sentence.toLowerCase();\n if (TRANSITION_WORDS.some((tw) => lower.includes(tw))) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Analyze the readability of content using multiple algorithms.\n *\n * Returns a combined `ReadabilityOutput` with individual algorithm scores,\n * traffic-light results, and actionable recommendations.\n *\n * @example\n * ```ts\n * const result = analyzeReadability({\n * content: '<p>Your article content here...</p>',\n * });\n * console.log(result.fleschReadingEase, result.recommendations);\n * ```\n */\nexport function analyzeReadability(input: ReadabilityInput): ReadabilityOutput {\n const { content } = input;\n const stats = getTextStatistics(content);\n const text = stripHtml(content);\n const sentences = getSentences(content);\n const paragraphs = getParagraphs(content);\n // Algorithm scores\n const fre = fleschReadingEase(stats);\n const fkg = fleschKincaidGrade(stats);\n\n // Passive voice analysis\n const passiveCount = countPassiveVoice(text);\n const passiveVoicePercentage =\n sentences.length > 0 ? Math.round((passiveCount / sentences.length) * 1000) / 10 : 0;\n\n // Long sentence analysis\n const longSentences = sentences.filter((s) => {\n const wordCount = s.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_SENTENCE_LENGTH;\n });\n const longSentencePercentage =\n sentences.length > 0 ? Math.round((longSentences.length / sentences.length) * 1000) / 10 : 0;\n\n // Long paragraph analysis\n const longParagraphCount = paragraphs.filter((p) => {\n const wordCount = p.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_PARAGRAPH_WORDS;\n }).length;\n\n // Transition word analysis\n const transitionCount = countTransitionSentences(sentences);\n const transitionWordPercentage =\n sentences.length > 0 ? Math.round((transitionCount / sentences.length) * 1000) / 10 : 0;\n\n // Normalized overall score: 0-100 based on Flesch Reading Ease\n const score = Math.round(fre);\n\n // Build results\n const results: AnalysisResult[] = [];\n const recommendations: string[] = [];\n\n // Flesch Reading Ease result\n if (fre >= READABILITY.FLESCH_EASE_GOOD) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is easy to read.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (fre >= READABILITY.FLESCH_EASE_FAIR) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is fairly difficult to read. Try shorter sentences and simpler words.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n 'Simplify your writing — use shorter sentences and common words to improve readability.',\n );\n } else {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is very difficult to read. Significantly simplify your writing.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n 'Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives.',\n );\n }\n\n // Sentence length result\n if (longSentencePercentage <= 25) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Good variety.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (longSentencePercentage <= 40) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Try to shorten some.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.`,\n );\n } else {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Many sentences need to be shortened.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`,\n );\n }\n\n // Passive voice result\n if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. This is within the recommended limit.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT * 2) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Try to use more active voice.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`,\n );\n } else {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Rewrite using active voice.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`,\n );\n }\n\n // Transition words result\n if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Good flow.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT / 2) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Use more to improve flow.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Use more transition words (currently ${transitionWordPercentage}%). Words like \"however\", \"therefore\", and \"for example\" improve readability.`,\n );\n } else {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Add more to connect your ideas.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like \"however\", \"in addition\", and \"therefore\" to guide readers.`,\n );\n }\n\n // Paragraph length result\n if (longParagraphCount === 0) {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: 'All paragraphs are a reasonable length.',\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: `${longParagraphCount} paragraph${longParagraphCount === 1 ? '' : 's'} exceed${longParagraphCount === 1 ? 's' : ''} ${READABILITY.MAX_PARAGRAPH_WORDS} words. Break them up for better readability.`,\n status: longParagraphCount <= 2 ? 'ok' : 'poor',\n score: longParagraphCount <= 2 ? 3 : 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longParagraphCount} paragraph${longParagraphCount === 1 ? ' is' : 's are'} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.`,\n );\n }\n\n return {\n score,\n fleschReadingEase: fre,\n fleschKincaidGrade: fkg,\n avgSentenceLength: stats.avgWordsPerSentence,\n avgSyllablesPerWord: stats.avgSyllablesPerWord,\n passiveVoicePercentage,\n longSentencePercentage,\n longParagraphCount,\n transitionWordPercentage,\n results,\n recommendations,\n };\n}\n","// ============================================================================\n// @power-seo/readability — Gunning Fog Index\n// ============================================================================\n\nimport { getWords, getSentences, countSyllables, stripHtml } from '@power-seo/core';\n\n/**\n * Calculate the Gunning Fog Index.\n *\n * Formula: 0.4 * [(words/sentences) + 100 * (complex words/words)]\n *\n * \"Complex words\" are words with 3 or more syllables, excluding:\n * - Proper nouns (capitalized words that aren't sentence-starters)\n * - Common suffixes (-es, -ed, -ing) that push words to 3+ syllables\n *\n * Returns a US school grade level.\n */\nexport function gunningFog(content: string): number {\n const text = stripHtml(content);\n const words = getWords(content);\n const sentences = getSentences(content);\n\n if (words.length === 0 || sentences.length === 0) return 0;\n\n const complexWords = countComplexWords(text);\n const avgSentenceLength = words.length / sentences.length;\n const percentComplex = (complexWords / words.length) * 100;\n\n const index = 0.4 * (avgSentenceLength + percentComplex);\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n\n/**\n * Count complex words (3+ syllables), excluding common inflected forms.\n */\nfunction countComplexWords(text: string): number {\n const words = text.split(/\\s+/).filter((w) => w.length > 0);\n let count = 0;\n\n for (const word of words) {\n const cleaned = word.replace(/[^a-zA-Z]/g, '').toLowerCase();\n if (!cleaned) continue;\n\n const syllables = countSyllables(cleaned);\n if (syllables < 3) continue;\n\n // Exclude words that are 3+ syllables only due to common suffixes\n const withoutSuffix = cleaned.replace(/ing$/, '').replace(/ed$/, '').replace(/es$/, '');\n\n if (withoutSuffix !== cleaned && countSyllables(withoutSuffix) < 3) {\n continue;\n }\n\n count++;\n }\n\n return count;\n}\n","// ============================================================================\n// @power-seo/readability — Coleman-Liau Index\n// ============================================================================\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Coleman-Liau Index.\n *\n * Formula: 0.0588 * L - 0.296 * S - 15.8\n *\n * Where:\n * - L = average number of letters per 100 words\n * - S = average number of sentences per 100 words\n *\n * Returns a US school grade level.\n */\nexport function colemanLiau(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n // L: average letters per 100 words\n // characterCount from core includes spaces, so count only letters\n const letterCount = stats.characterCount - (stats.wordCount - 1); // subtract spaces between words\n const L = (letterCount / stats.wordCount) * 100;\n\n // S: average sentences per 100 words\n const S = (stats.sentenceCount / stats.wordCount) * 100;\n\n const index = 0.0588 * L - 0.296 * S - 15.8;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n","// ============================================================================\n// @power-seo/readability — Automated Readability Index (ARI)\n// ============================================================================\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Automated Readability Index (ARI).\n *\n * Formula: 4.71 * (characters/words) + 0.5 * (words/sentences) - 21.43\n *\n * Returns a US school grade level.\n */\nexport function automatedReadability(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const charsPerWord = stats.characterCount / stats.wordCount;\n const wordsPerSentence = stats.wordCount / stats.sentenceCount;\n\n const index = 4.71 * charsPerWord + 0.5 * wordsPerSentence - 21.43;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n"]} | ||
| {"version":3,"sources":["../src/index.ts","../src/analyzer.ts","../src/algorithms/flesch-kincaid.ts","../src/algorithms/gunning-fog.ts","../src/algorithms/coleman-liau.ts","../src/algorithms/automated-readability.ts"],"sourcesContent":["// @power-seo/readability — Public API\n// ----------------------------------------------------------------------------\n\nexport { analyzeReadability } from './analyzer.js';\nexport { fleschReadingEase, fleschKincaidGrade } from './algorithms/flesch-kincaid.js';\nexport { gunningFog } from './algorithms/gunning-fog.js';\nexport { colemanLiau } from './algorithms/coleman-liau.js';\nexport { automatedReadability } from './algorithms/automated-readability.js';\n\nexport type {\n ReadabilityInput,\n ReadabilityOutput,\n TextStatistics,\n AnalysisResult,\n AnalysisStatus,\n AlgorithmScore,\n} from './types.js';\n","// @power-seo/readability — Combined Readability Analyzer\n// ----------------------------------------------------------------------------\n\nimport type { ReadabilityInput, ReadabilityOutput, AnalysisResult } from '@power-seo/core';\nimport {\n getTextStatistics,\n getSentences,\n getParagraphs,\n stripHtml,\n READABILITY,\n} from '@power-seo/core';\nimport { fleschReadingEase, fleschKincaidGrade } from './algorithms/flesch-kincaid.js';\n\n// --- Passive Voice Detection ---\n\nconst PASSIVE_AUXILIARIES = ['am', 'is', 'are', 'was', 'were', 'be', 'been', 'being'];\nconst PASSIVE_REGEX = new RegExp(\n `\\\\b(${PASSIVE_AUXILIARIES.join('|')})\\\\s+\\\\w+(?:ed|en|t)\\\\b`,\n 'gi',\n);\n\nfunction countPassiveVoice(text: string): number {\n const matches = text.match(PASSIVE_REGEX);\n return matches?.length ?? 0;\n}\n\n// --- Transition Word Detection ---\n\nconst TRANSITION_WORDS = [\n 'accordingly',\n 'additionally',\n 'also',\n 'although',\n 'as a result',\n 'because',\n 'besides',\n 'but',\n 'certainly',\n 'consequently',\n 'conversely',\n 'equally',\n 'eventually',\n 'finally',\n 'first',\n 'for example',\n 'for instance',\n 'furthermore',\n 'hence',\n 'however',\n 'in addition',\n 'in conclusion',\n 'in contrast',\n 'in fact',\n 'in other words',\n 'in particular',\n 'in summary',\n 'indeed',\n 'instead',\n 'likewise',\n 'meanwhile',\n 'moreover',\n 'namely',\n 'nevertheless',\n 'next',\n 'nonetheless',\n 'notably',\n 'on the other hand',\n 'otherwise',\n 'overall',\n 'particularly',\n 'rather',\n 'second',\n 'similarly',\n 'since',\n 'specifically',\n 'still',\n 'subsequently',\n 'such as',\n 'then',\n 'therefore',\n 'third',\n 'thus',\n 'to illustrate',\n 'ultimately',\n 'whereas',\n 'yet',\n];\n\nfunction countTransitionSentences(sentences: string[]): number {\n let count = 0;\n for (const sentence of sentences) {\n const lower = sentence.toLowerCase();\n if (TRANSITION_WORDS.some((tw) => lower.includes(tw))) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Analyze the readability of content using multiple algorithms.\n *\n * Returns a combined `ReadabilityOutput` with individual algorithm scores,\n * traffic-light results, and actionable recommendations.\n *\n * @example\n * ```ts\n * const result = analyzeReadability({\n * content: '<p>Your article content here...</p>',\n * });\n * console.log(result.fleschReadingEase, result.recommendations);\n * ```\n */\nexport function analyzeReadability(input: ReadabilityInput): ReadabilityOutput {\n const { content } = input;\n const stats = getTextStatistics(content);\n const text = stripHtml(content);\n const sentences = getSentences(content);\n const paragraphs = getParagraphs(content);\n // Algorithm scores\n const fre = fleschReadingEase(stats);\n const fkg = fleschKincaidGrade(stats);\n\n // Passive voice analysis\n const passiveCount = countPassiveVoice(text);\n const passiveVoicePercentage =\n sentences.length > 0 ? Math.round((passiveCount / sentences.length) * 1000) / 10 : 0;\n\n // Long sentence analysis\n const longSentences = sentences.filter((s) => {\n const wordCount = s.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_SENTENCE_LENGTH;\n });\n const longSentencePercentage =\n sentences.length > 0 ? Math.round((longSentences.length / sentences.length) * 1000) / 10 : 0;\n\n // Long paragraph analysis\n const longParagraphCount = paragraphs.filter((p) => {\n const wordCount = p.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_PARAGRAPH_WORDS;\n }).length;\n\n // Transition word analysis\n const transitionCount = countTransitionSentences(sentences);\n const transitionWordPercentage =\n sentences.length > 0 ? Math.round((transitionCount / sentences.length) * 1000) / 10 : 0;\n\n // Normalized overall score: 0-100 based on Flesch Reading Ease\n const score = Math.round(fre);\n\n // Build results\n const results: AnalysisResult[] = [];\n const recommendations: string[] = [];\n\n // Flesch Reading Ease result\n if (fre >= READABILITY.FLESCH_EASE_GOOD) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is easy to read.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (fre >= READABILITY.FLESCH_EASE_FAIR) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is fairly difficult to read. Try shorter sentences and simpler words.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n 'Simplify your writing — use shorter sentences and common words to improve readability.',\n );\n } else {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is very difficult to read. Significantly simplify your writing.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n 'Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives.',\n );\n }\n\n // Sentence length result\n if (longSentencePercentage <= 25) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Good variety.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (longSentencePercentage <= 40) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Try to shorten some.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.`,\n );\n } else {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Many sentences need to be shortened.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`,\n );\n }\n\n // Passive voice result\n if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. This is within the recommended limit.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT * 2) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Try to use more active voice.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`,\n );\n } else {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Rewrite using active voice.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`,\n );\n }\n\n // Transition words result\n if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Good flow.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT / 2) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Use more to improve flow.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Use more transition words (currently ${transitionWordPercentage}%). Words like \"however\", \"therefore\", and \"for example\" improve readability.`,\n );\n } else {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Add more to connect your ideas.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like \"however\", \"in addition\", and \"therefore\" to guide readers.`,\n );\n }\n\n // Paragraph length result\n if (longParagraphCount === 0) {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: 'All paragraphs are a reasonable length.',\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: `${longParagraphCount} paragraph${longParagraphCount === 1 ? '' : 's'} exceed${longParagraphCount === 1 ? 's' : ''} ${READABILITY.MAX_PARAGRAPH_WORDS} words. Break them up for better readability.`,\n status: longParagraphCount <= 2 ? 'ok' : 'poor',\n score: longParagraphCount <= 2 ? 3 : 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longParagraphCount} paragraph${longParagraphCount === 1 ? ' is' : 's are'} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.`,\n );\n }\n\n return {\n score,\n fleschReadingEase: fre,\n fleschKincaidGrade: fkg,\n avgSentenceLength: stats.avgWordsPerSentence,\n avgSyllablesPerWord: stats.avgSyllablesPerWord,\n passiveVoicePercentage,\n longSentencePercentage,\n longParagraphCount,\n transitionWordPercentage,\n results,\n recommendations,\n };\n}\n","// @power-seo/readability — Flesch-Kincaid Algorithms\n// ----------------------------------------------------------------------------\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Flesch Reading Ease score.\n *\n * Formula: 206.835 - 1.015 * (words/sentences) - 84.6 * (syllables/words)\n *\n * Scale:\n * - 90-100: Very Easy (5th grade)\n * - 80-89: Easy (6th grade)\n * - 70-79: Fairly Easy (7th grade)\n * - 60-69: Standard (8th-9th grade)\n * - 50-59: Fairly Difficult (10th-12th grade)\n * - 30-49: Difficult (College)\n * - 0-29: Very Confusing (Graduate)\n */\nexport function fleschReadingEase(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const score = 206.835 - 1.015 * stats.avgWordsPerSentence - 84.6 * stats.avgSyllablesPerWord;\n\n return Math.round(Math.max(0, Math.min(100, score)) * 100) / 100;\n}\n\n/**\n * Calculate the Flesch-Kincaid Grade Level.\n *\n * Formula: 0.39 * (words/sentences) + 11.8 * (syllables/words) - 15.59\n *\n * Returns a US school grade level (e.g., 8.0 = 8th grade).\n */\nexport function fleschKincaidGrade(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const grade = 0.39 * stats.avgWordsPerSentence + 11.8 * stats.avgSyllablesPerWord - 15.59;\n\n return Math.round(Math.max(0, grade) * 100) / 100;\n}\n","// @power-seo/readability — Gunning Fog Index\n// ----------------------------------------------------------------------------\n\nimport { getWords, getSentences, countSyllables, stripHtml } from '@power-seo/core';\n\n/**\n * Calculate the Gunning Fog Index.\n *\n * Formula: 0.4 * [(words/sentences) + 100 * (complex words/words)]\n *\n * \"Complex words\" are words with 3 or more syllables, excluding:\n * - Proper nouns (capitalized words that aren't sentence-starters)\n * - Common suffixes (-es, -ed, -ing) that push words to 3+ syllables\n *\n * Returns a US school grade level.\n */\nexport function gunningFog(content: string): number {\n const text = stripHtml(content);\n const words = getWords(content);\n const sentences = getSentences(content);\n\n if (words.length === 0 || sentences.length === 0) return 0;\n\n const complexWords = countComplexWords(text);\n const avgSentenceLength = words.length / sentences.length;\n const percentComplex = (complexWords / words.length) * 100;\n\n const index = 0.4 * (avgSentenceLength + percentComplex);\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n\n/**\n * Count complex words (3+ syllables), excluding common inflected forms.\n */\nfunction countComplexWords(text: string): number {\n const words = text.split(/\\s+/).filter((w) => w.length > 0);\n let count = 0;\n\n for (const word of words) {\n const cleaned = word.replace(/[^a-zA-Z]/g, '').toLowerCase();\n if (!cleaned) continue;\n\n const syllables = countSyllables(cleaned);\n if (syllables < 3) continue;\n\n // Exclude words that are 3+ syllables only due to common suffixes\n const withoutSuffix = cleaned.replace(/ing$/, '').replace(/ed$/, '').replace(/es$/, '');\n\n if (withoutSuffix !== cleaned && countSyllables(withoutSuffix) < 3) {\n continue;\n }\n\n count++;\n }\n\n return count;\n}\n","// @power-seo/readability — Coleman-Liau Index\n// ----------------------------------------------------------------------------\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Coleman-Liau Index.\n *\n * Formula: 0.0588 * L - 0.296 * S - 15.8\n *\n * Where:\n * - L = average number of letters per 100 words\n * - S = average number of sentences per 100 words\n *\n * Returns a US school grade level.\n */\nexport function colemanLiau(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n // L: average letters per 100 words\n // characterCount from core includes spaces, so count only letters\n const letterCount = stats.characterCount - (stats.wordCount - 1); // subtract spaces between words\n const L = (letterCount / stats.wordCount) * 100;\n\n // S: average sentences per 100 words\n const S = (stats.sentenceCount / stats.wordCount) * 100;\n\n const index = 0.0588 * L - 0.296 * S - 15.8;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n","// @power-seo/readability — Automated Readability Index (ARI)\n// ----------------------------------------------------------------------------\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Automated Readability Index (ARI).\n *\n * Formula: 4.71 * (characters/words) + 0.5 * (words/sentences) - 21.43\n *\n * Returns a US school grade level.\n */\nexport function automatedReadability(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const charsPerWord = stats.characterCount / stats.wordCount;\n const wordsPerSentence = stats.wordCount / stats.sentenceCount;\n\n const index = 4.71 * charsPerWord + 0.5 * wordsPerSentence - 21.43;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n"],"mappings":"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","names":["import_core"]} |
+20
-7
@@ -1,4 +0,9 @@ | ||
| import { getTextStatistics, stripHtml, getSentences, getParagraphs, READABILITY, getWords, countSyllables } from '@power-seo/core'; | ||
| // src/analyzer.ts | ||
| import { | ||
| getTextStatistics, | ||
| getSentences, | ||
| getParagraphs, | ||
| stripHtml, | ||
| READABILITY | ||
| } from "@power-seo/core"; | ||
@@ -292,6 +297,9 @@ // src/algorithms/flesch-kincaid.ts | ||
| } | ||
| // src/algorithms/gunning-fog.ts | ||
| import { getWords, getSentences as getSentences2, countSyllables, stripHtml as stripHtml2 } from "@power-seo/core"; | ||
| function gunningFog(content) { | ||
| const text = stripHtml(content); | ||
| const text = stripHtml2(content); | ||
| const words = getWords(content); | ||
| const sentences = getSentences(content); | ||
| const sentences = getSentences2(content); | ||
| if (words.length === 0 || sentences.length === 0) return 0; | ||
@@ -339,5 +347,10 @@ const complexWords = countComplexWords(text); | ||
| } | ||
| export { analyzeReadability, automatedReadability, colemanLiau, fleschKincaidGrade, fleschReadingEase, gunningFog }; | ||
| //# sourceMappingURL=index.js.map | ||
| export { | ||
| analyzeReadability, | ||
| automatedReadability, | ||
| colemanLiau, | ||
| fleschKincaidGrade, | ||
| fleschReadingEase, | ||
| gunningFog | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/algorithms/flesch-kincaid.ts","../src/analyzer.ts","../src/algorithms/gunning-fog.ts","../src/algorithms/coleman-liau.ts","../src/algorithms/automated-readability.ts"],"names":["stripHtml","getSentences"],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/readability — Flesch-Kincaid Algorithms\n// ============================================================================\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Flesch Reading Ease score.\n *\n * Formula: 206.835 - 1.015 * (words/sentences) - 84.6 * (syllables/words)\n *\n * Scale:\n * - 90-100: Very Easy (5th grade)\n * - 80-89: Easy (6th grade)\n * - 70-79: Fairly Easy (7th grade)\n * - 60-69: Standard (8th-9th grade)\n * - 50-59: Fairly Difficult (10th-12th grade)\n * - 30-49: Difficult (College)\n * - 0-29: Very Confusing (Graduate)\n */\nexport function fleschReadingEase(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const score = 206.835 - 1.015 * stats.avgWordsPerSentence - 84.6 * stats.avgSyllablesPerWord;\n\n return Math.round(Math.max(0, Math.min(100, score)) * 100) / 100;\n}\n\n/**\n * Calculate the Flesch-Kincaid Grade Level.\n *\n * Formula: 0.39 * (words/sentences) + 11.8 * (syllables/words) - 15.59\n *\n * Returns a US school grade level (e.g., 8.0 = 8th grade).\n */\nexport function fleschKincaidGrade(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const grade = 0.39 * stats.avgWordsPerSentence + 11.8 * stats.avgSyllablesPerWord - 15.59;\n\n return Math.round(Math.max(0, grade) * 100) / 100;\n}\n","// ============================================================================\n// @power-seo/readability — Combined Readability Analyzer\n// ============================================================================\n\nimport type { ReadabilityInput, ReadabilityOutput, AnalysisResult } from '@power-seo/core';\nimport {\n getTextStatistics,\n getSentences,\n getParagraphs,\n stripHtml,\n READABILITY,\n} from '@power-seo/core';\nimport { fleschReadingEase, fleschKincaidGrade } from './algorithms/flesch-kincaid.js';\n\n// --- Passive Voice Detection ---\n\nconst PASSIVE_AUXILIARIES = ['am', 'is', 'are', 'was', 'were', 'be', 'been', 'being'];\nconst PASSIVE_REGEX = new RegExp(\n `\\\\b(${PASSIVE_AUXILIARIES.join('|')})\\\\s+\\\\w+(?:ed|en|t)\\\\b`,\n 'gi',\n);\n\nfunction countPassiveVoice(text: string): number {\n const matches = text.match(PASSIVE_REGEX);\n return matches?.length ?? 0;\n}\n\n// --- Transition Word Detection ---\n\nconst TRANSITION_WORDS = [\n 'accordingly',\n 'additionally',\n 'also',\n 'although',\n 'as a result',\n 'because',\n 'besides',\n 'but',\n 'certainly',\n 'consequently',\n 'conversely',\n 'equally',\n 'eventually',\n 'finally',\n 'first',\n 'for example',\n 'for instance',\n 'furthermore',\n 'hence',\n 'however',\n 'in addition',\n 'in conclusion',\n 'in contrast',\n 'in fact',\n 'in other words',\n 'in particular',\n 'in summary',\n 'indeed',\n 'instead',\n 'likewise',\n 'meanwhile',\n 'moreover',\n 'namely',\n 'nevertheless',\n 'next',\n 'nonetheless',\n 'notably',\n 'on the other hand',\n 'otherwise',\n 'overall',\n 'particularly',\n 'rather',\n 'second',\n 'similarly',\n 'since',\n 'specifically',\n 'still',\n 'subsequently',\n 'such as',\n 'then',\n 'therefore',\n 'third',\n 'thus',\n 'to illustrate',\n 'ultimately',\n 'whereas',\n 'yet',\n];\n\nfunction countTransitionSentences(sentences: string[]): number {\n let count = 0;\n for (const sentence of sentences) {\n const lower = sentence.toLowerCase();\n if (TRANSITION_WORDS.some((tw) => lower.includes(tw))) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Analyze the readability of content using multiple algorithms.\n *\n * Returns a combined `ReadabilityOutput` with individual algorithm scores,\n * traffic-light results, and actionable recommendations.\n *\n * @example\n * ```ts\n * const result = analyzeReadability({\n * content: '<p>Your article content here...</p>',\n * });\n * console.log(result.fleschReadingEase, result.recommendations);\n * ```\n */\nexport function analyzeReadability(input: ReadabilityInput): ReadabilityOutput {\n const { content } = input;\n const stats = getTextStatistics(content);\n const text = stripHtml(content);\n const sentences = getSentences(content);\n const paragraphs = getParagraphs(content);\n // Algorithm scores\n const fre = fleschReadingEase(stats);\n const fkg = fleschKincaidGrade(stats);\n\n // Passive voice analysis\n const passiveCount = countPassiveVoice(text);\n const passiveVoicePercentage =\n sentences.length > 0 ? Math.round((passiveCount / sentences.length) * 1000) / 10 : 0;\n\n // Long sentence analysis\n const longSentences = sentences.filter((s) => {\n const wordCount = s.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_SENTENCE_LENGTH;\n });\n const longSentencePercentage =\n sentences.length > 0 ? Math.round((longSentences.length / sentences.length) * 1000) / 10 : 0;\n\n // Long paragraph analysis\n const longParagraphCount = paragraphs.filter((p) => {\n const wordCount = p.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_PARAGRAPH_WORDS;\n }).length;\n\n // Transition word analysis\n const transitionCount = countTransitionSentences(sentences);\n const transitionWordPercentage =\n sentences.length > 0 ? Math.round((transitionCount / sentences.length) * 1000) / 10 : 0;\n\n // Normalized overall score: 0-100 based on Flesch Reading Ease\n const score = Math.round(fre);\n\n // Build results\n const results: AnalysisResult[] = [];\n const recommendations: string[] = [];\n\n // Flesch Reading Ease result\n if (fre >= READABILITY.FLESCH_EASE_GOOD) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is easy to read.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (fre >= READABILITY.FLESCH_EASE_FAIR) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is fairly difficult to read. Try shorter sentences and simpler words.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n 'Simplify your writing — use shorter sentences and common words to improve readability.',\n );\n } else {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is very difficult to read. Significantly simplify your writing.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n 'Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives.',\n );\n }\n\n // Sentence length result\n if (longSentencePercentage <= 25) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Good variety.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (longSentencePercentage <= 40) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Try to shorten some.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.`,\n );\n } else {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Many sentences need to be shortened.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`,\n );\n }\n\n // Passive voice result\n if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. This is within the recommended limit.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT * 2) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Try to use more active voice.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`,\n );\n } else {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Rewrite using active voice.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`,\n );\n }\n\n // Transition words result\n if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Good flow.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT / 2) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Use more to improve flow.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Use more transition words (currently ${transitionWordPercentage}%). Words like \"however\", \"therefore\", and \"for example\" improve readability.`,\n );\n } else {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Add more to connect your ideas.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like \"however\", \"in addition\", and \"therefore\" to guide readers.`,\n );\n }\n\n // Paragraph length result\n if (longParagraphCount === 0) {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: 'All paragraphs are a reasonable length.',\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: `${longParagraphCount} paragraph${longParagraphCount === 1 ? '' : 's'} exceed${longParagraphCount === 1 ? 's' : ''} ${READABILITY.MAX_PARAGRAPH_WORDS} words. Break them up for better readability.`,\n status: longParagraphCount <= 2 ? 'ok' : 'poor',\n score: longParagraphCount <= 2 ? 3 : 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longParagraphCount} paragraph${longParagraphCount === 1 ? ' is' : 's are'} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.`,\n );\n }\n\n return {\n score,\n fleschReadingEase: fre,\n fleschKincaidGrade: fkg,\n avgSentenceLength: stats.avgWordsPerSentence,\n avgSyllablesPerWord: stats.avgSyllablesPerWord,\n passiveVoicePercentage,\n longSentencePercentage,\n longParagraphCount,\n transitionWordPercentage,\n results,\n recommendations,\n };\n}\n","// ============================================================================\n// @power-seo/readability — Gunning Fog Index\n// ============================================================================\n\nimport { getWords, getSentences, countSyllables, stripHtml } from '@power-seo/core';\n\n/**\n * Calculate the Gunning Fog Index.\n *\n * Formula: 0.4 * [(words/sentences) + 100 * (complex words/words)]\n *\n * \"Complex words\" are words with 3 or more syllables, excluding:\n * - Proper nouns (capitalized words that aren't sentence-starters)\n * - Common suffixes (-es, -ed, -ing) that push words to 3+ syllables\n *\n * Returns a US school grade level.\n */\nexport function gunningFog(content: string): number {\n const text = stripHtml(content);\n const words = getWords(content);\n const sentences = getSentences(content);\n\n if (words.length === 0 || sentences.length === 0) return 0;\n\n const complexWords = countComplexWords(text);\n const avgSentenceLength = words.length / sentences.length;\n const percentComplex = (complexWords / words.length) * 100;\n\n const index = 0.4 * (avgSentenceLength + percentComplex);\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n\n/**\n * Count complex words (3+ syllables), excluding common inflected forms.\n */\nfunction countComplexWords(text: string): number {\n const words = text.split(/\\s+/).filter((w) => w.length > 0);\n let count = 0;\n\n for (const word of words) {\n const cleaned = word.replace(/[^a-zA-Z]/g, '').toLowerCase();\n if (!cleaned) continue;\n\n const syllables = countSyllables(cleaned);\n if (syllables < 3) continue;\n\n // Exclude words that are 3+ syllables only due to common suffixes\n const withoutSuffix = cleaned.replace(/ing$/, '').replace(/ed$/, '').replace(/es$/, '');\n\n if (withoutSuffix !== cleaned && countSyllables(withoutSuffix) < 3) {\n continue;\n }\n\n count++;\n }\n\n return count;\n}\n","// ============================================================================\n// @power-seo/readability — Coleman-Liau Index\n// ============================================================================\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Coleman-Liau Index.\n *\n * Formula: 0.0588 * L - 0.296 * S - 15.8\n *\n * Where:\n * - L = average number of letters per 100 words\n * - S = average number of sentences per 100 words\n *\n * Returns a US school grade level.\n */\nexport function colemanLiau(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n // L: average letters per 100 words\n // characterCount from core includes spaces, so count only letters\n const letterCount = stats.characterCount - (stats.wordCount - 1); // subtract spaces between words\n const L = (letterCount / stats.wordCount) * 100;\n\n // S: average sentences per 100 words\n const S = (stats.sentenceCount / stats.wordCount) * 100;\n\n const index = 0.0588 * L - 0.296 * S - 15.8;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n","// ============================================================================\n// @power-seo/readability — Automated Readability Index (ARI)\n// ============================================================================\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Automated Readability Index (ARI).\n *\n * Formula: 4.71 * (characters/words) + 0.5 * (words/sentences) - 21.43\n *\n * Returns a US school grade level.\n */\nexport function automatedReadability(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const charsPerWord = stats.characterCount / stats.wordCount;\n const wordsPerSentence = stats.wordCount / stats.sentenceCount;\n\n const index = 4.71 * charsPerWord + 0.5 * wordsPerSentence - 21.43;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n"]} | ||
| {"version":3,"sources":["../src/analyzer.ts","../src/algorithms/flesch-kincaid.ts","../src/algorithms/gunning-fog.ts","../src/algorithms/coleman-liau.ts","../src/algorithms/automated-readability.ts"],"sourcesContent":["// @power-seo/readability — Combined Readability Analyzer\n// ----------------------------------------------------------------------------\n\nimport type { ReadabilityInput, ReadabilityOutput, AnalysisResult } from '@power-seo/core';\nimport {\n getTextStatistics,\n getSentences,\n getParagraphs,\n stripHtml,\n READABILITY,\n} from '@power-seo/core';\nimport { fleschReadingEase, fleschKincaidGrade } from './algorithms/flesch-kincaid.js';\n\n// --- Passive Voice Detection ---\n\nconst PASSIVE_AUXILIARIES = ['am', 'is', 'are', 'was', 'were', 'be', 'been', 'being'];\nconst PASSIVE_REGEX = new RegExp(\n `\\\\b(${PASSIVE_AUXILIARIES.join('|')})\\\\s+\\\\w+(?:ed|en|t)\\\\b`,\n 'gi',\n);\n\nfunction countPassiveVoice(text: string): number {\n const matches = text.match(PASSIVE_REGEX);\n return matches?.length ?? 0;\n}\n\n// --- Transition Word Detection ---\n\nconst TRANSITION_WORDS = [\n 'accordingly',\n 'additionally',\n 'also',\n 'although',\n 'as a result',\n 'because',\n 'besides',\n 'but',\n 'certainly',\n 'consequently',\n 'conversely',\n 'equally',\n 'eventually',\n 'finally',\n 'first',\n 'for example',\n 'for instance',\n 'furthermore',\n 'hence',\n 'however',\n 'in addition',\n 'in conclusion',\n 'in contrast',\n 'in fact',\n 'in other words',\n 'in particular',\n 'in summary',\n 'indeed',\n 'instead',\n 'likewise',\n 'meanwhile',\n 'moreover',\n 'namely',\n 'nevertheless',\n 'next',\n 'nonetheless',\n 'notably',\n 'on the other hand',\n 'otherwise',\n 'overall',\n 'particularly',\n 'rather',\n 'second',\n 'similarly',\n 'since',\n 'specifically',\n 'still',\n 'subsequently',\n 'such as',\n 'then',\n 'therefore',\n 'third',\n 'thus',\n 'to illustrate',\n 'ultimately',\n 'whereas',\n 'yet',\n];\n\nfunction countTransitionSentences(sentences: string[]): number {\n let count = 0;\n for (const sentence of sentences) {\n const lower = sentence.toLowerCase();\n if (TRANSITION_WORDS.some((tw) => lower.includes(tw))) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Analyze the readability of content using multiple algorithms.\n *\n * Returns a combined `ReadabilityOutput` with individual algorithm scores,\n * traffic-light results, and actionable recommendations.\n *\n * @example\n * ```ts\n * const result = analyzeReadability({\n * content: '<p>Your article content here...</p>',\n * });\n * console.log(result.fleschReadingEase, result.recommendations);\n * ```\n */\nexport function analyzeReadability(input: ReadabilityInput): ReadabilityOutput {\n const { content } = input;\n const stats = getTextStatistics(content);\n const text = stripHtml(content);\n const sentences = getSentences(content);\n const paragraphs = getParagraphs(content);\n // Algorithm scores\n const fre = fleschReadingEase(stats);\n const fkg = fleschKincaidGrade(stats);\n\n // Passive voice analysis\n const passiveCount = countPassiveVoice(text);\n const passiveVoicePercentage =\n sentences.length > 0 ? Math.round((passiveCount / sentences.length) * 1000) / 10 : 0;\n\n // Long sentence analysis\n const longSentences = sentences.filter((s) => {\n const wordCount = s.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_SENTENCE_LENGTH;\n });\n const longSentencePercentage =\n sentences.length > 0 ? Math.round((longSentences.length / sentences.length) * 1000) / 10 : 0;\n\n // Long paragraph analysis\n const longParagraphCount = paragraphs.filter((p) => {\n const wordCount = p.split(/\\s+/).filter((w) => w.length > 0).length;\n return wordCount > READABILITY.MAX_PARAGRAPH_WORDS;\n }).length;\n\n // Transition word analysis\n const transitionCount = countTransitionSentences(sentences);\n const transitionWordPercentage =\n sentences.length > 0 ? Math.round((transitionCount / sentences.length) * 1000) / 10 : 0;\n\n // Normalized overall score: 0-100 based on Flesch Reading Ease\n const score = Math.round(fre);\n\n // Build results\n const results: AnalysisResult[] = [];\n const recommendations: string[] = [];\n\n // Flesch Reading Ease result\n if (fre >= READABILITY.FLESCH_EASE_GOOD) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is easy to read.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (fre >= READABILITY.FLESCH_EASE_FAIR) {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is fairly difficult to read. Try shorter sentences and simpler words.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n 'Simplify your writing — use shorter sentences and common words to improve readability.',\n );\n } else {\n results.push({\n id: 'flesch-reading-ease',\n title: 'Flesch Reading Ease',\n description: `Score: ${fre}. The text is very difficult to read. Significantly simplify your writing.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n 'Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives.',\n );\n }\n\n // Sentence length result\n if (longSentencePercentage <= 25) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Good variety.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (longSentencePercentage <= 40) {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Try to shorten some.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.`,\n );\n } else {\n results.push({\n id: 'sentence-length',\n title: 'Sentence length',\n description: `${longSentencePercentage}% of sentences are longer than ${READABILITY.MAX_SENTENCE_LENGTH} words. Many sentences need to be shortened.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`,\n );\n }\n\n // Passive voice result\n if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. This is within the recommended limit.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT * 2) {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Try to use more active voice.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`,\n );\n } else {\n results.push({\n id: 'passive-voice',\n title: 'Passive voice',\n description: `${passiveVoicePercentage}% of sentences use passive voice. Rewrite using active voice.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`,\n );\n }\n\n // Transition words result\n if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Good flow.`,\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT / 2) {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Use more to improve flow.`,\n status: 'ok',\n score: 3,\n maxScore: 5,\n });\n recommendations.push(\n `Use more transition words (currently ${transitionWordPercentage}%). Words like \"however\", \"therefore\", and \"for example\" improve readability.`,\n );\n } else {\n results.push({\n id: 'transition-words',\n title: 'Transition words',\n description: `${transitionWordPercentage}% of sentences contain transition words. Add more to connect your ideas.`,\n status: 'poor',\n score: 1,\n maxScore: 5,\n });\n recommendations.push(\n `Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like \"however\", \"in addition\", and \"therefore\" to guide readers.`,\n );\n }\n\n // Paragraph length result\n if (longParagraphCount === 0) {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: 'All paragraphs are a reasonable length.',\n status: 'good',\n score: 5,\n maxScore: 5,\n });\n } else {\n results.push({\n id: 'paragraph-length',\n title: 'Paragraph length',\n description: `${longParagraphCount} paragraph${longParagraphCount === 1 ? '' : 's'} exceed${longParagraphCount === 1 ? 's' : ''} ${READABILITY.MAX_PARAGRAPH_WORDS} words. Break them up for better readability.`,\n status: longParagraphCount <= 2 ? 'ok' : 'poor',\n score: longParagraphCount <= 2 ? 3 : 1,\n maxScore: 5,\n });\n recommendations.push(\n `${longParagraphCount} paragraph${longParagraphCount === 1 ? ' is' : 's are'} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.`,\n );\n }\n\n return {\n score,\n fleschReadingEase: fre,\n fleschKincaidGrade: fkg,\n avgSentenceLength: stats.avgWordsPerSentence,\n avgSyllablesPerWord: stats.avgSyllablesPerWord,\n passiveVoicePercentage,\n longSentencePercentage,\n longParagraphCount,\n transitionWordPercentage,\n results,\n recommendations,\n };\n}\n","// @power-seo/readability — Flesch-Kincaid Algorithms\n// ----------------------------------------------------------------------------\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Flesch Reading Ease score.\n *\n * Formula: 206.835 - 1.015 * (words/sentences) - 84.6 * (syllables/words)\n *\n * Scale:\n * - 90-100: Very Easy (5th grade)\n * - 80-89: Easy (6th grade)\n * - 70-79: Fairly Easy (7th grade)\n * - 60-69: Standard (8th-9th grade)\n * - 50-59: Fairly Difficult (10th-12th grade)\n * - 30-49: Difficult (College)\n * - 0-29: Very Confusing (Graduate)\n */\nexport function fleschReadingEase(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const score = 206.835 - 1.015 * stats.avgWordsPerSentence - 84.6 * stats.avgSyllablesPerWord;\n\n return Math.round(Math.max(0, Math.min(100, score)) * 100) / 100;\n}\n\n/**\n * Calculate the Flesch-Kincaid Grade Level.\n *\n * Formula: 0.39 * (words/sentences) + 11.8 * (syllables/words) - 15.59\n *\n * Returns a US school grade level (e.g., 8.0 = 8th grade).\n */\nexport function fleschKincaidGrade(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const grade = 0.39 * stats.avgWordsPerSentence + 11.8 * stats.avgSyllablesPerWord - 15.59;\n\n return Math.round(Math.max(0, grade) * 100) / 100;\n}\n","// @power-seo/readability — Gunning Fog Index\n// ----------------------------------------------------------------------------\n\nimport { getWords, getSentences, countSyllables, stripHtml } from '@power-seo/core';\n\n/**\n * Calculate the Gunning Fog Index.\n *\n * Formula: 0.4 * [(words/sentences) + 100 * (complex words/words)]\n *\n * \"Complex words\" are words with 3 or more syllables, excluding:\n * - Proper nouns (capitalized words that aren't sentence-starters)\n * - Common suffixes (-es, -ed, -ing) that push words to 3+ syllables\n *\n * Returns a US school grade level.\n */\nexport function gunningFog(content: string): number {\n const text = stripHtml(content);\n const words = getWords(content);\n const sentences = getSentences(content);\n\n if (words.length === 0 || sentences.length === 0) return 0;\n\n const complexWords = countComplexWords(text);\n const avgSentenceLength = words.length / sentences.length;\n const percentComplex = (complexWords / words.length) * 100;\n\n const index = 0.4 * (avgSentenceLength + percentComplex);\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n\n/**\n * Count complex words (3+ syllables), excluding common inflected forms.\n */\nfunction countComplexWords(text: string): number {\n const words = text.split(/\\s+/).filter((w) => w.length > 0);\n let count = 0;\n\n for (const word of words) {\n const cleaned = word.replace(/[^a-zA-Z]/g, '').toLowerCase();\n if (!cleaned) continue;\n\n const syllables = countSyllables(cleaned);\n if (syllables < 3) continue;\n\n // Exclude words that are 3+ syllables only due to common suffixes\n const withoutSuffix = cleaned.replace(/ing$/, '').replace(/ed$/, '').replace(/es$/, '');\n\n if (withoutSuffix !== cleaned && countSyllables(withoutSuffix) < 3) {\n continue;\n }\n\n count++;\n }\n\n return count;\n}\n","// @power-seo/readability — Coleman-Liau Index\n// ----------------------------------------------------------------------------\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Coleman-Liau Index.\n *\n * Formula: 0.0588 * L - 0.296 * S - 15.8\n *\n * Where:\n * - L = average number of letters per 100 words\n * - S = average number of sentences per 100 words\n *\n * Returns a US school grade level.\n */\nexport function colemanLiau(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n // L: average letters per 100 words\n // characterCount from core includes spaces, so count only letters\n const letterCount = stats.characterCount - (stats.wordCount - 1); // subtract spaces between words\n const L = (letterCount / stats.wordCount) * 100;\n\n // S: average sentences per 100 words\n const S = (stats.sentenceCount / stats.wordCount) * 100;\n\n const index = 0.0588 * L - 0.296 * S - 15.8;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n","// @power-seo/readability — Automated Readability Index (ARI)\n// ----------------------------------------------------------------------------\n\nimport type { TextStatistics } from '@power-seo/core';\n\n/**\n * Calculate the Automated Readability Index (ARI).\n *\n * Formula: 4.71 * (characters/words) + 0.5 * (words/sentences) - 21.43\n *\n * Returns a US school grade level.\n */\nexport function automatedReadability(stats: TextStatistics): number {\n if (stats.wordCount === 0 || stats.sentenceCount === 0) return 0;\n\n const charsPerWord = stats.characterCount / stats.wordCount;\n const wordsPerSentence = stats.wordCount / stats.sentenceCount;\n\n const index = 4.71 * charsPerWord + 0.5 * wordsPerSentence - 21.43;\n return Math.round(Math.max(0, index) * 100) / 100;\n}\n"],"mappings":"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","names":["getSentences","stripHtml"]} |
+22
-14
| { | ||
| "name": "@power-seo/readability", | ||
| "version": "1.0.4", | ||
| "version": "1.0.7", | ||
| "description": "Readability scoring algorithms (Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI) with configurable thresholds", | ||
@@ -20,17 +20,7 @@ "license": "MIT", | ||
| ], | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "dev": "tsup --watch", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "typecheck": "tsc --noEmit", | ||
| "lint": "eslint src/", | ||
| "lint:fix": "eslint src/ --fix", | ||
| "clean": "rimraf dist" | ||
| }, | ||
| "dependencies": { | ||
| "@power-seo/core": "workspace:*" | ||
| "@power-seo/core": "1.0.3" | ||
| }, | ||
| "devDependencies": { | ||
| "rimraf": "^6.0.0", | ||
| "rimraf": "^6.1.3", | ||
| "tsup": "^8.3.0", | ||
@@ -56,3 +46,21 @@ "typescript": "^5.7.0", | ||
| "access": "public" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/CyberCraftBD/power-seo/issues" | ||
| }, | ||
| "homepage": "https://github.com/CyberCraftBD/power-seo/tree/main/packages/readability#readme", | ||
| "funding": { | ||
| "type": "github", | ||
| "url": "https://github.com/sponsors/cybercraftbd" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "dev": "tsup --watch", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "typecheck": "tsc --noEmit", | ||
| "lint": "eslint src/", | ||
| "lint:fix": "eslint src/ --fix", | ||
| "clean": "rimraf dist" | ||
| } | ||
| } | ||
| } |
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
9
12.5%800
6.1%0
-100%0
-100%100934
-4.96%Updated