@power-seo/readability
Advanced tools
+27
-9
@@ -140,3 +140,5 @@ 'use strict'; | ||
| }); | ||
| recommendations.push("Simplify your writing \u2014 use shorter sentences and common words to improve readability."); | ||
| recommendations.push( | ||
| "Simplify your writing \u2014 use shorter sentences and common words to improve readability." | ||
| ); | ||
| } else { | ||
@@ -151,3 +153,5 @@ results.push({ | ||
| }); | ||
| recommendations.push("Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives."); | ||
| recommendations.push( | ||
| "Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives." | ||
| ); | ||
| } | ||
@@ -172,3 +176,5 @@ if (longSentencePercentage <= 25) { | ||
| }); | ||
| recommendations.push(`${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${core.READABILITY.MAX_SENTENCE_LENGTH} words.`); | ||
| recommendations.push( | ||
| `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${core.READABILITY.MAX_SENTENCE_LENGTH} words.` | ||
| ); | ||
| } else { | ||
@@ -183,3 +189,5 @@ results.push({ | ||
| }); | ||
| recommendations.push(`${longSentencePercentage}% of your sentences exceed ${core.READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`); | ||
| recommendations.push( | ||
| `${longSentencePercentage}% of your sentences exceed ${core.READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.` | ||
| ); | ||
| } | ||
@@ -204,3 +212,5 @@ if (passiveVoicePercentage <= core.READABILITY.MAX_PASSIVE_VOICE_PERCENT) { | ||
| }); | ||
| recommendations.push(`Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`); | ||
| recommendations.push( | ||
| `Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.` | ||
| ); | ||
| } else { | ||
@@ -215,3 +225,5 @@ results.push({ | ||
| }); | ||
| recommendations.push(`${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`); | ||
| recommendations.push( | ||
| `${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.` | ||
| ); | ||
| } | ||
@@ -236,3 +248,5 @@ if (transitionWordPercentage >= core.READABILITY.MIN_TRANSITION_WORD_PERCENT) { | ||
| }); | ||
| recommendations.push(`Use more transition words (currently ${transitionWordPercentage}%). Words like "however", "therefore", and "for example" improve readability.`); | ||
| recommendations.push( | ||
| `Use more transition words (currently ${transitionWordPercentage}%). Words like "however", "therefore", and "for example" improve readability.` | ||
| ); | ||
| } else { | ||
@@ -247,3 +261,5 @@ results.push({ | ||
| }); | ||
| recommendations.push(`Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like "however", "in addition", and "therefore" to guide readers.`); | ||
| recommendations.push( | ||
| `Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like "however", "in addition", and "therefore" to guide readers.` | ||
| ); | ||
| } | ||
@@ -268,3 +284,5 @@ if (longParagraphCount === 0) { | ||
| }); | ||
| recommendations.push(`${longParagraphCount} paragraph${longParagraphCount === 1 ? " is" : "s are"} too long. Keep paragraphs under ${core.READABILITY.MAX_PARAGRAPH_WORDS} words.`); | ||
| recommendations.push( | ||
| `${longParagraphCount} paragraph${longParagraphCount === 1 ? " is" : "s are"} too long. Keep paragraphs under ${core.READABILITY.MAX_PARAGRAPH_WORDS} words.` | ||
| ); | ||
| } | ||
@@ -271,0 +289,0 @@ return { |
@@ -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 =\n 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 =\n 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', 'additionally', 'also', 'although', 'as a result',\n 'because', 'besides', 'but', 'certainly', 'consequently',\n 'conversely', 'equally', 'eventually', 'finally', 'first',\n 'for example', 'for instance', 'furthermore', 'hence', 'however',\n 'in addition', 'in conclusion', 'in contrast', 'in fact', 'in other words',\n 'in particular', 'in summary', 'indeed', 'instead', 'likewise',\n 'meanwhile', 'moreover', 'namely', 'nevertheless', 'next',\n 'nonetheless', 'notably', 'on the other hand', 'otherwise', 'overall',\n 'particularly', 'rather', 'second', 'similarly', 'since',\n 'specifically', 'still', 'subsequently', 'such as', 'then',\n 'therefore', 'third', 'thus', 'to illustrate', 'ultimately',\n 'whereas', '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\n ? Math.round((longSentences.length / sentences.length) * 1000) / 10\n : 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('Simplify your writing — use shorter sentences and common words to improve readability.');\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('Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives.');\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(`${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.`);\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(`${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`);\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(`Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`);\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(`${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`);\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(`Use more transition words (currently ${transitionWordPercentage}%). Words like \"however\", \"therefore\", and \"for example\" improve readability.`);\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(`Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like \"however\", \"in addition\", and \"therefore\" to guide readers.`);\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(`${longParagraphCount} paragraph${longParagraphCount === 1 ? ' is' : 's are'} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.`);\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\n .replace(/ing$/, '')\n .replace(/ed$/, '')\n .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/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":";;;;;;;AAoBO,SAAS,kBAAkB,KAAA,EAA+B;AAC/D,EAAA,IAAI,MAAM,SAAA,KAAc,CAAA,IAAK,KAAA,CAAM,aAAA,KAAkB,GAAG,OAAO,CAAA;AAE/D,EAAA,MAAM,QAAQ,OAAA,GAAU,KAAA,GAAQ,KAAA,CAAM,mBAAA,GAAsB,OAAO,KAAA,CAAM,mBAAA;AAEzE,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAC/D;AASO,SAAS,mBAAmB,KAAA,EAA+B;AAChE,EAAA,IAAI,MAAM,SAAA,KAAc,CAAA,IAAK,KAAA,CAAM,aAAA,KAAkB,GAAG,OAAO,CAAA;AAE/D,EAAA,MAAM,QAAQ,IAAA,GAAO,KAAA,CAAM,mBAAA,GAAsB,IAAA,GAAO,MAAM,mBAAA,GAAsB,KAAA;AAEpF,EAAA,OAAO,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAK,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAChD;;;ACzBA,IAAM,mBAAA,GAAsB,CAAC,IAAA,EAAM,IAAA,EAAM,OAAO,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA;AACpF,IAAM,gBAAgB,IAAI,MAAA;AAAA,EACxB,CAAA,IAAA,EAAO,mBAAA,CAAoB,IAAA,CAAK,GAAG,CAAC,CAAA,uBAAA,CAAA;AAAA,EACpC;AACF,CAAA;AAEA,SAAS,kBAAkB,IAAA,EAAsB;AAC/C,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA;AACxC,EAAA,OAAO,SAAS,MAAA,IAAU,CAAA;AAC5B;AAIA,IAAM,gBAAA,GAAmB;AAAA,EACvB,aAAA;AAAA,EACA,cAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA;AAAA,EACA,eAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,MAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,mBAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,yBAAyB,SAAA,EAA6B;AAC7D,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,IAAA,MAAM,KAAA,GAAQ,SAAS,WAAA,EAAY;AACnC,IAAA,IAAI,gBAAA,CAAiB,KAAK,CAAC,EAAA,KAAO,MAAM,QAAA,CAAS,EAAE,CAAC,CAAA,EAAG;AACrD,MAAA,KAAA,EAAA;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAgBO,SAAS,mBAAmB,KAAA,EAA4C;AAC7E,EAAA,MAAM,EAAE,SAAQ,GAAI,KAAA;AACpB,EAAA,MAAM,KAAA,GAAQA,uBAAkB,OAAO,CAAA;AACvC,EAAA,MAAM,IAAA,GAAOC,eAAU,OAAO,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAYC,kBAAa,OAAO,CAAA;AACtC,EAAA,MAAM,UAAA,GAAaC,mBAAc,OAAO,CAAA;AAExC,EAAA,MAAM,GAAA,GAAM,kBAAkB,KAAK,CAAA;AACnC,EAAA,MAAM,GAAA,GAAM,mBAAmB,KAAK,CAAA;AAGpC,EAAA,MAAM,YAAA,GAAe,kBAAkB,IAAI,CAAA;AAC3C,EAAA,MAAM,sBAAA,GACJ,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,KAAA,CAAO,YAAA,GAAe,SAAA,CAAU,MAAA,GAAU,GAAI,CAAA,GAAI,EAAA,GAAK,CAAA;AAGrF,EAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM;AAC5C,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA,CAAE,MAAA;AAC7D,IAAA,OAAO,YAAYC,gBAAA,CAAY,mBAAA;AAAA,EACjC,CAAC,CAAA;AACD,EAAA,MAAM,sBAAA,GACJ,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,KAAA,CAAO,aAAA,CAAc,MAAA,GAAS,SAAA,CAAU,MAAA,GAAU,GAAI,CAAA,GAAI,EAAA,GAAK,CAAA;AAG7F,EAAA,MAAM,kBAAA,GAAqB,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM;AAClD,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA,CAAE,MAAA;AAC7D,IAAA,OAAO,YAAYA,gBAAA,CAAY,mBAAA;AAAA,EACjC,CAAC,CAAA,CAAE,MAAA;AAGH,EAAA,MAAM,eAAA,GAAkB,yBAAyB,SAAS,CAAA;AAC1D,EAAA,MAAM,wBAAA,GACJ,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,KAAA,CAAO,eAAA,GAAkB,SAAA,CAAU,MAAA,GAAU,GAAI,CAAA,GAAI,EAAA,GAAK,CAAA;AAGxF,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAG5B,EAAA,MAAM,UAA4B,EAAC;AACnC,EAAA,MAAM,kBAA4B,EAAC;AAGnC,EAAA,IAAI,GAAA,IAAOA,iBAAY,gBAAA,EAAkB;AACvC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,qBAAA;AAAA,MACJ,KAAA,EAAO,qBAAA;AAAA,MACP,WAAA,EAAa,UAAU,GAAG,CAAA,2BAAA,CAAA;AAAA,MAC1B,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH,CAAA,MAAA,IAAW,GAAA,IAAOA,gBAAA,CAAY,gBAAA,EAAkB;AAC9C,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,qBAAA;AAAA,MACJ,KAAA,EAAO,qBAAA;AAAA,MACP,WAAA,EAAa,UAAU,GAAG,CAAA,gFAAA,CAAA;AAAA,MAC1B,MAAA,EAAQ,IAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd;AAAA,KACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,qBAAA;AAAA,MACJ,KAAA,EAAO,qBAAA;AAAA,MACP,WAAA,EAAa,UAAU,GAAG,CAAA,0EAAA,CAAA;AAAA,MAC1B,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAI,0BAA0B,EAAA,EAAI;AAChC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,iBAAA;AAAA,MACJ,KAAA,EAAO,iBAAA;AAAA,MACP,WAAA,EAAa,CAAA,EAAG,sBAAsB,CAAA,+BAAA,EAAkCA,iBAAY,mBAAmB,CAAA,qBAAA,CAAA;AAAA,MACvG,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH,CAAA,MAAA,IAAW,0BAA0B,EAAA,EAAI;AACvC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,iBAAA;AAAA,MACJ,KAAA,EAAO,iBAAA;AAAA,MACP,WAAA,EAAa,CAAA,EAAG,sBAAsB,CAAA,+BAAA,EAAkCA,iBAAY,mBAAmB,CAAA,4BAAA,CAAA;AAAA,MACvG,MAAA,EAAQ,IAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd,CAAA,EAAG,sBAAsB,CAAA,+DAAA,EAAkEA,gBAAA,CAAY,mBAAmB,CAAA,OAAA;AAAA,KAC5H;AAAA,EACF,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,iBAAA;AAAA,MACJ,KAAA,EAAO,iBAAA;AAAA,MACP,WAAA,EAAa,CAAA,EAAG,sBAAsB,CAAA,+BAAA,EAAkCA,iBAAY,mBAAmB,CAAA,4CAAA,CAAA;AAAA,MACvG,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd,CAAA,EAAG,sBAAsB,CAAA,2BAAA,EAA8BA,gBAAA,CAAY,mBAAmB,CAAA,2DAAA;AAAA,KACxF;AAAA,EACF;AAGA,EAAA,IAAI,sBAAA,IAA0BA,iBAAY,yBAAA,EAA2B;AACnE,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,eAAA;AAAA,MACJ,KAAA,EAAO,eAAA;AAAA,MACP,WAAA,EAAa,GAAG,sBAAsB,CAAA,uEAAA,CAAA;AAAA,MACtC,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH,CAAA,MAAA,IAAW,sBAAA,IAA0BA,gBAAA,CAAY,yBAAA,GAA4B,CAAA,EAAG;AAC9E,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,eAAA;AAAA,MACJ,KAAA,EAAO,eAAA;AAAA,MACP,WAAA,EAAa,GAAG,sBAAsB,CAAA,+DAAA,CAAA;AAAA,MACtC,MAAA,EAAQ,IAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd,+BAA+B,sBAAsB,CAAA,6DAAA;AAAA,KACvD;AAAA,EACF,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,eAAA;AAAA,MACJ,KAAA,EAAO,eAAA;AAAA,MACP,WAAA,EAAa,GAAG,sBAAsB,CAAA,6DAAA,CAAA;AAAA,MACtC,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd,GAAG,sBAAsB,CAAA,uGAAA;AAAA,KAC3B;AAAA,EACF;AAGA,EAAA,IAAI,wBAAA,IAA4BA,iBAAY,2BAAA,EAA6B;AACvE,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,kBAAA;AAAA,MACJ,KAAA,EAAO,kBAAA;AAAA,MACP,WAAA,EAAa,GAAG,wBAAwB,CAAA,mDAAA,CAAA;AAAA,MACxC,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH,CAAA,MAAA,IAAW,wBAAA,IAA4BA,gBAAA,CAAY,2BAAA,GAA8B,CAAA,EAAG;AAClF,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,kBAAA;AAAA,MACJ,KAAA,EAAO,kBAAA;AAAA,MACP,WAAA,EAAa,GAAG,wBAAwB,CAAA,kEAAA,CAAA;AAAA,MACxC,MAAA,EAAQ,IAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd,wCAAwC,wBAAwB,CAAA,6EAAA;AAAA,KAClE;AAAA,EACF,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,kBAAA;AAAA,MACJ,KAAA,EAAO,kBAAA;AAAA,MACP,WAAA,EAAa,GAAG,wBAAwB,CAAA,wEAAA,CAAA;AAAA,MACxC,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd,QAAQ,wBAAwB,CAAA,oHAAA;AAAA,KAClC;AAAA,EACF;AAGA,EAAA,IAAI,uBAAuB,CAAA,EAAG;AAC5B,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,kBAAA;AAAA,MACJ,KAAA,EAAO,kBAAA;AAAA,MACP,WAAA,EAAa,yCAAA;AAAA,MACb,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,EAAA,EAAI,kBAAA;AAAA,MACJ,KAAA,EAAO,kBAAA;AAAA,MACP,WAAA,EAAa,CAAA,EAAG,kBAAkB,CAAA,UAAA,EAAa,uBAAuB,CAAA,GAAI,EAAA,GAAK,GAAG,CAAA,OAAA,EAAU,uBAAuB,CAAA,GAAI,GAAA,GAAM,EAAE,CAAA,CAAA,EAAIA,iBAAY,mBAAmB,CAAA,6CAAA,CAAA;AAAA,MAClK,MAAA,EAAQ,kBAAA,IAAsB,CAAA,GAAI,IAAA,GAAO,MAAA;AAAA,MACzC,KAAA,EAAO,kBAAA,IAAsB,CAAA,GAAI,CAAA,GAAI,CAAA;AAAA,MACrC,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,eAAA,CAAgB,IAAA;AAAA,MACd,CAAA,EAAG,kBAAkB,CAAA,UAAA,EAAa,kBAAA,KAAuB,IAAI,KAAA,GAAQ,OAAO,CAAA,iCAAA,EAAoCA,gBAAA,CAAY,mBAAmB,CAAA,OAAA;AAAA,KACjJ;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,iBAAA,EAAmB,GAAA;AAAA,IACnB,kBAAA,EAAoB,GAAA;AAAA,IACpB,mBAAmB,KAAA,CAAM,mBAAA;AAAA,IACzB,qBAAqB,KAAA,CAAM,mBAAA;AAAA,IAC3B,sBAAA;AAAA,IACA,sBAAA;AAAA,IACA,kBAAA;AAAA,IACA,wBAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACF;AC/TO,SAAS,WAAW,OAAA,EAAyB;AAClD,EAAA,MAAM,IAAA,GAAOH,eAAU,OAAO,CAAA;AAC9B,EAAA,MAAM,KAAA,GAAQI,cAAS,OAAO,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAYH,kBAAa,OAAO,CAAA;AAEtC,EAAA,IAAI,MAAM,MAAA,KAAW,CAAA,IAAK,SAAA,CAAU,MAAA,KAAW,GAAG,OAAO,CAAA;AAEzD,EAAA,MAAM,YAAA,GAAe,kBAAkB,IAAI,CAAA;AAC3C,EAAA,MAAM,iBAAA,GAAoB,KAAA,CAAM,MAAA,GAAS,SAAA,CAAU,MAAA;AACnD,EAAA,MAAM,cAAA,GAAkB,YAAA,GAAe,KAAA,CAAM,MAAA,GAAU,GAAA;AAEvD,EAAA,MAAM,KAAA,GAAQ,OAAO,iBAAA,GAAoB,cAAA,CAAA;AACzC,EAAA,OAAO,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAK,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAChD;AAKA,SAAS,kBAAkB,IAAA,EAAsB;AAC/C,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,CAAE,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA;AAC1D,EAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,EAAE,EAAE,WAAA,EAAY;AAC3D,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,MAAM,SAAA,GAAYI,oBAAe,OAAO,CAAA;AACxC,IAAA,IAAI,YAAY,CAAA,EAAG;AAGnB,IAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAEtF,IAAA,IAAI,aAAA,KAAkB,OAAA,IAAWA,mBAAA,CAAe,aAAa,IAAI,CAAA,EAAG;AAClE,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,EAAA;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;;;ACxCO,SAAS,YAAY,KAAA,EAA+B;AACzD,EAAA,IAAI,MAAM,SAAA,KAAc,CAAA,IAAK,KAAA,CAAM,aAAA,KAAkB,GAAG,OAAO,CAAA;AAI/D,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,cAAA,IAAkB,KAAA,CAAM,SAAA,GAAY,CAAA,CAAA;AAC9D,EAAA,MAAM,CAAA,GAAK,WAAA,GAAc,KAAA,CAAM,SAAA,GAAa,GAAA;AAG5C,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,aAAA,GAAgB,KAAA,CAAM,SAAA,GAAa,GAAA;AAEpD,EAAA,MAAM,KAAA,GAAQ,MAAA,GAAS,CAAA,GAAI,KAAA,GAAQ,CAAA,GAAI,IAAA;AACvC,EAAA,OAAO,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAK,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAChD;;;ACjBO,SAAS,qBAAqB,KAAA,EAA+B;AAClE,EAAA,IAAI,MAAM,SAAA,KAAc,CAAA,IAAK,KAAA,CAAM,aAAA,KAAkB,GAAG,OAAO,CAAA;AAE/D,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,cAAA,GAAiB,KAAA,CAAM,SAAA;AAClD,EAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,SAAA,GAAY,KAAA,CAAM,aAAA;AAEjD,EAAA,MAAM,KAAA,GAAQ,IAAA,GAAO,YAAA,GAAe,GAAA,GAAM,gBAAA,GAAmB,KAAA;AAC7D,EAAA,OAAO,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,GAAG,KAAK,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAChD","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"]} |
+27
-9
@@ -138,3 +138,5 @@ import { getTextStatistics, stripHtml, getSentences, getParagraphs, READABILITY, getWords, countSyllables } from '@power-seo/core'; | ||
| }); | ||
| recommendations.push("Simplify your writing \u2014 use shorter sentences and common words to improve readability."); | ||
| recommendations.push( | ||
| "Simplify your writing \u2014 use shorter sentences and common words to improve readability." | ||
| ); | ||
| } else { | ||
@@ -149,3 +151,5 @@ results.push({ | ||
| }); | ||
| recommendations.push("Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives."); | ||
| recommendations.push( | ||
| "Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives." | ||
| ); | ||
| } | ||
@@ -170,3 +174,5 @@ if (longSentencePercentage <= 25) { | ||
| }); | ||
| recommendations.push(`${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.`); | ||
| recommendations.push( | ||
| `${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.` | ||
| ); | ||
| } else { | ||
@@ -181,3 +187,5 @@ results.push({ | ||
| }); | ||
| recommendations.push(`${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`); | ||
| recommendations.push( | ||
| `${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.` | ||
| ); | ||
| } | ||
@@ -202,3 +210,5 @@ if (passiveVoicePercentage <= READABILITY.MAX_PASSIVE_VOICE_PERCENT) { | ||
| }); | ||
| recommendations.push(`Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`); | ||
| recommendations.push( | ||
| `Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.` | ||
| ); | ||
| } else { | ||
@@ -213,3 +223,5 @@ results.push({ | ||
| }); | ||
| recommendations.push(`${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`); | ||
| recommendations.push( | ||
| `${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.` | ||
| ); | ||
| } | ||
@@ -234,3 +246,5 @@ if (transitionWordPercentage >= READABILITY.MIN_TRANSITION_WORD_PERCENT) { | ||
| }); | ||
| recommendations.push(`Use more transition words (currently ${transitionWordPercentage}%). Words like "however", "therefore", and "for example" improve readability.`); | ||
| recommendations.push( | ||
| `Use more transition words (currently ${transitionWordPercentage}%). Words like "however", "therefore", and "for example" improve readability.` | ||
| ); | ||
| } else { | ||
@@ -245,3 +259,5 @@ results.push({ | ||
| }); | ||
| recommendations.push(`Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like "however", "in addition", and "therefore" to guide readers.`); | ||
| recommendations.push( | ||
| `Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like "however", "in addition", and "therefore" to guide readers.` | ||
| ); | ||
| } | ||
@@ -266,3 +282,5 @@ if (longParagraphCount === 0) { | ||
| }); | ||
| recommendations.push(`${longParagraphCount} paragraph${longParagraphCount === 1 ? " is" : "s are"} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.`); | ||
| recommendations.push( | ||
| `${longParagraphCount} paragraph${longParagraphCount === 1 ? " is" : "s are"} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.` | ||
| ); | ||
| } | ||
@@ -269,0 +287,0 @@ return { |
@@ -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 =\n 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 =\n 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', 'additionally', 'also', 'although', 'as a result',\n 'because', 'besides', 'but', 'certainly', 'consequently',\n 'conversely', 'equally', 'eventually', 'finally', 'first',\n 'for example', 'for instance', 'furthermore', 'hence', 'however',\n 'in addition', 'in conclusion', 'in contrast', 'in fact', 'in other words',\n 'in particular', 'in summary', 'indeed', 'instead', 'likewise',\n 'meanwhile', 'moreover', 'namely', 'nevertheless', 'next',\n 'nonetheless', 'notably', 'on the other hand', 'otherwise', 'overall',\n 'particularly', 'rather', 'second', 'similarly', 'since',\n 'specifically', 'still', 'subsequently', 'such as', 'then',\n 'therefore', 'third', 'thus', 'to illustrate', 'ultimately',\n 'whereas', '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\n ? Math.round((longSentences.length / sentences.length) * 1000) / 10\n : 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('Simplify your writing — use shorter sentences and common words to improve readability.');\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('Your content is very hard to read. Break up long sentences and replace complex words with simpler alternatives.');\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(`${longSentencePercentage}% of your sentences are long. Try to keep most sentences under ${READABILITY.MAX_SENTENCE_LENGTH} words.`);\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(`${longSentencePercentage}% of your sentences exceed ${READABILITY.MAX_SENTENCE_LENGTH} words. Break them into shorter, more digestible sentences.`);\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(`Reduce passive voice usage (${passiveVoicePercentage}%). Active voice makes your writing more direct and engaging.`);\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(`${passiveVoicePercentage}% of your sentences use passive voice. Rewrite them in active voice for clearer, more engaging content.`);\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(`Use more transition words (currently ${transitionWordPercentage}%). Words like \"however\", \"therefore\", and \"for example\" improve readability.`);\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(`Only ${transitionWordPercentage}% of sentences use transition words. Add connectors like \"however\", \"in addition\", and \"therefore\" to guide readers.`);\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(`${longParagraphCount} paragraph${longParagraphCount === 1 ? ' is' : 's are'} too long. Keep paragraphs under ${READABILITY.MAX_PARAGRAPH_WORDS} words.`);\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\n .replace(/ing$/, '')\n .replace(/ed$/, '')\n .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/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"]} |
+1
-1
| { | ||
| "name": "@power-seo/readability", | ||
| "version": "1.0.1", | ||
| "version": "1.0.2", | ||
| "description": "Readability scoring algorithms (Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI) with configurable thresholds", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
106099
0.61%754
5.01%