Book Metrics Generator Overview This skill automates the generation of comprehensive metrics for intelligent textbooks. It analyzes the entire textbook structure and content to produce two detailed reports: 1. book-metrics.md - Overall book statistics with links to relevant sections 2. chapter-metrics.md - Chapter-by-chapter breakdown in tabular format The metrics provide quantitative insights into content volume, educational components, and interactive elements, helping authors track progress and identify areas needing attention. Running the Shell Script Directly Tell the user the following:…

, line.strip())\n if match:\n return match.group(1)\n except Exception as e:\n print(f\"Warning: Could not read {markdown_file}: {e}\")\n\n return markdown_file.parent.name\n\n def count_concepts(self) -> int:\n \"\"\"Count concepts from learning-graph.csv.\n\n Returns:\n Number of concepts\n \"\"\"\n csv_file = self.learning_graph_dir / \"learning-graph.csv\"\n\n if not csv_file.exists():\n return 0\n\n try:\n with open(csv_file, 'r', encoding='utf-8') as f:\n reader = csv.DictReader(f)\n return sum(1 for _ in reader)\n except Exception as e:\n print(f\"Warning: Could not read learning graph CSV: {e}\")\n return 0\n\n def count_glossary_terms(self) -> int:\n \"\"\"Count glossary terms from glossary.md.\n\n Returns:\n Number of glossary terms\n \"\"\"\n if not self.glossary_file.exists():\n return 0\n\n try:\n with open(self.glossary_file, 'r', encoding='utf-8') as f:\n content = f.read()\n # Count H4 headers as glossary terms\n h4_count = len(re.findall(r'^####\\s+', content, re.MULTILINE))\n return h4_count\n except Exception as e:\n print(f\"Warning: Could not read glossary: {e}\")\n return 0\n\n def count_faqs(self) -> int:\n \"\"\"Count FAQ items from faq.md.\n\n Returns:\n Number of FAQ items\n \"\"\"\n if not self.faq_file.exists():\n return 0\n\n try:\n with open(self.faq_file, 'r', encoding='utf-8') as f:\n content = f.read()\n # Count H3 headers as FAQ questions\n return len(re.findall(r'^###\\s+', content, re.MULTILINE))\n except Exception as e:\n print(f\"Warning: Could not read FAQ: {e}\")\n return 0\n\n def count_quiz_questions(self) -> int:\n \"\"\"Count quiz questions across all chapters.\n\n Returns:\n Total number of quiz questions\n \"\"\"\n total = 0\n\n if not self.chapters_dir.exists():\n return 0\n\n # Look for quiz.md files in chapter directories\n for chapter_dir in self.chapters_dir.iterdir():\n if chapter_dir.is_dir():\n quiz_file = chapter_dir / \"quiz.md\"\n if quiz_file.exists():\n total += self._count_quiz_in_file(quiz_file)\n\n return total\n\n def _count_quiz_in_file(self, quiz_file: Path) -> int:\n \"\"\"Count quiz questions in a single quiz file.\n\n Args:\n quiz_file: Path to quiz.md file\n\n Returns:\n Number of questions in the file\n \"\"\"\n try:\n with open(quiz_file, 'r', encoding='utf-8') as f:\n content = f.read()\n # Count H4 headers with numbered questions (e.g., \"#### 1.\")\n h4_pattern = len(re.findall(r'^####\\s+\\d+\\.', content, re.MULTILINE))\n # Also count H2 headers as questions (legacy format)\n h2_pattern = len(re.findall(r'^##\\s+', content, re.MULTILINE))\n return h4_pattern + h2_pattern\n except Exception as e:\n print(f\"Warning: Could not read {quiz_file}: {e}\")\n return 0\n\n def count_diagrams_in_file(self, markdown_file: Path) -> int:\n \"\"\"Count diagrams in a single markdown file.\n\n Args:\n markdown_file: Path to markdown file\n\n Returns:\n Number of diagrams (H4 headers starting with \"#### Diagram:\")\n \"\"\"\n try:\n with open(markdown_file, 'r', encoding='utf-8') as f:\n content = f.read()\n return len(re.findall(r'^####\\s+Diagram:', content, re.MULTILINE))\n except Exception as e:\n print(f\"Warning: Could not read {markdown_file}: {e}\")\n return 0\n\n def count_all_diagrams(self) -> int:\n \"\"\"Count all diagrams in all markdown files.\n\n Returns:\n Total number of diagrams\n \"\"\"\n total = 0\n\n # Search all markdown files in docs directory\n for md_file in self.docs_dir.rglob('*.md'):\n total += self.count_diagrams_in_file(md_file)\n\n return total\n\n # TODO: Fix bug in equation counting to avoid double counting dollar amounts in numbers\n def count_equations_in_file(self, markdown_file: Path) -> int:\n \"\"\"Count LaTeX equations in a single markdown file.\n\n Args:\n markdown_file: Path to markdown file\n\n Returns:\n Number of equations (LaTeX expressions)\n \"\"\"\n try:\n with open(markdown_file, 'r', encoding='utf-8') as f:\n content = f.read()\n # Count inline math: $...$\n inline = len(re.findall(r'\\$[^$]+\\

Book Metrics Generator Overview This skill automates the generation of comprehensive metrics for intelligent textbooks. It analyzes the entire textbook structure and content to produce two detailed reports: 1. book-metrics.md - Overall book statistics with links to relevant sections 2. chapter-metrics.md - Chapter-by-chapter breakdown in tabular format The metrics provide quantitative insights into content volume, educational components, and interactive elements, helping authors track progress and identify areas needing attention. Running the Shell Script Directly Tell the user the following:…

, content))\n # Count display math: $...$\n display = len(re.findall(r'\\$\\$[^$]+\\$\\

Book Metrics Generator Overview This skill automates the generation of comprehensive metrics for intelligent textbooks. It analyzes the entire textbook structure and content to produce two detailed reports: 1. book-metrics.md - Overall book statistics with links to relevant sections 2. chapter-metrics.md - Chapter-by-chapter breakdown in tabular format The metrics provide quantitative insights into content volume, educational components, and interactive elements, helping authors track progress and identify areas needing attention. Running the Shell Script Directly Tell the user the following:…

, content))\n return inline + display\n except Exception as e:\n print(f\"Warning: Could not read {markdown_file}: {e}\")\n return 0\n\n # TODO: Fix bug in equation counting to avoid double counting dollar amounts in numbers\n def count_all_equations(self) -> int:\n \"\"\"Count all equations in all markdown files.\n\n Returns:\n Total number of equations\n \"\"\"\n total = 0\n\n # Search all markdown files in docs directory\n for md_file in self.docs_dir.rglob('*.md'):\n total += self.count_equations_in_file(md_file)\n\n return total\n\n def count_microsims(self) -> int:\n \"\"\"Count MicroSim directories in docs/sims.\n\n Returns:\n Number of MicroSim directories\n \"\"\"\n if not self.sims_dir.exists():\n return 0\n\n count = 0\n for item in self.sims_dir.iterdir():\n if item.is_dir() and (item / \"index.md\").exists():\n count += 1\n\n return count\n\n def count_species_cards(self) -> Dict[str, int]:\n \"\"\"Count species cards and per-card asset coverage in docs/plants.\n\n Returns a dict with keys:\n total — number of \u003cslug>.md files in docs/plants/\n with_illustration — cards whose docs/plants/img/\u003cslug>-illustration.png exists\n with_photos — cards with at least one Wikipedia photo\n with_quick_facts — cards whose Quick Facts table has any non-empty cells\n (i.e., something other than \"—\")\n\n Returns all zeros if docs/plants doesn't exist (project doesn't use\n the plant-gallery-generator skill).\"\"\"\n plants_dir = self.docs_dir / \"plants\"\n img_dir = plants_dir / \"img\"\n result = {\n \"total\": 0,\n \"with_illustration\": 0,\n \"with_photos\": 0,\n \"with_quick_facts\": 0,\n }\n if not plants_dir.exists():\n return result\n\n for card in plants_dir.iterdir():\n if not (card.is_file() and card.suffix == \".md\"\n and card.name != \"index.md\"):\n continue\n result[\"total\"] += 1\n slug = card.stem\n try:\n text = card.read_text(encoding=\"utf-8\")\n except Exception:\n continue\n if (img_dir / f\"{slug}-illustration.png\").exists():\n result[\"with_illustration\"] += 1\n # Photo references in the card body, e.g. ![alt](img/\u003cslug>-1.jpg)\n if f\"{slug}-1.jpg\" in text or f\"{slug}-1.JPG\" in text:\n result[\"with_photos\"] += 1\n # Quick Facts populated: at least one DATA row (Family, Height,\n # Bloom time, Sun, Moisture, Soil, Wildlife value) has content\n # other than \"—\". The Scientific name row is auto-populated\n # and doesn't count.\n in_facts = False\n data_keys = {\"family\", \"height\", \"bloom time\", \"sun\",\n \"moisture\", \"soil\", \"wildlife value\",\n \"hardiness zone\", \"native range\"}\n for line in text.splitlines():\n if line.strip().startswith(\"## Quick Facts\"):\n in_facts = True\n continue\n if in_facts:\n if line.strip().startswith(\"## \"):\n break\n if \"|\" in line and \"---\" not in line:\n cells = [c.strip().strip(\"*\").lower()\n for c in line.split(\"|\")[1:-1]]\n if len(cells) >= 2 and cells[0] in data_keys:\n value = cells[1].strip(\"*\")\n if value and value != \"—\":\n result[\"with_quick_facts\"] += 1\n break\n return result\n\n def count_host_plant_relationships(self) -> int:\n \"\"\"Approximate count of host-plant relationships documented in\n chapter prose. Looks for the phrase 'host plant' or 'larval host'\n appearing near a species name. Useful for tracking pollinator-\n ecology coverage in textbooks.\n\n Returns 0 if no chapters use the convention. This is a soft\n metric — exact counts require a pollinator-host-plant matrix\n in structured data, which most textbooks don't have.\"\"\"\n if not self.chapters_dir.exists():\n return 0\n count = 0\n for chapter in self.chapters_dir.iterdir():\n if not chapter.is_dir():\n continue\n index = chapter / \"index.md\"\n if not index.exists():\n continue\n try:\n text = index.read_text(encoding=\"utf-8\").lower()\n except Exception:\n continue\n count += text.count(\"host plant\")\n count += text.count(\"larval host\")\n return count\n\n def count_words_in_file(self, markdown_file: Path) -> int:\n \"\"\"Count words in a single markdown file.\n\n Args:\n markdown_file: Path to markdown file\n\n Returns:\n Number of words\n \"\"\"\n try:\n with open(markdown_file, 'r', encoding='utf-8') as f:\n content = f.read()\n # Remove code blocks\n content = re.sub(r'```.*?```', '', content, flags=re.DOTALL)\n # Remove inline code\n content = re.sub(r'`[^`]+`', '', content)\n # Remove URLs\n content = re.sub(r'https?://\\S+', '', content)\n # Count words\n words = re.findall(r'\\b\\w+\\b', content)\n return len(words)\n except Exception as e:\n print(f\"Warning: Could not read {markdown_file}: {e}\")\n return 0\n\n def count_total_words(self) -> int:\n \"\"\"Count total words in all markdown files.\n\n Returns:\n Total word count\n \"\"\"\n total = 0\n\n # Search all markdown files in docs directory\n for md_file in self.docs_dir.rglob('*.md'):\n total += self.count_words_in_file(md_file)\n\n return total\n\n def count_links_in_file(self, markdown_file: Path) -> int:\n \"\"\"Count markdown links in a single file.\n\n Args:\n markdown_file: Path to markdown file\n\n Returns:\n Number of links\n \"\"\"\n try:\n with open(markdown_file, 'r', encoding='utf-8') as f:\n content = f.read()\n # Count markdown links [text](url)\n return len(re.findall(r'\\[([^\\]]+)\\]\\(([^)]+)\\)', content))\n except Exception as e:\n print(f\"Warning: Could not read {markdown_file}: {e}\")\n return 0\n\n def count_all_links(self) -> int:\n \"\"\"Count all links in all markdown files.\n\n Returns:\n Total number of links\n \"\"\"\n total = 0\n\n # Search all markdown files in docs directory\n for md_file in self.docs_dir.rglob('*.md'):\n total += self.count_links_in_file(md_file)\n\n return total\n\n def calculate_equivalent_pages(self, total_words: int, diagrams: int, microsims: int) -> int:\n \"\"\"Calculate equivalent pages based on words, diagrams, and MicroSims.\n\n Assumptions:\n - 250 words per page\n - Each diagram takes 0.25 page\n - Each MicroSim takes 0.5 page\n\n Args:\n total_words: Total word count\n diagrams: Number of diagrams\n microsims: Number of MicroSims\n\n Returns:\n Estimated page count\n \"\"\"\n words_per_page = 250\n diagram_pages = diagrams * 0.25\n microsim_pages = microsims * 0.5\n text_pages = total_words / words_per_page\n\n return int(text_pages + diagram_pages + microsim_pages)\n\n def count_sections_in_file(self, markdown_file: Path) -> int:\n \"\"\"Count sections (H2 and H3 headers) in a markdown file.\n\n Args:\n markdown_file: Path to markdown file\n\n Returns:\n Number of sections\n \"\"\"\n try:\n with open(markdown_file, 'r', encoding='utf-8') as f:\n content = f.read()\n h2_count = len(re.findall(r'^##\\s+', content, re.MULTILINE))\n h3_count = len(re.findall(r'^###\\s+', content, re.MULTILINE))\n return h2_count + h3_count\n except Exception as e:\n print(f\"Warning: Could not read {markdown_file}: {e}\")\n return 0\n\n def get_chapter_metrics(self, chapter: Dict[str, Any]) -> Dict[str, Any]:\n \"\"\"Get metrics for a single chapter.\n\n Args:\n chapter: Chapter info dict\n\n Returns:\n Dict with chapter metrics\n \"\"\"\n index_file = chapter['index_file']\n chapter_dir = chapter['path']\n\n # Count sections in index.md\n sections = self.count_sections_in_file(index_file)\n\n # Count diagrams in all markdown files in chapter directory\n diagrams = 0\n words = 0\n for md_file in chapter_dir.rglob('*.md'):\n diagrams += self.count_diagrams_in_file(md_file)\n words += self.count_words_in_file(md_file)\n\n return {\n 'number': chapter['number'],\n 'name': chapter['name'],\n 'sections': sections,\n 'diagrams': diagrams,\n 'words': words\n }\n\n def generate_book_metrics_md(self) -> str:\n \"\"\"Generate the book-metrics.md content.\n\n Returns:\n Markdown content as string\n \"\"\"\n # Collect all metrics\n chapter_count, chapters = self.count_chapters()\n concepts = self.count_concepts()\n glossary_terms = self.count_glossary_terms()\n faqs = self.count_faqs()\n quiz_questions = self.count_quiz_questions()\n diagrams = self.count_all_diagrams()\n equations = self.count_all_equations()\n microsims = self.count_microsims()\n total_words = self.count_total_words()\n links = self.count_all_links()\n equivalent_pages = self.calculate_equivalent_pages(total_words, diagrams, microsims)\n species = self.count_species_cards()\n host_relationships = self.count_host_plant_relationships()\n\n # Build markdown table\n md = \"# Book Metrics\\n\\n\"\n md += \"This file contains overall metrics for the intelligent textbook.\\n\\n\"\n md += \"| Metric Name | Value | Link | Notes |\\n\"\n md += \"|-------------|-------|------|-------|\\n\"\n\n # Add rows\n md += f\"| Chapters | {chapter_count} | [Chapters](../chapters/index.md) | Number of chapter directories |\\n\"\n md += f\"| Concepts | {concepts} | [Concept List](./concept-list.md) | Concepts from learning graph |\\n\"\n md += f\"| Glossary Terms | {glossary_terms} | [Glossary](../glossary.md) | Defined terms |\\n\"\n md += f\"| FAQs | {faqs} | [FAQ](../faq.md) | Frequently asked questions |\\n\"\n md += f\"| Quiz Questions | {quiz_questions} | - | Questions across all chapters |\\n\"\n md += f\"| Diagrams | {diagrams} | - | Level 4 headers starting with '#### Diagram:' |\\n\"\n md += f\"| Equations | {equations} | - | LaTeX expressions (inline and display) |\\n\"\n md += f\"| MicroSims | {microsims} | [Simulations](../sims/index.md) | Interactive MicroSims |\\n\"\n md += f\"| Total Words | {total_words:,} | - | Words in all markdown files |\\n\"\n md += f\"| Links | {links} | - | Hyperlinks in markdown format |\\n\"\n md += f\"| Equivalent Pages | {equivalent_pages} | - | Estimated pages (250 words/page + visuals) |\\n\"\n\n # Botany / species-card metrics — only show if the project uses\n # the plant-gallery-generator (i.e., docs/plants/ exists)\n if species[\"total\"] > 0:\n md += f\"| Species Cards | {species['total']} | [Plants](../plants/index.md) | Per-species reference pages |\\n\"\n md += (f\"| Cards w/ Illustration | {species['with_illustration']} \"\n f\"({species['with_illustration'] * 100 // species['total']}%) \"\n f\"| - | Botanical plates available |\\n\")\n md += (f\"| Cards w/ Photos | {species['with_photos']} \"\n f\"({species['with_photos'] * 100 // species['total']}%) \"\n f\"| - | Wikipedia/Wikimedia photo present |\\n\")\n md += (f\"| Cards w/ Quick Facts | {species['with_quick_facts']} \"\n f\"({species['with_quick_facts'] * 100 // species['total']}%) \"\n f\"| - | Trait data populated (not just dashes) |\\n\")\n if host_relationships > 0:\n md += (f\"| Host-plant Mentions | {host_relationships} \"\n f\"| - | Pollinator-host coverage signal |\\n\")\n\n md += \"\\n## Metrics Explanation\\n\\n\"\n md += \"- **Chapters**: Count of chapter directories containing index.md files\\n\"\n md += \"- **Concepts**: Number of rows in learning-graph.csv\\n\"\n md += \"- **Glossary Terms**: H4 headers in glossary.md\\n\"\n md += \"- **FAQs**: H3 headers in faq.md\\n\"\n md += \"- **Quiz Questions**: H4 headers with numbered questions (e.g., '#### 1.') or H2 headers in quiz.md files\\n\"\n md += \"- **Diagrams**: H4 headers starting with '#### Diagram:'\\n\"\n md += \"- **Equations**: LaTeX expressions using $ and $ delimiters\\n\"\n md += \"- **MicroSims**: Directories in docs/sims/ with index.md files\\n\"\n md += \"- **Total Words**: All words in markdown files (excluding code blocks and URLs)\\n\"\n md += \"- **Links**: Markdown-formatted links `[text](url)`\\n\"\n md += \"- **Equivalent Pages**: Based on 250 words/page + 0.25 page/diagram + 0.5 page/MicroSim\\n\"\n if species[\"total\"] > 0:\n md += \"- **Species Cards**: Files in docs/plants/ (excluding index.md)\\n\"\n md += \"- **Cards w/ Illustration**: Cards whose docs/plants/img/\u003cslug>-illustration.png exists\\n\"\n md += \"- **Cards w/ Photos**: Cards referencing at least one \u003cslug>-1.jpg photo\\n\"\n md += \"- **Cards w/ Quick Facts**: Cards whose Quick Facts table has at least one populated row (not just em-dashes)\\n\"\n if host_relationships > 0:\n md += \"- **Host-plant Mentions**: Occurrences of 'host plant' or 'larval host' in chapters — soft signal of pollinator-ecology coverage\\n\"\n\n return md\n\n def generate_chapter_metrics_md(self) -> str:\n \"\"\"Generate the chapter-metrics.md content.\n\n Returns:\n Markdown content as string\n \"\"\"\n # Collect chapter info\n chapter_count, chapters = self.count_chapters()\n\n if chapter_count == 0:\n return \"# Chapter Metrics\\n\\nNo chapters found.\\n\"\n\n # Build markdown table\n md = \"# Chapter Metrics\\n\\n\"\n md += \"This file contains chapter-by-chapter metrics.\\n\\n\"\n md += \"| Chapter | Name | Sections | Diagrams | Words |\\n\"\n md += \"|---------|------|----------|----------|-------|\\n\"\n\n # Add rows for each chapter\n for chapter in chapters:\n metrics = self.get_chapter_metrics(chapter)\n # Create link to chapter index.md (relative to learning-graph directory)\n chapter_dir_name = chapter['path'].name\n chapter_link = f\"[{metrics['name']}](../chapters/{chapter_dir_name}/index.md)\"\n md += f\"| {metrics['number']} | {chapter_link} | {metrics['sections']} | {metrics['diagrams']} | {metrics['words']:,} |\\n\"\n\n md += \"\\n## Metrics Explanation\\n\\n\"\n md += \"- **Chapter**: Chapter number (leading zeros removed)\\n\"\n md += \"- **Name**: Chapter title from index.md\\n\"\n md += \"- **Sections**: Count of H2 and H3 headers in chapter markdown files\\n\"\n md += \"- **Diagrams**: Count of H4 headers starting with '#### Diagram:'\\n\"\n md += \"- **Words**: Word count across all markdown files in the chapter\\n\"\n\n return md\n\n def generate_metrics(self, output_dir: Path = None):\n \"\"\"Generate both metrics files.\n\n Args:\n output_dir: Directory to write files to (defaults to learning-graph directory)\n \"\"\"\n if output_dir is None:\n output_dir = self.learning_graph_dir\n\n # Create output directory if it doesn't exist\n output_dir.mkdir(parents=True, exist_ok=True)\n\n # Generate book metrics\n book_metrics_content = self.generate_book_metrics_md()\n book_metrics_file = output_dir / \"book-metrics.md\"\n with open(book_metrics_file, 'w', encoding='utf-8') as f:\n f.write(book_metrics_content)\n print(f\"✅ Generated {book_metrics_file}\")\n\n # Generate chapter metrics\n chapter_metrics_content = self.generate_chapter_metrics_md()\n chapter_metrics_file = output_dir / \"chapter-metrics.md\"\n with open(chapter_metrics_file, 'w', encoding='utf-8') as f:\n f.write(chapter_metrics_content)\n print(f\"✅ Generated {chapter_metrics_file}\")\n\n\ndef main():\n \"\"\"Main entry point.\"\"\"\n import sys\n\n # Get docs directory from command line or use default\n docs_dir = sys.argv[1] if len(sys.argv) > 1 else \"docs\"\n\n # Check if docs directory exists\n if not Path(docs_dir).exists():\n print(f\"❌ Error: Directory '{docs_dir}' does not exist\")\n sys.exit(1)\n\n # Generate metrics\n generator = BookMetricsGenerator(docs_dir)\n generator.generate_metrics()\n\n print(\"\\n✅ Book metrics generation version 0.02 complete!\")\n print(\"\\nhttp://localhost:8000/conversational-ai/learning-graph/book-metrics/\")\n print(\"http://localhost:8000/conversational-ai/learning-graph/chapter-metrics/\")\n\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":25435,"content_sha256":"24d08819ec2366028c9400355040fc48e3b73ab7dec799d9e276594bcb860063"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Book Metrics Generator","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill automates the generation of comprehensive metrics for intelligent textbooks. It analyzes the entire textbook structure and content to produce two detailed reports:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"book-metrics.md","type":"text","marks":[{"type":"strong"}]},{"text":" - Overall book statistics with links to relevant sections","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"chapter-metrics.md","type":"text","marks":[{"type":"strong"}]},{"text":" - Chapter-by-chapter breakdown in tabular format","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"The metrics provide quantitative insights into content volume, educational components, and interactive elements, helping authors track progress and identify areas needing attention.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Running the Shell Script Directly","type":"text"}]},{"type":"paragraph","content":[{"text":"Tell the user the following:","type":"text"}]},{"type":"paragraph","content":[{"text":"We setup this skill mostly to automate the process of installing the shell script. The shell script calls a Python program that does the work of building the metrics files. If you want to save a few tokens, after the skill is installed (a symbolic link really) you can run the following from your terminal:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sh"},"content":[{"text":"~/.claude/skills/book-metrics-generator/scripts/book-metrics-generator.sh","type":"text"}]},{"type":"paragraph","content":[{"text":"Just make sure that you do a git pull on the claude-skills repo to get the latest version.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to Use This Skill","type":"text"}]},{"type":"paragraph","content":[{"text":"Use this skill when:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tracking progress on intelligent textbook development","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Preparing status reports for stakeholders or collaborators","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Assessing content completeness before publication","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Analyzing the distribution of educational elements across chapters","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Estimating the physical page equivalent of the digital textbook","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Auditing content after major updates or additions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Comparing metrics over time to track growth","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"The skill is designed for MkDocs Material-based intelligent textbooks following the structure defined in the intelligent-textbook skill.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Prerequisites","type":"text"}]},{"type":"paragraph","content":[{"text":"The intelligent textbook project should have:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A ","type":"text"},{"text":"docs/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory containing the textbook content","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A ","type":"text"},{"text":"docs/chapters/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory with chapter subdirectories (e.g., ","type":"text"},{"text":"01-chapter-name/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"02-chapter-name/","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Each chapter directory containing an ","type":"text"},{"text":"index.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" file","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A ","type":"text"},{"text":"docs/learning-graph/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory (will be created if it doesn't exist)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Optional components that enhance metrics:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/learning-graph/learning-graph.csv","type":"text","marks":[{"type":"code_inline"}]},{"text":" - For concept counting","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/glossary.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" - For glossary term counting","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/faq.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" - For FAQ counting","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/sims/","type":"text","marks":[{"type":"code_inline"}]},{"text":" - For MicroSim counting","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Chapter-level ","type":"text"},{"text":"quiz.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files - For quiz question counting","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Usage","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Basic Workflow","type":"text"}]},{"type":"paragraph","content":[{"text":"To generate metrics for an intelligent textbook:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Navigate to the textbook project root directory","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Execute the shell script:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"./scripts/book-metrics-generator.sh","type":"text"}]},{"type":"paragraph","content":[{"text":"Or if the skill scripts are available:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash /path/to/skill/scripts/book-metrics-generator.sh","type":"text"}]},{"type":"ordered_list","attrs":{"order":3,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Review the generated files:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/learning-graph/book-metrics.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/learning-graph/chapter-metrics.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Update ","type":"text"},{"text":"mkdocs.yml","type":"text","marks":[{"type":"code_inline"}]},{"text":" navigation to include the new metrics files:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"nav:\n - Learning Graph:\n - Book Metrics: learning-graph/book-metrics.md\n - Chapter Metrics: learning-graph/chapter-metrics.md","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Custom Docs Directory","type":"text"}]},{"type":"paragraph","content":[{"text":"To analyze a textbook in a non-standard location:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"./scripts/book-metrics-generator.sh path/to/custom/docs","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Running the Python Script Directly","type":"text"}]},{"type":"paragraph","content":[{"text":"For more control or integration into custom workflows:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 scripts/book-metrics.py docs","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Book Metrics Collected","type":"text"}]},{"type":"paragraph","content":[{"text":"The ","type":"text"},{"text":"book-metrics.md","type":"text","marks":[{"type":"strong"}]},{"text":" file contains a four-column table with the following metrics:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Category","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Metric","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Structure","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Chapters","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Count of chapter directories with index.md files","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Learning","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Concepts","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Number of concepts in learning-graph.csv","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Learning","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Glossary Terms","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Count of defined terms (H2/H3 headers in glossary.md)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Learning","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"FAQs","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Number of FAQ items (H2 headers in faq.md)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Assessment","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Quiz Questions","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Total quiz questions across all chapters","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Visual","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Diagrams","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Count of H4 headers starting with \"#### Diagram:\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Technical","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Equations","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"LaTeX expressions using $ and $ delimiters","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Interactive","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MicroSims","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Directories in docs/sims/ with index.md files","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Content","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Total Words","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"All words in markdown files (excluding code and URLs)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Content","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Links","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Markdown-formatted hyperlinks ","type":"text"},{"text":"text","type":"text","marks":[{"type":"link","attrs":{"href":"url","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Estimation","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Equivalent Pages","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Calculated pages based on words + visuals","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Page Calculation Formula","type":"text"}]},{"type":"paragraph","content":[{"text":"Equivalent pages are estimated using:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Pages = (Total Words ÷ 250) + (Diagrams × 0.25) + (MicroSims × 0.5)","type":"text"}]},{"type":"paragraph","content":[{"text":"Assumptions:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"250 words per printed page","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Each diagram occupies 0.25 page","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Each MicroSim occupies 0.5 page","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Chapter Metrics Collected","type":"text"}]},{"type":"paragraph","content":[{"text":"The ","type":"text"},{"text":"chapter-metrics.md","type":"text","marks":[{"type":"strong"}]},{"text":" file contains a table with these columns:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Column","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Chapter","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Chapter number (leading zeros removed)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Name","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Chapter title extracted from index.md H1 header","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Sections","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Count of H2 and H3 headers in chapter markdown files","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Diagrams","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Count of \"#### Diagram:\" headers in chapter","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Words","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Total word count for all markdown in the chapter","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"This table enables quick identification of:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Chapters with insufficient content","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Uneven content distribution","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Chapters lacking visual aids","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Outlier chapters requiring review","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Technical Details","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"File Detection Patterns","type":"text"}]},{"type":"paragraph","content":[{"text":"The Python script uses these patterns to count elements:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Chapters","type":"text","marks":[{"type":"strong"}]},{"text":": Directories in ","type":"text"},{"text":"docs/chapters/","type":"text","marks":[{"type":"code_inline"}]},{"text":" containing ","type":"text"},{"text":"index.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Concepts","type":"text","marks":[{"type":"strong"}]},{"text":": Rows in ","type":"text"},{"text":"docs/learning-graph/learning-graph.csv","type":"text","marks":[{"type":"code_inline"}]},{"text":" (excluding header)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Glossary Terms","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"^##","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"^###","type":"text","marks":[{"type":"code_inline"}]},{"text":" patterns in ","type":"text"},{"text":"glossary.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"FAQs","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"^##","type":"text","marks":[{"type":"code_inline"}]},{"text":" pattern in ","type":"text"},{"text":"faq.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Quiz Questions","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"^##","type":"text","marks":[{"type":"code_inline"}]},{"text":" pattern in all ","type":"text"},{"text":"quiz.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Diagrams","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"^####\\s+Diagram:","type":"text","marks":[{"type":"code_inline"}]},{"text":" pattern (multiline flag)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Equations","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"\\$[^$]+\\$","type":"text","marks":[{"type":"code_inline"}]},{"text":" (inline) and ","type":"text"},{"text":"\\$\\$[^$]+\\$\\$","type":"text","marks":[{"type":"code_inline"}]},{"text":" (display)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MicroSims","type":"text","marks":[{"type":"strong"}]},{"text":": Subdirectories in ","type":"text"},{"text":"docs/sims/","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"index.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Links","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"\\[([^\\]]+)\\]\\(([^)]+)\\)","type":"text","marks":[{"type":"code_inline"}]},{"text":" pattern","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Word Counting Methodology","type":"text"}]},{"type":"paragraph","content":[{"text":"To ensure accurate word counts, the script:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Removes code blocks (triple backticks)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Removes inline code (single backticks)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Removes URLs (http/https links)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Counts word boundaries using ","type":"text"},{"text":"\\b\\w+\\b","type":"text","marks":[{"type":"code_inline"}]},{"text":" pattern","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Error Handling","type":"text"}]},{"type":"paragraph","content":[{"text":"The script gracefully handles:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing directories (returns 0 for counts)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing files (returns 0 for counts)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Malformed CSV files (prints warning, returns 0)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Encoding issues (UTF-8 with fallback)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Permission errors (prints warning, continues)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Extending the Metrics","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Adding New Book-Level Metrics","type":"text"}]},{"type":"paragraph","content":[{"text":"To add a new book-level metric:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add a counting method to the ","type":"text"},{"text":"BookMetricsGenerator","type":"text","marks":[{"type":"code_inline"}]},{"text":" class:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"def count_new_metric(self) -> int:\n \"\"\"Count the new metric.\n\n Returns:\n Number of items\n \"\"\"\n # Implementation here\n pass","type":"text"}]},{"type":"ordered_list","attrs":{"order":2,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Update ","type":"text"},{"text":"generate_book_metrics_md()","type":"text","marks":[{"type":"code_inline"}]},{"text":" to call the new method:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"new_metric = self.count_new_metric()","type":"text"}]},{"type":"ordered_list","attrs":{"order":3,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add a row to the markdown table:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"md += f\"| New Metric | {new_metric} | [Link](path) | Description |\\n\"","type":"text"}]},{"type":"ordered_list","attrs":{"order":4,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add explanation in the \"Metrics Explanation\" section","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Adding New Chapter-Level Metrics","type":"text"}]},{"type":"paragraph","content":[{"text":"To add a new chapter-level metric:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Update ","type":"text"},{"text":"get_chapter_metrics()","type":"text","marks":[{"type":"code_inline"}]},{"text":" to compute the new metric:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"def get_chapter_metrics(self, chapter: Dict[str, Any]) -> Dict[str, Any]:\n # Existing code...\n\n # Add new metric\n new_metric = self.count_new_metric_for_chapter(chapter)\n\n return {\n # Existing fields...\n 'new_metric': new_metric\n }","type":"text"}]},{"type":"ordered_list","attrs":{"order":2,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Update ","type":"text"},{"text":"generate_chapter_metrics_md()","type":"text","marks":[{"type":"code_inline"}]},{"text":" to include the new column:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"md += \"| Chapter | Name | ... | New Metric |\\n\"\n# In the row loop:\nmd += f\"| {metrics['number']} | ... | {metrics['new_metric']} |\\n\"","type":"text"}]},{"type":"ordered_list","attrs":{"order":3,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add explanation in the \"Metrics Explanation\" section","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Integration with Workflows","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"After Content Generation","type":"text"}]},{"type":"paragraph","content":[{"text":"Run metrics generation after completing chapters:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Generate chapter content\n/skill intelligent-textbook\n\n# Generate metrics\n/skill book-metrics-generator\n\n# Review progress\ncat docs/learning-graph/book-metrics.md","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Continuous Integration","type":"text"}]},{"type":"paragraph","content":[{"text":"Add to ","type":"text"},{"text":".github/workflows/metrics.yml","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"name: Generate Metrics\n\non:\n push:\n paths:\n - 'docs/**/*.md'\n\njobs:\n metrics:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n - name: Generate metrics\n run: python3 scripts/book-metrics.py docs\n - name: Commit metrics\n run: |\n git config user.name \"GitHub Actions\"\n git add docs/learning-graph/book-metrics.md\n git add docs/learning-graph/chapter-metrics.md\n git commit -m \"Update metrics\" || exit 0\n git push","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Pre-Deployment Checklist","type":"text"}]},{"type":"paragraph","content":[{"text":"Before deploying the textbook:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run metrics generation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify all chapters have reasonable word counts (>1000 words)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check that quiz questions exist for most chapters","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Ensure MicroSims cover key concepts","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Review total page count for scope appropriateness","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Troubleshooting","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"No Chapters Found","type":"text"}]},{"type":"paragraph","content":[{"text":"Symptom","type":"text","marks":[{"type":"strong"}]},{"text":": \"No chapters found\" in chapter-metrics.md","type":"text"}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Ensure chapter directories:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Are located in ","type":"text"},{"text":"docs/chapters/","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Contain an ","type":"text"},{"text":"index.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" file","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Follow naming pattern: ","type":"text"},{"text":"NN-chapter-name/","type":"text","marks":[{"type":"code_inline"}]},{"text":" (where NN is a number)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Concept Count is Zero","type":"text"}]},{"type":"paragraph","content":[{"text":"Symptom","type":"text","marks":[{"type":"strong"}]},{"text":": Concepts metric shows 0","type":"text"}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Verify that:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/learning-graph/learning-graph.csv","type":"text","marks":[{"type":"code_inline"}]},{"text":" exists","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"CSV file has correct format (header row + data rows)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"CSV file is UTF-8 encoded","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Missing Metrics Files","type":"text"}]},{"type":"paragraph","content":[{"text":"Symptom","type":"text","marks":[{"type":"strong"}]},{"text":": Metrics files not created","type":"text"}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Check that:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docs/learning-graph/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory exists (script creates it if missing)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User has write permissions to the directory","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Python 3 is installed and accessible via ","type":"text"},{"text":"python3","type":"text","marks":[{"type":"code_inline"}]},{"text":" command","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Incorrect Word Counts","type":"text"}]},{"type":"paragraph","content":[{"text":"Symptom","type":"text","marks":[{"type":"strong"}]},{"text":": Word counts seem too high or too low","type":"text"}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": The script excludes code blocks and URLs. To verify:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check for large code blocks that should be excluded","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Review markdown files for formatting issues","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Ensure no binary or non-text files with .md extension","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Resources","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"scripts/","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill includes two executable scripts:","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"book-metrics-generator.sh","type":"text"}]},{"type":"paragraph","content":[{"text":"Bash wrapper script that:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validates the docs directory exists","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Checks for Python 3 installation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Executes the Python metrics generator","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Provides user-friendly output","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Default usage assumes ","type":"text"},{"text":"docs/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory in current working directory.","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"book-metrics.py","type":"text"}]},{"type":"paragraph","content":[{"text":"Python 3 script that:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Implements modular ","type":"text"},{"text":"BookMetricsGenerator","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Provides separate methods for each metric type","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generates markdown-formatted output","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Handles errors gracefully with warnings","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Supports custom docs directory path","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"The Python script is designed for extensibility - new metrics can be added by implementing new counting methods and updating the markdown generation functions.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Example Output","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Book Metrics Table Sample","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"| Metric Name | Value | Link | Notes |\n|-------------|-------|------|-------|\n| Chapters | 12 | [Chapters](../chapters/) | Number of chapter directories |\n| Concepts | 200 | [Learning Graph](learning-graph.csv) | Concepts from learning graph |\n| Total Words | 45,000 | - | Words in all markdown files |\n| Equivalent Pages | 195 | - | Estimated pages (250 words/page + visuals) |","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Chapter Metrics Table Sample","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"| Chapter | Name | Sections | Diagrams | Words |\n|---------|------|----------|----------|-------|\n| 1 | Introduction to Geometry | 8 | 3 | 3,200 |\n| 2 | Points and Lines | 12 | 7 | 4,100 |\n| 3 | Angles and Triangles | 15 | 12 | 5,500 |","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Related Skills","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"intelligent-textbook","type":"text","marks":[{"type":"strong"}]},{"text":" - Complete textbook generation workflow (runs before metrics)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"learning-graph-generator","type":"text","marks":[{"type":"strong"}]},{"text":" - Creates the concept graph (provides concept count)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glossary-generator","type":"text","marks":[{"type":"strong"}]},{"text":" - Generates glossary (provides glossary term count)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"faq-generator","type":"text","marks":[{"type":"strong"}]},{"text":" - Creates FAQ section (provides FAQ count)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"quiz-generator","type":"text","marks":[{"type":"strong"}]},{"text":" - Generates quizzes (provides quiz question count)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"chapter-content-generator","type":"text","marks":[{"type":"strong"}]},{"text":" - Creates chapter content (provides word count)","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"book-metrics-generator","author":"@skillopedia","source":{"stars":72,"repo_name":"claude-skills","origin_url":"https://github.com/dmccreary/claude-skills/blob/HEAD/skills/book-metrics-generator/SKILL.md","repo_owner":"dmccreary","body_sha256":"9cd4a7b0c08d7ece663ba5703f21807081828af272e1922a7599298a37c1e0f7","cluster_key":"0389eb70600c7a86e07d4e1114d08cedcabf977032c3f4cfcc2f9f6345f873da","clean_bundle":{"format":"clean-skill-bundle-v1","source":"dmccreary/claude-skills/skills/book-metrics-generator/SKILL.md","attachments":[{"id":"8862ecec-2508-58b2-bc60-6ff26aac33e5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8862ecec-2508-58b2-bc60-6ff26aac33e5/attachment.sh","path":"scripts/book-metrics-generator.sh","size":1227,"sha256":"d6715f0ef3031edb7e8473ca8db4d5a5cdb20ac503839d68c9b3196d31f33fe1","contentType":"application/x-sh; charset=utf-8"},{"id":"5abbee6b-58ba-56bb-8472-9afc354b79a7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5abbee6b-58ba-56bb-8472-9afc354b79a7/attachment.py","path":"scripts/book-metrics.py","size":25435,"sha256":"24d08819ec2366028c9400355040fc48e3b73ab7dec799d9e276594bcb860063","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"ec348d93897477cb69ee55da655401905566876abf7a0abf748ebe66676de5f3","attachment_count":2,"text_attachments":2,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/book-metrics-generator/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"web-development","category_label":"Web"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"web-development","import_tag":"clean-skills-v1","description":"This skill generates comprehensive metrics reports for intelligent textbooks built with MkDocs Material, analyzing chapters, concepts, glossary terms, FAQs, quiz questions, diagrams, equations, MicroSims, word counts, and links. Use this skill when working with an intelligent textbook project that needs quantitative analysis of its content, typically after significant content development or for project status reporting. The skill creates two markdown files - book-metrics.md with overall statistics and chapter-metrics.md with per-chapter breakdowns - in the docs/learning-graph/ directory."}},"renderedAt":1782988942276}

Book Metrics Generator Overview This skill automates the generation of comprehensive metrics for intelligent textbooks. It analyzes the entire textbook structure and content to produce two detailed reports: 1. book-metrics.md - Overall book statistics with links to relevant sections 2. chapter-metrics.md - Chapter-by-chapter breakdown in tabular format The metrics provide quantitative insights into content volume, educational components, and interactive elements, helping authors track progress and identify areas needing attention. Running the Shell Script Directly Tell the user the following:…