Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 09c83a8

Browse files
authoredApr 6, 2024··
Merge pull request #8 from goatbytes/develop
meta: Improve generating proper meta tags for open graph and X (Twitter)
2 parents 3ad472d + e00c3e7 commit 09c83a8

File tree

3 files changed

+107
-45
lines changed

3 files changed

+107
-45
lines changed
 

‎docs/assets/img/goatstyles.png

752 KB
Loading

‎docs/assets/img/social.jpg

-86.2 KB
Binary file not shown.

‎plugins/default_meta/__init__.py

+107-45
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,119 @@
1+
from typing import Dict, List, Optional, Tuple
12
from mkdocs.plugins import BasePlugin
2-
from mkdocs.config import config_options
33
import os
44

5+
56
class DefaultMetaPlugin(BasePlugin):
6-
# A mapping for special case language names
7-
SPECIAL_CASES = {
8-
'typescript': 'TypeScript',
9-
'javascript': 'JavaScript',
10-
'csharp': 'C#',
11-
'objective-c': 'Objective-C',
7+
"""
8+
An MkDocs plugin that automatically generates and updates meta tags
9+
for pages with enhanced descriptions, keywords, and Open Graph properties.
10+
"""
11+
12+
LANGUAGES: Dict[str, str] = {
13+
'cpp': 'C++', 'c': 'C', 'csharp': 'C#', 'css': 'CSS', 'dart': 'Dart', 'go': 'Go',
14+
'html': 'HTML', 'java': 'Java', 'javascript': 'JavaScript', 'json': 'JSON',
15+
'kotlin': 'Kotlin', 'markdown': 'Markdown', 'objective-c': 'Objective-C',
16+
'php': 'PHP', 'python': 'Python', 'ruby': 'Ruby', 'rust': 'Rust', 'scala': 'Scala',
17+
'shell': 'Shell', 'sql': 'SQL', 'swift': 'Swift', 'typescript': 'TypeScript',
18+
}
19+
20+
PAGE_TITLES: Dict[str, str] = {
21+
'index': 'Home', 'about': 'About', 'contributing': 'Contributing',
22+
'foundation': 'Foundational Code Standards',
1223
}
1324

14-
def format_language_name(self, filename):
25+
DEFAULT_KEYWORDS: List[str] = [
26+
'Coding Standards', 'Programming Best Practices', 'Coding Guidelines',
27+
'Software Development', 'Code Quality', 'Software Engineering Principles',
28+
'Code Review Standards', 'Code Style', 'Source Code formatting',
29+
'Programming Language Style', 'Clean Code Principles', 'Development Guidelines',
30+
'Best Coding Practices', 'Coding Style Guides', 'Software Craftsmanship',
31+
'Code Consistency', 'GoatBytes.IO', 'GoatStyles', 'GoatBytes',
32+
]
33+
34+
SITE_DESC: str = ("GoatStyles is an authoritative resource dedicated to promoting "
35+
"best practices and consistency in coding across various programming "
36+
"languages. As a comprehensive style guide repository created by "
37+
"GoatBytes.IO, it aims to elevate code quality and readability for "
38+
"developers worldwide.")
39+
40+
def __init__(self):
41+
self.site_url: Optional[str] = None
42+
self.keywords: List[str] = []
43+
44+
def on_config(self, config):
45+
"""Handles configuration to set site-wide settings."""
46+
self.site_url = config.get('site_url', 'https://styles.goatbytes.io')
47+
# Reset keywords to default at the start of each build to avoid accumulation
48+
self.keywords = self.DEFAULT_KEYWORDS.copy()
49+
50+
def format_language_name(self, filename: str) -> str:
1551
"""Format language name correctly based on filename."""
16-
language = os.path.splitext(filename)[0]
17-
return self.SPECIAL_CASES.get(language, language.capitalize())
18-
19-
def on_page_markdown(self, markdown, page, config, files):
20-
# Basic site info
21-
site_url = config.get('site_url', 'https://styles.goatbytes.io')
22-
default_image = f"{site_url}assets/img/social.jpg"
23-
24-
# Extract and format the language name from the file name
25-
language = self.format_language_name(os.path.basename(page.file.src_path))
26-
custom_title = f"{language} Code Style Guide | GoatStyles"
27-
custom_description = f"The official {language} code style guide used by GoatBytes.IO."
28-
29-
# Default meta tags with dynamic title and description
30-
defaults = [
31-
{'name': 'description', 'content': custom_description},
32-
{'property': 'og:type', 'content': 'website'},
33-
{'property': 'og:title', 'content': custom_title},
34-
{'property': 'og:description', 'content': custom_description},
35-
{'property': 'og:image', 'content': default_image},
36-
{'property': 'og:url', 'content': site_url},
37-
{'name': 'twitter:card', 'content': 'summary_large_image'},
38-
{'name': 'twitter:title', 'content': custom_title},
39-
{'name': 'twitter:description', 'content': custom_description},
40-
{'name': 'twitter:image', 'content': default_image},
52+
base = os.path.splitext(filename)[0]
53+
return self.LANGUAGES.get(base, base.capitalize())
54+
55+
def get_language_keywords(self, language: str) -> List[str]:
56+
"""Generate keywords specific to a programming language."""
57+
return [
58+
f"{language} Style Guide",
59+
f"{language} Syntax Rules",
60+
f"{language} Coding Conventions"
4161
]
4262

43-
# Initialize or update page meta
44-
if 'meta' not in page.meta:
45-
page.meta['meta'] = defaults
63+
def format_page_title_and_description(self, filename: str) -> Tuple[str, str]:
64+
"""Generate title and description based on filename."""
65+
base, _ = os.path.splitext(filename)
66+
if base in self.PAGE_TITLES:
67+
title = self.PAGE_TITLES[base]
68+
description = self.SITE_DESC
69+
elif base in self.LANGUAGES:
70+
lang = self.LANGUAGES[base]
71+
# Extend keywords list with language-specific keywords
72+
self.keywords.extend(self.get_language_keywords(lang))
73+
title = f"{lang} Code Style Guide"
74+
description = (f"Explore the official {lang} coding conventions "
75+
"and best practices used by GoatBytes.IO.")
4676
else:
47-
# Update existing tags or add defaults if missing
48-
existing_tags = {tag.get('name') or tag.get('property'): tag for tag in page.meta['meta']}
49-
for default in defaults:
50-
key = default.get('name') or default.get('property')
51-
if key not in existing_tags:
52-
page.meta['meta'].append(default)
53-
elif key in ['description', 'og:title', 'og:description', 'twitter:title', 'twitter:description']:
54-
# Update content for specific tags if they already exist
55-
existing_tags[key]['content'] = default['content']
77+
title = 'GoatStyles Documentation'
78+
description = self.SITE_DESC
79+
return title, description
80+
81+
def on_page_markdown(self, markdown: str, page, config, files) -> str:
82+
"""Add meta tags to page based on content."""
83+
default_image = f"{self.site_url}/assets/img/goatstyles.png"
84+
page_title, custom_description = self.format_page_title_and_description(
85+
os.path.basename(page.file.src_path)
86+
)
87+
88+
# Ensure proper formatting and prevent duplication of meta tags
89+
defaults = self.generate_default_meta(page_title, custom_description, default_image)
90+
91+
# Initialize or update page meta
92+
page.meta.setdefault('meta', []).extend(
93+
[tag for tag in defaults if tag not in page.meta['meta']]
94+
)
5695

5796
return markdown
97+
98+
def generate_default_meta(self, title: str, description: str, image: str) -> List[Dict]:
99+
"""Generates a list of default meta tags."""
100+
101+
# Ensure the image URL does not have double slashes (except after "http:")
102+
image = image.replace("//assets", "/assets")
103+
return [
104+
{'name': 'description', 'content': description},
105+
{'name': 'keywords', 'content': ', '.join(self.keywords)},
106+
{'property': 'og:type', 'content': 'website'},
107+
{'property': 'og:url', 'content': self.site_url},
108+
{'property': 'og:site_name', 'content': 'GoatStyles'},
109+
{'property': 'og:title', 'content': title},
110+
{'property': 'og:description', 'content': description},
111+
{'property': 'og:image', 'content': image},
112+
{'property': 'og:image:type', 'content': 'image/png'},
113+
{'property': 'og:image:width', 'content': '1200'},
114+
{'property': 'og:image:height', 'content': '620'},
115+
{'name': 'twitter:card', 'content': 'summary_large_image'},
116+
{'name': 'twitter:title', 'content': title},
117+
{'name': 'twitter:description', 'content': description},
118+
{'name': 'twitter:image', 'content': image},
119+
]

0 commit comments

Comments
 (0)
Please sign in to comment.