Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/create-release-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,20 @@ jobs:
id: tag-message
run: |
TAG_NAME=${GITHUB_REF#refs/tags/}
TAG_MESSAGE=$(git tag -l --format='%(contents)' $TAG_NAME)
echo "TAG_NAME: $TAG_NAME"
TAG_MESSAGE=$(git tag -l --format='%(contents)' "$TAG_NAME")
echo "message<<EOF" >> $GITHUB_OUTPUT
echo "$TAG_MESSAGE" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "TAG_MESSAGE: $TAG_MESSAGE"

- name: create release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/maddy-src.zip
tag: ${{ github.ref }}
release_name: ${{ github.ref }}
release_name: ${{ github.ref_name }}
body: |
${{ steps.tag-message.outputs.message }}

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ maddy uses [semver versioning](https://semver.org/).
## Upcoming

* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added CMake install and find_package() support.
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Script to update maddy version number in all files.

## version 1.5.0 2025-04-21

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

cmake_minimum_required(VERSION 3.25)

project(maddy VERSION 1.5.0)
project(maddy VERSION 1.5.0) # MADDY_VERSION_LINE_REPLACEMENT

# ------------------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# maddy

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Version: 1.5.0](https://img.shields.io/badge/Version-1.5.0-brightgreen.svg)](https://semver.org/)
[![Version: 1.5.0](https://img.shields.io/badge/Version-1.5.0-brightgreen.svg)](https://semver.org/) <!-- MADDY_VERSION_LINE_REPLACEMENT -->

maddy is a C++ Markdown to HTML **header-only** parser library.

Expand Down
2 changes: 1 addition & 1 deletion include/maddy/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class Parser
*/
static const std::string& version()
{
static const std::string v = "1.5.0";
static const std::string v = "1.5.0"; // MADDY_VERSION_LINE_REPLACEMENT
return v;
}

Expand Down
1 change: 1 addition & 0 deletions tools/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ name = "pypi"

[packages]
requests = "*"
semver = "*"

[dev-packages]

Expand Down
234 changes: 115 additions & 119 deletions tools/Pipfile.lock

Large diffs are not rendered by default.

41 changes: 20 additions & 21 deletions tools/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import sys

# required clang-format version
REQUIRED_VERSION = "18.1.3"
REQUIRED_VERSION = '18.1.3'

def check_clang_format_version():
"""
Expand Down Expand Up @@ -37,13 +37,13 @@ def check_clang_format_version():
break

if version_line != REQUIRED_VERSION:
print(f"Error: Required clang-format version is "
f"{REQUIRED_VERSION}, but found {version_line}.")
print(f'Error: Required clang-format version is '
f'{REQUIRED_VERSION}, but found {version_line}.')
sys.exit(1)
else:
print('clang-format version equals the required version.')
except subprocess.CalledProcessError as e:
print(f"Error checking clang-format version: {e.stderr}")
print(f'Error checking clang-format version: {e.stderr}')
sys.exit(1)

def format_files(dry_run):
Expand All @@ -60,11 +60,11 @@ def format_files(dry_run):
during the actual formatting process.
"""
patterns = [
"bench/**/*.h",
"bench/**/*.cpp",
"include/**/*.h",
"tests/**/*.h",
"tests/**/*.cpp",
'bench/**/*.h',
'bench/**/*.cpp',
'include/**/*.h',
'tests/**/*.h',
'tests/**/*.cpp',
]

files_to_format = []
Expand All @@ -73,10 +73,9 @@ def format_files(dry_run):
files_to_format.extend(matched_files)

if not files_to_format:
print("No files to format.")
print('No files to format.')
return

# Create a space-separated string of files
patterns_arg = ' '.join(file.replace('\\', '/') for file in files_to_format)

cwd = os.getcwd()
Expand All @@ -92,13 +91,13 @@ def format_files(dry_run):
cwd=cwd
)
if result.returncode != 0:
print("Files that need formatting:")
print('Files that need formatting:')
print(result.stdout)
print("Error output:")
print('Error output:')
print(result.stderr)
sys.exit(1)
else:
print("no changes found")
print('no changes found')
else:
# Format the files in place
command = f'clang-format --style=file -i {patterns_arg}'
Expand All @@ -110,7 +109,7 @@ def format_files(dry_run):
cwd=cwd
)
if result.returncode != 0:
print("Error formatting files:")
print('Error formatting files:')
print(result.stderr)
sys.exit(1)
else:
Expand All @@ -125,21 +124,21 @@ def main():
"""
if len(sys.argv) != 2:
print(
"Usage: python format.py <dry_run|format>"
'Usage: python format.py <dry_run|format>'
)
sys.exit(1)
else:
print(f"Running format with {sys.argv[1]}")
print(f'Running format with {sys.argv[1]}')

dry_run = False
if sys.argv[1] == "dry_run":
if sys.argv[1] == 'dry_run':
dry_run = True
elif sys.argv[1] != "format":
print("Invalid argument. Use 'dry_run' or 'format'.")
elif sys.argv[1] != 'format':
print('Invalid argument. Use "dry_run" or "format".')
sys.exit(1)

check_clang_format_version()
format_files(dry_run)

if __name__ == "__main__":
if __name__ == '__main__':
main()
33 changes: 12 additions & 21 deletions tools/update_dependencies.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/python
#
# maddy update dependencies
#
# This project is licensed under the MIT license. For more information see the
# LICENSE file.
import os
Expand All @@ -27,8 +28,8 @@ def get_cmake_files(directory, ignored_dirs=None):
# Modify dirs in place to skip ignored directories
dirs[:] = [d for d in dirs if d not in ignored_dirs]

if "CMakeLists.txt" in files:
cmakelists_paths.append(os.path.join(root, "CMakeLists.txt"))
if 'CMakeLists.txt' in files:
cmakelists_paths.append(os.path.join(root, 'CMakeLists.txt'))

return cmakelists_paths

Expand All @@ -49,29 +50,25 @@ def get_last_dependency_version(url):
ValueError: If the provided URL is not in the expected format.
Exception: If there is an error fetching data from the GitHub API.
"""
# Remove the .git suffix if it exists
if url.endswith('.git'):
url = url[:-4]

# Split the URL to extract owner and repository name
parts = url.split('/')
if len(parts) < 5 or parts[2] != 'github.com':
raise ValueError(f"Invalid GitHub repository URL {url}")
raise ValueError(f'Invalid GitHub repository URL {url}')

owner = parts[3]
repo = parts[4]

# GitHub API endpoint for releases
api_url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest"
api_url = f'https://api.github.com/repos/{owner}/{repo}/releases/latest'

# Make a GET request to the GitHub API
response = requests.get(api_url)

if response.status_code == 200:
release_data = response.json()
return release_data['tag_name'] # Return the latest version tag
else:
raise Exception(f"Error fetching data from GitHub API: {response.status_code} - {response.text}")
raise Exception(f'Error fetching data from GitHub API: {response.status_code} - {response.text}')

def get_current_version_from_fetch_content(cmake_code):
"""
Expand Down Expand Up @@ -102,14 +99,10 @@ def update_fetch_content_versions(cmake_file_path):
with open(cmake_file_path, 'r') as file:
cmake_code = file.read()

# Regular expression to find FetchContent blocks
fetch_content_pattern = r'FetchContent_Declare\s*\(\s*(.*?)\s*\)'

# Find all FetchContent blocks
fetch_content_blocks = re.findall(fetch_content_pattern, cmake_code, re.DOTALL)

for block in fetch_content_blocks:
# Extract the GIT_REPOSITORY line
repo_pattern = r'GIT_REPOSITORY\s+([^\s]+)'
repo_match = re.search(repo_pattern, block)

Expand All @@ -119,13 +112,11 @@ def update_fetch_content_versions(cmake_file_path):
latest_version = get_last_dependency_version(repo_url)

if current_version != latest_version:
# Replace the old version with the new version in the CMake code
new_block = re.sub(r'GIT_TAG\s+([^\s]+)', f'GIT_TAG {latest_version}', block)
cmake_code = cmake_code.replace(block, new_block)

# Write the updated CMake code back to the file
with open(cmake_file_path, 'w', encoding='utf-8', newline='\n') as file:
file.write(cmake_code.replace('\r\n', '\n')) # Ensure LF line
file.write(cmake_code.replace('\r\n', '\n'))

def main():
"""
Expand All @@ -134,22 +125,22 @@ def main():
ignoring specified directories.
"""
if len(sys.argv) < 2:
print("Usage: python update_dependencies.py <directory_path> [ignored_dirs...]")
print('Usage: python update_dependencies.py <directory_path> [ignored_dirs...]')
sys.exit(1)

directory_path = sys.argv[1]
ignored_dirs = sys.argv[2:] # Remaining arguments are ignored directories

if not os.path.isdir(directory_path):
print(f"The provided path '{directory_path}' is not a valid directory.")
print(f'The provided path "{directory_path}" is not a valid directory.')
sys.exit(1)

cmake_files = get_cmake_files(directory_path, ignored_dirs)

for cmake_file in cmake_files:
print(f"Updating {cmake_file}...")
print(f'Updating {cmake_file}...')
update_fetch_content_versions(cmake_file)
print(f"Updated {cmake_file} successfully.")
print(f'Updated {cmake_file} successfully.')

if __name__ == "__main__":
if __name__ == '__main__':
main()
89 changes: 89 additions & 0 deletions tools/update_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/bin/python
#
# maddy update version
#
# Replaces the version in all files in the lines containing
# `MADDY_VERSION_LINE_REPLACEMENT`.
#
# This project is licensed under the MIT license. For more information see the
# LICENSE file.

import mimetypes
import os
import re
from semver import Version
import sys

def update_version_in_file(version, file_path):
"""
Updates the version in the specified file.

Args:
file_path (str): The path to the file where the version needs to be updated.
version (str): The new version string to set in the file.
"""
with open(file_path, 'r') as file:
content = file.read()

new_content = content
lines = new_content.splitlines()

for i, line in enumerate(lines):
if 'MADDY_VERSION_LINE_REPLACEMENT' in line:
lines[i] = re.sub(r'\b\d+\.\d+\.\d+\b', version, line)

new_content = '\n'.join(lines) + '\n'

if new_content != content:
print(f'Updating version in {file_path}')
with open(file_path, 'w', encoding='utf-8', newline='\n') as file:
file.write(new_content.replace('\r\n', '\n'))


def update_version_in_files(version, directory, ignored_dirs):
"""
Updates the version in all files in the specified directory.

Args:
directory (str): The path to the directory containing files.
ignored_dirs (list): A list of directories to ignore during the update.
version (str): The new version string to set in the files.
"""
mimetypes.add_type('text/markdown', '.md')

ignroed_dirs_abs = [os.path.abspath(os.path.join(directory, d)) for d in ignored_dirs]

for root, dirs, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)

if any(os.path.abspath(root).startswith(ignored_dir) for ignored_dir in ignroed_dirs_abs):
continue

if mimetypes.guess_type(file_path)[0] and mimetypes.guess_type(file_path)[0].startswith('text'):
update_version_in_file(version, file_path)


def main():
if len(sys.argv) < 3:
print('Usage: python update_version.py <version> <directory> [ignored_dirs...]')
sys.exit(1)

version = sys.argv[1]
directory = sys.argv[2]
ignored_dirs = sys.argv[3:] if len(sys.argv) > 3 else []

if not os.path.isdir(directory):
print(f'Error: The specified directory "{directory}" does not exist.')
sys.exit(1)

if not Version.is_valid(version):
print(f'Error: The specified version "{version}" is not a valid semantic version.')
sys.exit(1)

update_version_in_files(version, directory, ignored_dirs)
print(f'Updated version to {version} in all files in {directory}')


if __name__ == '__main__':
main()