@power-seo/content-analysis
Advanced tools
+13
-13
| { | ||
| "name": "@power-seo/content-analysis", | ||
| "version": "1.0.8", | ||
| "version": "1.0.9", | ||
| "description": "Yoast-style SEO content analysis engine with scoring, checks, and React components", | ||
@@ -25,4 +25,14 @@ "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": "1.0.3" | ||
| "@power-seo/core": "workspace:*" | ||
| }, | ||
@@ -87,13 +97,3 @@ "peerDependencies": { | ||
| "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" | ||
| } | ||
| } | ||
| } |
+73
-71
@@ -23,12 +23,12 @@ # @power-seo/content-analysis | ||
| | | Without | With | | ||
| |---|---|---| | ||
| | Keyphrase check | ❌ Manual grep | ✅ Density + distribution scoring | | ||
| | Title validation | ❌ Eye-check only | ✅ Presence, length, keyphrase match | | ||
| | Meta description | ❌ Unchecked | ✅ Length (120–160 chars) + keyphrase | | ||
| | Heading structure | ❌ Missed H1s | ✅ H1 hierarchy + keyphrase in subheadings | | ||
| | Image alt text | ❌ Skipped | ✅ Alt presence + keyphrase in alt | | ||
| | Link analysis | ❌ Unknown | ✅ Internal + external link presence | | ||
| | SEO score | ❌ Guesswork | ✅ Aggregate score with per-check breakdown | | ||
| | Framework support | ❌ WordPress-only | ✅ Next.js, Remix, Vite, Node.js, Edge | | ||
| | | Without | With | | ||
| | ----------------- | ----------------- | ------------------------------------------- | | ||
| | Keyphrase check | ❌ Manual grep | ✅ Density + distribution scoring | | ||
| | Title validation | ❌ Eye-check only | ✅ Presence, length, keyphrase match | | ||
| | Meta description | ❌ Unchecked | ✅ Length (120–160 chars) + keyphrase | | ||
| | Heading structure | ❌ Missed H1s | ✅ H1 hierarchy + keyphrase in subheadings | | ||
| | Image alt text | ❌ Skipped | ✅ Alt presence + keyphrase in alt | | ||
| | Link analysis | ❌ Unknown | ✅ Internal + external link presence | | ||
| | SEO score | ❌ Guesswork | ✅ Aggregate score with per-check breakdown | | ||
| | Framework support | ❌ WordPress-only | ✅ Next.js, Remix, Vite, Node.js, Edge | | ||
@@ -64,16 +64,16 @@  | ||
| | ------------------------------ | :-------------------------: | :-------: | :------: | :----------: | :----------: | | ||
| | Keyphrase density check | ✅ | ✅ | ❌ | Partial | ❌ | | ||
| | Keyphrase distribution | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Title + meta validation | ✅ | ✅ | ❌ | Partial | ❌ | | ||
| | Heading structure check | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Image alt + keyphrase check | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Internal / external link check | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Aggregate SEO score | ✅ | ✅ | ❌ | Partial | ❌ | | ||
| | Per-check disable config | ✅ | ❌ | ❌ | ❌ | ❌ | | ||
| | Works outside WordPress | ✅ | ❌ | ✅ | ✅ | ✅ | | ||
| | TypeScript-first | ✅ | ❌ | Partial | ❌ | ❌ | | ||
| | Tree-shakeable | ✅ | ❌ | Partial | ❌ | ❌ | | ||
| | React UI components | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | CI / Node.js usage | ✅ | ❌ | ❌ | ✅ | ❌ | | ||
| | Zero runtime dependencies | ✅ | ❌ | ❌ | ❌ | ❌ | | ||
| | Keyphrase density check | ✅ | ✅ | ❌ | Partial | ❌ | | ||
| | Keyphrase distribution | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Title + meta validation | ✅ | ✅ | ❌ | Partial | ❌ | | ||
| | Heading structure check | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Image alt + keyphrase check | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Internal / external link check | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | Aggregate SEO score | ✅ | ✅ | ❌ | Partial | ❌ | | ||
| | Per-check disable config | ✅ | ❌ | ❌ | ❌ | ❌ | | ||
| | Works outside WordPress | ✅ | ❌ | ✅ | ✅ | ✅ | | ||
| | TypeScript-first | ✅ | ❌ | Partial | ❌ | ❌ | | ||
| | Tree-shakeable | ✅ | ❌ | Partial | ❌ | ❌ | | ||
| | React UI components | ✅ | ✅ | ❌ | ❌ | ❌ | | ||
| | CI / Node.js usage | ✅ | ❌ | ❌ | ✅ | ❌ | | ||
| | Zero runtime dependencies | ✅ | ❌ | ❌ | ❌ | ❌ | | ||
@@ -112,4 +112,4 @@  | ||
| console.log(result.score); // e.g. 38 | ||
| console.log(result.maxScore); // e.g. 55 | ||
| console.log(result.score); // e.g. 38 | ||
| console.log(result.maxScore); // e.g. 55 | ||
| console.log(result.results); | ||
@@ -122,2 +122,3 @@ // [{ id: 'title-presence', status: 'good', description: '...', score: 5, maxScore: 5 }, ...] | ||
| **Status thresholds (per check):** | ||
| - `good` — check fully passes | ||
@@ -140,3 +141,4 @@ - `ok` — check partially passes | ||
| title: 'Next.js SEO Best Practices', | ||
| metaDescription: 'Learn how to optimize your Next.js app for search engines with meta tags and structured data.', | ||
| metaDescription: | ||
| 'Learn how to optimize your Next.js app for search engines with meta tags and structured data.', | ||
| focusKeyphrase: 'next.js seo', | ||
@@ -245,6 +247,6 @@ content: htmlString, | ||
| | Import | Description | | ||
| | --- | --- | | ||
| | `@power-seo/content-analysis` | Core analyzer and individual check functions | | ||
| | `@power-seo/content-analysis/react` | React components for analysis UI | | ||
| | Import | Description | | ||
| | ----------------------------------- | -------------------------------------------- | | ||
| | `@power-seo/content-analysis` | Core analyzer and individual check functions | | ||
| | `@power-seo/content-analysis/react` | React components for analysis UI | | ||
@@ -262,32 +264,32 @@ ### `analyzeContent()` | ||
| | Prop | Type | Required | Description | | ||
| | ----------------- | -------------------------------------- | -------- | ---------------------------------------------- | | ||
| | `content` | `string` | ✅ | Body HTML string | | ||
| | `title` | `string` | — | Page `<title>` content | | ||
| | `metaDescription` | `string` | — | Meta description content | | ||
| | `focusKeyphrase` | `string` | — | Focus keyphrase to analyze against | | ||
| | `slug` | `string` | — | URL slug (used for keyphrase-in-slug check) | | ||
| | `images` | `Array<{ src: string; alt?: string }>` | — | Images found on the page | | ||
| | `internalLinks` | `string[]` | — | Internal link URLs | | ||
| | `externalLinks` | `string[]` | — | External link URLs | | ||
| | Prop | Type | Required | Description | | ||
| | ----------------- | -------------------------------------- | -------- | ------------------------------------------- | | ||
| | `content` | `string` | ✅ | Body HTML string | | ||
| | `title` | `string` | — | Page `<title>` content | | ||
| | `metaDescription` | `string` | — | Meta description content | | ||
| | `focusKeyphrase` | `string` | — | Focus keyphrase to analyze against | | ||
| | `slug` | `string` | — | URL slug (used for keyphrase-in-slug check) | | ||
| | `images` | `Array<{ src: string; alt?: string }>` | — | Images found on the page | | ||
| | `internalLinks` | `string[]` | — | Internal link URLs | | ||
| | `externalLinks` | `string[]` | — | External link URLs | | ||
| #### `ContentAnalysisOutput` | ||
| | Field | Type | Description | | ||
| | ----------------- | ------------------ | ----------------------------------------------------- | | ||
| | `score` | `number` | Sum of all individual check scores | | ||
| | `maxScore` | `number` | Maximum possible score (varies by enabled checks) | | ||
| | `results` | `AnalysisResult[]` | Per-check results | | ||
| | `recommendations` | `string[]` | Descriptions from all failed or partial checks | | ||
| | Field | Type | Description | | ||
| | ----------------- | ------------------ | ------------------------------------------------- | | ||
| | `score` | `number` | Sum of all individual check scores | | ||
| | `maxScore` | `number` | Maximum possible score (varies by enabled checks) | | ||
| | `results` | `AnalysisResult[]` | Per-check results | | ||
| | `recommendations` | `string[]` | Descriptions from all failed or partial checks | | ||
| #### `AnalysisResult` | ||
| | Field | Type | Description | | ||
| | ------------- | ---------------- | --------------------------------------------------------- | | ||
| | `id` | `string` | Unique check identifier (one of the `CheckId` values) | | ||
| | `title` | `string` | Short display label for the check (e.g. `"SEO title"`) | | ||
| | `description` | `string` | Human-readable actionable feedback | | ||
| | `status` | `AnalysisStatus` | `'good'` \| `'ok'` \| `'poor'` | | ||
| | `score` | `number` | Points earned for this check | | ||
| | `maxScore` | `number` | Maximum points for this check | | ||
| | Field | Type | Description | | ||
| | ------------- | ---------------- | ------------------------------------------------------ | | ||
| | `id` | `string` | Unique check identifier (one of the `CheckId` values) | | ||
| | `title` | `string` | Short display label for the check (e.g. `"SEO title"`) | | ||
| | `description` | `string` | Human-readable actionable feedback | | ||
| | `status` | `AnalysisStatus` | `'good'` \| `'ok'` \| `'poor'` | | ||
| | `score` | `number` | Points earned for this check | | ||
| | `maxScore` | `number` | Maximum points for this check | | ||
@@ -302,11 +304,11 @@ #### `AnalysisConfig` | ||
| | Function | Check ID(s) | Checks For | | ||
| | ----------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | ||
| | `checkTitle(input)` | `title-presence`, `title-keyphrase` | Title presence **and** length (50–60 chars, validated inside `title-presence`), keyphrase | | ||
| | `checkMetaDescription(input)` | `meta-description-presence`, `meta-description-keyphrase` | Description presence, length (120–160 chars), keyphrase | | ||
| | `checkKeyphraseUsage(input)` | `keyphrase-density`, `keyphrase-distribution` | Density (0.5–2.5%) and occurrence in key areas | | ||
| | `checkHeadings(input)` | `heading-structure`, `heading-keyphrase` | H1 presence, hierarchy, keyphrase in subheadings | | ||
| | `checkWordCount(input)` | `word-count` | Min 300 words (good at 1,000+) | | ||
| | `checkImages(input)` | `image-alt`, `image-keyphrase` | Alt text presence and keyphrase in alt | | ||
| | `checkLinks(input)` | `internal-links`, `external-links` | Internal and external link presence | | ||
| | Function | Check ID(s) | Checks For | | ||
| | ----------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------- | | ||
| | `checkTitle(input)` | `title-presence`, `title-keyphrase` | Title presence **and** length (50–60 chars, validated inside `title-presence`), keyphrase | | ||
| | `checkMetaDescription(input)` | `meta-description-presence`, `meta-description-keyphrase` | Description presence, length (120–160 chars), keyphrase | | ||
| | `checkKeyphraseUsage(input)` | `keyphrase-density`, `keyphrase-distribution` | Density (0.5–2.5%) and occurrence in key areas | | ||
| | `checkHeadings(input)` | `heading-structure`, `heading-keyphrase` | H1 presence, hierarchy, keyphrase in subheadings | | ||
| | `checkWordCount(input)` | `word-count` | Min 300 words (good at 1,000+) | | ||
| | `checkImages(input)` | `image-alt`, `image-keyphrase` | Alt text presence and keyphrase in alt | | ||
| | `checkLinks(input)` | `internal-links`, `external-links` | Internal and external link presence | | ||
@@ -317,9 +319,9 @@ > **Note:** There is no separate `title-length` check ID. Title length validation (50–60 chars) is evaluated inside the `title-presence` check — a title that exists but is outside the recommended range returns `status: 'ok'` rather than `'good'`. | ||
| | Type | Description | | ||
| | ----------------------- | --------------------------------------------------------- | | ||
| | `CheckId` | Union of all 13 built-in check IDs | | ||
| | `AnalysisConfig` | `{ disabledChecks?: CheckId[] }` | | ||
| | `AnalysisStatus` | `'good' \| 'ok' \| 'poor'` | | ||
| | `ContentAnalysisInput` | Input shape for `analyzeContent()` | | ||
| | `ContentAnalysisOutput` | Output shape from `analyzeContent()` | | ||
| | Type | Description | | ||
| | ----------------------- | ------------------------------------------------------------------------ | | ||
| | `CheckId` | Union of all 13 built-in check IDs | | ||
| | `AnalysisConfig` | `{ disabledChecks?: CheckId[] }` | | ||
| | `AnalysisStatus` | `'good' \| 'ok' \| 'poor'` | | ||
| | `ContentAnalysisInput` | Input shape for `analyzeContent()` | | ||
| | `ContentAnalysisOutput` | Output shape from `analyzeContent()` | | ||
| | `AnalysisResult` | Single check result with id, title, description, status, score, maxScore | | ||
@@ -326,0 +328,0 @@ |
-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. |
398
0.51%258509
-0.28%16
-5.88%Updated