diff --git a/docs/assets/img/goatstyles.png b/docs/assets/img/goatstyles.png new file mode 100644 index 0000000..8ea36c5 Binary files /dev/null and b/docs/assets/img/goatstyles.png differ diff --git a/docs/assets/img/social.jpg b/docs/assets/img/social.jpg deleted file mode 100644 index aecc198..0000000 Binary files a/docs/assets/img/social.jpg and /dev/null differ diff --git a/plugins/default_meta/__init__.py b/plugins/default_meta/__init__.py index 36258dc..7440d8c 100644 --- a/plugins/default_meta/__init__.py +++ b/plugins/default_meta/__init__.py @@ -1,57 +1,119 @@ +from typing import Dict, List, Optional, Tuple from mkdocs.plugins import BasePlugin -from mkdocs.config import config_options import os + class DefaultMetaPlugin(BasePlugin): - # A mapping for special case language names - SPECIAL_CASES = { - 'typescript': 'TypeScript', - 'javascript': 'JavaScript', - 'csharp': 'C#', - 'objective-c': 'Objective-C', + """ + An MkDocs plugin that automatically generates and updates meta tags + for pages with enhanced descriptions, keywords, and Open Graph properties. + """ + + LANGUAGES: Dict[str, str] = { + 'cpp': 'C++', 'c': 'C', 'csharp': 'C#', 'css': 'CSS', 'dart': 'Dart', 'go': 'Go', + 'html': 'HTML', 'java': 'Java', 'javascript': 'JavaScript', 'json': 'JSON', + 'kotlin': 'Kotlin', 'markdown': 'Markdown', 'objective-c': 'Objective-C', + 'php': 'PHP', 'python': 'Python', 'ruby': 'Ruby', 'rust': 'Rust', 'scala': 'Scala', + 'shell': 'Shell', 'sql': 'SQL', 'swift': 'Swift', 'typescript': 'TypeScript', + } + + PAGE_TITLES: Dict[str, str] = { + 'index': 'Home', 'about': 'About', 'contributing': 'Contributing', + 'foundation': 'Foundational Code Standards', } - def format_language_name(self, filename): + DEFAULT_KEYWORDS: List[str] = [ + 'Coding Standards', 'Programming Best Practices', 'Coding Guidelines', + 'Software Development', 'Code Quality', 'Software Engineering Principles', + 'Code Review Standards', 'Code Style', 'Source Code formatting', + 'Programming Language Style', 'Clean Code Principles', 'Development Guidelines', + 'Best Coding Practices', 'Coding Style Guides', 'Software Craftsmanship', + 'Code Consistency', 'GoatBytes.IO', 'GoatStyles', 'GoatBytes', + ] + + SITE_DESC: str = ("GoatStyles is an authoritative resource dedicated to promoting " + "best practices and consistency in coding across various programming " + "languages. As a comprehensive style guide repository created by " + "GoatBytes.IO, it aims to elevate code quality and readability for " + "developers worldwide.") + + def __init__(self): + self.site_url: Optional[str] = None + self.keywords: List[str] = [] + + def on_config(self, config): + """Handles configuration to set site-wide settings.""" + self.site_url = config.get('site_url', 'https://styles.goatbytes.io') + # Reset keywords to default at the start of each build to avoid accumulation + self.keywords = self.DEFAULT_KEYWORDS.copy() + + def format_language_name(self, filename: str) -> str: """Format language name correctly based on filename.""" - language = os.path.splitext(filename)[0] - return self.SPECIAL_CASES.get(language, language.capitalize()) - - def on_page_markdown(self, markdown, page, config, files): - # Basic site info - site_url = config.get('site_url', 'https://styles.goatbytes.io') - default_image = f"{site_url}assets/img/social.jpg" - - # Extract and format the language name from the file name - language = self.format_language_name(os.path.basename(page.file.src_path)) - custom_title = f"{language} Code Style Guide | GoatStyles" - custom_description = f"The official {language} code style guide used by GoatBytes.IO." - - # Default meta tags with dynamic title and description - defaults = [ - {'name': 'description', 'content': custom_description}, - {'property': 'og:type', 'content': 'website'}, - {'property': 'og:title', 'content': custom_title}, - {'property': 'og:description', 'content': custom_description}, - {'property': 'og:image', 'content': default_image}, - {'property': 'og:url', 'content': site_url}, - {'name': 'twitter:card', 'content': 'summary_large_image'}, - {'name': 'twitter:title', 'content': custom_title}, - {'name': 'twitter:description', 'content': custom_description}, - {'name': 'twitter:image', 'content': default_image}, + base = os.path.splitext(filename)[0] + return self.LANGUAGES.get(base, base.capitalize()) + + def get_language_keywords(self, language: str) -> List[str]: + """Generate keywords specific to a programming language.""" + return [ + f"{language} Style Guide", + f"{language} Syntax Rules", + f"{language} Coding Conventions" ] - # Initialize or update page meta - if 'meta' not in page.meta: - page.meta['meta'] = defaults + def format_page_title_and_description(self, filename: str) -> Tuple[str, str]: + """Generate title and description based on filename.""" + base, _ = os.path.splitext(filename) + if base in self.PAGE_TITLES: + title = self.PAGE_TITLES[base] + description = self.SITE_DESC + elif base in self.LANGUAGES: + lang = self.LANGUAGES[base] + # Extend keywords list with language-specific keywords + self.keywords.extend(self.get_language_keywords(lang)) + title = f"{lang} Code Style Guide" + description = (f"Explore the official {lang} coding conventions " + "and best practices used by GoatBytes.IO.") else: - # Update existing tags or add defaults if missing - existing_tags = {tag.get('name') or tag.get('property'): tag for tag in page.meta['meta']} - for default in defaults: - key = default.get('name') or default.get('property') - if key not in existing_tags: - page.meta['meta'].append(default) - elif key in ['description', 'og:title', 'og:description', 'twitter:title', 'twitter:description']: - # Update content for specific tags if they already exist - existing_tags[key]['content'] = default['content'] + title = 'GoatStyles Documentation' + description = self.SITE_DESC + return title, description + + def on_page_markdown(self, markdown: str, page, config, files) -> str: + """Add meta tags to page based on content.""" + default_image = f"{self.site_url}/assets/img/goatstyles.png" + page_title, custom_description = self.format_page_title_and_description( + os.path.basename(page.file.src_path) + ) + + # Ensure proper formatting and prevent duplication of meta tags + defaults = self.generate_default_meta(page_title, custom_description, default_image) + + # Initialize or update page meta + page.meta.setdefault('meta', []).extend( + [tag for tag in defaults if tag not in page.meta['meta']] + ) return markdown + + def generate_default_meta(self, title: str, description: str, image: str) -> List[Dict]: + """Generates a list of default meta tags.""" + + # Ensure the image URL does not have double slashes (except after "http:") + image = image.replace("//assets", "/assets") + return [ + {'name': 'description', 'content': description}, + {'name': 'keywords', 'content': ', '.join(self.keywords)}, + {'property': 'og:type', 'content': 'website'}, + {'property': 'og:url', 'content': self.site_url}, + {'property': 'og:site_name', 'content': 'GoatStyles'}, + {'property': 'og:title', 'content': title}, + {'property': 'og:description', 'content': description}, + {'property': 'og:image', 'content': image}, + {'property': 'og:image:type', 'content': 'image/png'}, + {'property': 'og:image:width', 'content': '1200'}, + {'property': 'og:image:height', 'content': '620'}, + {'name': 'twitter:card', 'content': 'summary_large_image'}, + {'name': 'twitter:title', 'content': title}, + {'name': 'twitter:description', 'content': description}, + {'name': 'twitter:image', 'content': image}, + ]