28 Commits

Author SHA1 Message Date
Petra Baranski
9c2ac44df0 update changelog 2025-05-01 05:41:35 +02:00
github-actions
48347d3963 Update dependency versions 2025-05-01 01:01:47 +00:00
Petra Baranski
4f977219c3 Release 1.5.0
Some checks failed
run-checks / run-clang-format (push) Has been cancelled
run-tests / test-on-ubuntu (push) Has been cancelled
run-tests / test-on-windows (push) Has been cancelled
run-tests / test-on-osx (push) Has been cancelled
Update dependency versions / update-fetch-content (push) Has been cancelled
* Use the git tag as release name
* Update version to 1.5.0
* stabilize benchmark code
2025-04-21 12:43:45 +02:00
Petra Baranski
9ec4777a7b Add benchmark
Some checks failed
run-checks / run-clang-format (push) Has been cancelled
run-tests / test-on-ubuntu (push) Has been cancelled
run-tests / test-on-windows (push) Has been cancelled
run-tests / test-on-osx (push) Has been cancelled
* add benchmark option
* updated changelog
* added benchmark info to readme
* add bench folder to format.py
2025-04-21 01:02:07 +02:00
Lucian Smith
2a00c9fb0b Add regex for title text version of links
* Add regex for title text version of links

Original parser matched:
  [name](http:://link)

Add match for:
  [name](http:://link "title text")

* Add tests and improve regex's
* Several new tests in test_maddy_linkparser.cpp  (Some with paths for future improvement, and one to ensure an overzealous future update doesn't disallow actually-used special characters like o-umlaut).
* URLs now ignore leading/trailing spaces.
* URLs now don't match on internal spaces or quotes.
* Small grammar fix in CONTRIBUTING.md
* Updated changelog.
2025-04-20 18:45:27 +02:00
Petra Baranski
af59cd13d4 Update pull_request_template.md
Some checks failed
run-checks / run-clang-format (push) Has been cancelled
run-tests / test-on-ubuntu (push) Has been cancelled
run-tests / test-on-windows (push) Has been cancelled
run-tests / test-on-osx (push) Has been cancelled
2025-04-18 12:52:51 +02:00
Petra Baranski
f7d2e69e44 Create pull_request_template.md 2025-04-18 12:49:42 +02:00
Petra Baranski
261e75f22f Release should use the actual annotated tag message
Some checks failed
run-checks / run-clang-format (push) Has been cancelled
run-tests / test-on-ubuntu (push) Has been cancelled
run-tests / test-on-windows (push) Has been cancelled
run-tests / test-on-osx (push) Has been cancelled
Update dependency versions / update-fetch-content (push) Has been cancelled
2025-03-28 05:22:54 +01:00
Petra Baranski
731827264e Fix workflow indentation 2025-03-28 05:17:38 +01:00
Petra Baranski
100eb59bc8 Release 1.4.0
* up version to 1.4.0
* Remove deprecated code
* change release message
2025-03-28 05:04:55 +01:00
Petra Baranski
4518e402c7 Fix linkparser line handling with multiple parenthesis 2025-03-28 03:37:04 +01:00
github-actions[bot]
a5b18310a8 Update dependency versions (#67)
Some checks failed
run-checks / run-clang-format (push) Has been cancelled
run-tests / test-on-ubuntu (push) Has been cancelled
run-tests / test-on-windows (push) Has been cancelled
run-tests / test-on-osx (push) Has been cancelled
* Update dependency versions
* update changelog

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Petra Baranski <info@progsource.de>
2025-03-01 14:19:35 +01:00
github-actions[bot]
8aa290cd38 Update dependency versions
Co-authored-by: github-actions <github-actions@github.com>

* googletest v1.15.2
2024-11-16 06:46:02 +01:00
Petra Baranski
798863e292 fix: update dependencies pipeline 2024-11-16 06:40:12 +01:00
Petra Baranski
ee4b0cc2e2 ci: Add update dependencies 2024-11-16 06:06:28 +01:00
Petra Baranski
d0dae091e0 chore: Add clang-format 2024-11-16 05:50:22 +01:00
Petra Baranski
1f12bc15b6 Update GoogleTest to v1.15.0 2024-07-20 13:46:24 +02:00
dependabot[bot]
369859f7ed build(deps): bump actions/checkout from 3 to 4 (#61)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-19 05:30:16 +02:00
Petra Baranski
2e8e538660 Create dependabot.yml 2024-07-19 05:25:12 +02:00
Petra Baranski
0a97ad8079 trigger run tests on any pull request 2024-07-19 05:16:47 +02:00
Petra Baranski
1fe37d5a1f chore: fix other.yml 2023-08-26 13:34:41 +02:00
Petra Baranski
6e01add19a Merge pull request #49 from progsource/rc-1.3.0
Release 1.3.0
2023-08-26 13:33:19 +02:00
Petra Baranski
65730beffa chore: update version to 1.3.0 2023-08-26 13:28:28 +02:00
Petra Baranski
4722932068 docs: updated changelog 2023-08-26 13:25:11 +02:00
Petra Baranski
c4ca557e43 Merge pull request #48 from progsource/headline-inline-parsing
Headline inline parsing
2023-08-26 13:11:04 +02:00
Petra Baranski
650ea2bc82 ci: enable test runners for dev branch 2023-08-26 13:08:06 +02:00
Petra Baranski
ce81283b26 feat: enable optional inline parsing in headlines 2023-08-26 13:03:35 +02:00
Petra Baranski
211b627a75 chore: added 'other' issue template 2023-08-26 13:01:27 +02:00
70 changed files with 2043 additions and 844 deletions

46
.clang-format Normal file
View File

@@ -0,0 +1,46 @@
BasedOnStyle: Google
AccessModifierOffset: -2
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
ConstructorInitializerIndentWidth: 2
BracedInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
IndentAccessModifiers: false
InsertNewlineAtEOF: true
LambdaBodyIndentation: Signature
AlignAfterOpenBracket: BlockIndent
AllowShortIfStatementsOnASingleLine: Never
BinPackArguments: false
BinPackParameters: false
AllowShortLambdasOnASingleLine: All
SpacesBeforeTrailingComments: 1
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: true
IndentBraces: false
BeforeWhile: true
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
IncludeCategories:
- Regex: '^<.*>'
Priority: 1
- Regex: '^"maddy/.*'
Priority: 3
- Regex: '.*'
Priority: 2
SortIncludes: true
IncludeBlocks: Regroup
InsertTrailingCommas: Wrapped

View File

@@ -8,5 +8,8 @@ indent_style = space
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
[*.{h,hh,hpp,c,cc,cpp,cxx,yml}] [*.{h,hh,hpp,c,cc,cpp,cxx,yml,py,md}]
indent_size = 2
[CMakeLists.txt]
indent_size = 2 indent_size = 2

View File

@@ -37,7 +37,11 @@ body:
label: maddy version label: maddy version
description: What version of maddy are you using? description: What version of maddy are you using?
options: options:
- 1.2.0 (latest) - 1.5.0 (latest)
- 1.4.0
- 1.3.0
- 1.2.1
- 1.2.0
- 1.1.2 - 1.1.2
- 1.1.1 - 1.1.1
- 1.1.0 - 1.1.0

View File

@@ -37,7 +37,11 @@ body:
label: maddy version label: maddy version
description: What version of maddy are you using? description: What version of maddy are you using?
options: options:
- 1.2.0 (latest) - 1.5.0 (latest)
- 1.4.0
- 1.3.0
- 1.2.1
- 1.2.0
- 1.1.2 - 1.1.2
- 1.1.1 - 1.1.1
- 1.1.0 - 1.1.0
@@ -51,7 +55,7 @@ body:
id: example id: example
attributes: attributes:
label: Minimal Mardown example label: Minimal Mardown example
description: To be able to reproduce your issue, please give some example Markdown which creates problems. description: To be able to reproduce your issue, please give some example Markdown which creates problems. Please indent the Markdown by 4 spaces.
validations: validations:
required: true required: true
- type: textarea - type: textarea

10
.github/ISSUE_TEMPLATE/other.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
name: Other
description: Anything that doesn't fit into one of the other issue categories
body:
- type: textarea
id: whats-up
attributes:
label: What is the issue?
description: Is some tooling not working? Performance issues? ...
validations:
required: true

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "monthly"

11
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,11 @@
### Description of the change
*Please describe what has changed and why. If it fixes an open issue, mention it here.*
### Checklist for contributor
* [ ] if you want to be mentioned in the [AUTHORS](https://github.com/progsource/maddy/blob/master/AUTHORS) file, you added yourself
* [ ] added an entry to [CHANGELOG.md](https://github.com/progsource/maddy/blob/master/CHANGELOG.md) at "Upcoming"
* [ ] if any Markdown definition changed, you updated the [definition docs](https://github.com/progsource/maddy/blob/master/docs/definitions.md)
* [ ] your C++ code change is accommodated with a unit/integration test where it makes sense
* [ ] your code meets the code format style (clang-format) of the project (`tools/format.py`)

View File

@@ -11,7 +11,7 @@ jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
with: with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
@@ -25,10 +25,25 @@ jobs:
cmake -DMADDY_CREATE_PACKAGE=ON .. cmake -DMADDY_CREATE_PACKAGE=ON ..
make maddy_package make maddy_package
- name: Get current tag message
id: tag-message
run: |
TAG_NAME=${GITHUB_REF#refs/tags/}
TAG_MESSAGE=$(git tag -l --format='%(contents)' $TAG_NAME)
echo "message<<EOF" >> $GITHUB_OUTPUT
echo "$TAG_MESSAGE" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: create release - name: create release
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/maddy-src.zip file: build/maddy-src.zip
tag: ${{ github.ref }} tag: ${{ github.ref }}
body: "You can find all changes of this release in the [changelog](https://github.com/progsource/maddy/blob/master/CHANGELOG.md)" release_name: ${{ github.ref }}
body: |
${{ steps.tag-message.outputs.message }}
---
[full changelog](https://github.com/progsource/maddy/blob/master/CHANGELOG.md)

24
.github/workflows/run-checks.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: run-checks
run-name: run-checks ${{ github.ref }}
on:
push:
branches:
- master
pull_request:
jobs:
run-clang-format:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.8'
- name: Run format script with dry_run
run: |
clang-format --version
python tools/format.py dry_run

View File

@@ -5,13 +5,11 @@ on:
branches: branches:
- master - master
pull_request: pull_request:
branches:
- master
jobs: jobs:
test-on-ubuntu: test-on-ubuntu:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
with: with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
@@ -29,7 +27,7 @@ jobs:
test-on-windows: test-on-windows:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
with: with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
@@ -47,7 +45,7 @@ jobs:
test-on-osx: test-on-osx:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
with: with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version

View File

@@ -0,0 +1,54 @@
name: Update dependency versions
permissions:
contents: write
pull-requests: write
on:
schedule:
# This cron expression runs the job at 00:00 UTC on the first day of every month
- cron: '0 0 1 * *'
workflow_dispatch: # Allows manual triggering of the workflow
jobs:
update-fetch-content:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Pipenv
run: pip install pipenv
- name: Install dependencies
run: |
cd tools
pipenv install
- name: Run update scripts
run: |
cd tools
pipenv run python update_dependencies.py .. tmp tools build docs .github
- name: Check for changes
id: check_changes
run: |
git config --local user.name "github-actions"
git config --local user.email "github-actions@github.com"
git add .
git diff --cached --exit-code || echo "changed=true" >> $GITHUB_OUTPUT
- name: Create Pull Request
if: steps.check_changes.outputs.changed == 'true'
run: |
git commit -m "Update dependency versions"
git push origin HEAD:update-dependency-versions
gh pr create --base master --head update-dependency-versions --title "Update dependency versions" --body "This pull request updates the dependency versions in files."
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -11,3 +11,4 @@ Andrew Mettlach (dmmettlach@gmail.com)
Evan Klitzke (evan@eklitzke.org) Evan Klitzke (evan@eklitzke.org)
Albert Schwarzkopf (dev-maddy@quitesimple.org) Albert Schwarzkopf (dev-maddy@quitesimple.org)
Ivans Saponenko (ivans.saponenko+maddy@gmail.com) Ivans Saponenko (ivans.saponenko+maddy@gmail.com)
Lucian Smith (lpsmith@uw.edu)

View File

@@ -14,7 +14,27 @@ maddy uses [semver versioning](https://semver.org/).
## Upcoming ## Upcoming
* ? * ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) Updated google test to v1.17.0.
* ...
## version 1.5.0 2025-04-21
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Correctly parse links with title text, i.e. `[link](http://example.com "example")`.
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Do not create invalid URLs from links with spaces, i.e. `[link](/ABC/some file)`.
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Do not create invalid HTML from links with quotes, i.e. `[link](/ABC/some"file)`.
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) benchmarks.
## version 1.4.0 2025-03-28
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) Updated google test to v1.16.0.
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) clang-format
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) automatic update dependencies ci
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) `(This is a [link](/ABC/some file) (the URL will include this).)` should not put the later parenthesis into the link url.
* ![**REMOVED**](https://img.shields.io/badge/-REMOVED-%23900) config flags `isEmphasizedParserEnabled` and `isHTMLWrappedInParagraph`. Use `config->enabledParsers &= ~maddy::types::EMPHASIZED_PARSER;` and `config->enabledParsers |= maddy::types::HTML_PARSER;` to gain the same behavior as if the previous config flags were set to `false`.
## version 1.3.0 2023-08-26
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Headlines can have inline parsing now. It is on by default, but can be disabled by config.
## version 1.2.1 2023-08-06 ## version 1.2.1 2023-08-06

View File

@@ -19,6 +19,7 @@ if(${MADDY_BUILD_WITH_TESTS})
enable_testing() enable_testing()
endif() endif()
option(MADDY_BUILD_WITH_BENCH "enable benchmarks" OFF)
option(MADDY_CREATE_PACKAGE "create a package for a version release" OFF) option(MADDY_CREATE_PACKAGE "create a package for a version release" OFF)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -49,10 +50,14 @@ if(${MADDY_BUILD_WITH_TESTS})
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()
if(${MADDY_BUILD_WITH_BENCH})
add_subdirectory(bench)
endif()
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
if(${MADDY_CREATE_PACKAGE}) if(${MADDY_CREATE_PACKAGE})
set(MADDY_PACKAGE_FILES include/ CMakeLists.txt LICENSE) set(MADDY_PACKAGE_FILES include/ CMakeLists.txt LICENSE AUTHORS)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-src.zip add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-src.zip
COMMAND ${CMAKE_COMMAND} -E tar c ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-src.zip --format=zip -- ${MADDY_PACKAGE_FILES} COMMAND ${CMAKE_COMMAND} -E tar c ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-src.zip --format=zip -- ${MADDY_PACKAGE_FILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}

View File

@@ -10,17 +10,10 @@ improve the code? Then [create a GitHub issue](https://github.com/progsource/mad
## Creating Pull-Requests ## Creating Pull-Requests
* Use a branch other than master. * Use a branch other than master.
* Add yourself to the `AUTHORS` file. * Feel free to add yourself to the `AUTHORS` file. (optional)
* Try to stick with the code style the files are having right now. * Use clang-format to format the code.
* Write in your commit messages what/why you did something. Often times a one-liner might be enough, but if you want to write more, make an empty line in between like: * Write in your commit messages what/why you did something. Often times a one-liner might be enough.
```
Short description
More and longer text for the commit message with some more information.
That can go over multiple lines.
```
Do not include Github issue ticket numbers inside commit messages.
* Explain for what your PR is for - like providing a use-case or something similar. * Explain for what your PR is for - like providing a use-case or something similar.
* Update documentation of the Markdown syntax if anything changed there. (`docs/definitions.md`) * Update documentation of the Markdown syntax if anything changed there. (`docs/definitions.md`)
* Add a changelog entry at "Upcoming" inside of `CHANGELOG.md` * Add a changelog entry at "Upcoming" inside of `CHANGELOG.md`
* Make sure, that the tests are successful. * Make sure that the tests are successful and if you wrote a bugfix, to have a test that highlights the issue.

View File

@@ -1,4 +1,4 @@
Copyright 2017, 2018, 2019, 2020, 2023 M. Petra Baranski Copyright M. Petra Baranski (for contributors see AUTHORS file)
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in

View File

@@ -1,7 +1,7 @@
# maddy # maddy
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Version: 1.2.1](https://img.shields.io/badge/Version-1.2.1-brightgreen.svg)](https://semver.org/) [![Version: 1.5.0](https://img.shields.io/badge/Version-1.5.0-brightgreen.svg)](https://semver.org/)
maddy is a C++ Markdown to HTML **header-only** parser library. maddy is a C++ Markdown to HTML **header-only** parser library.
@@ -70,10 +70,8 @@ std::stringstream markdownInput("");
// config is optional // config is optional
std::shared_ptr<maddy::ParserConfig> config = std::make_shared<maddy::ParserConfig>(); std::shared_ptr<maddy::ParserConfig> config = std::make_shared<maddy::ParserConfig>();
// config->isEmphasizedParserEnabled = false; // default true - this flag is deprecated config->enabledParsers &= ~maddy::types::EMPHASIZED_PARSER; // disable emphasized parser
// config->isHTMLWrappedInParagraph = false; // default true - this flag is deprecated config->enabledParsers |= maddy::types::HTML_PARSER; // do not wrap HTML in paragraph
config->enabledParsers &= ~maddy::types::EMPHASIZED_PARSER; // equivalent to !isEmphasizedParserEnabled
config->enabledParsers |= maddy::types::HTML_PARSER; // equivalent to !isHTMLWrappedInParagraph
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>(config); std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>(config);
std::string htmlOutput = parser->Parse(markdownInput); std::string htmlOutput = parser->Parse(markdownInput);
@@ -100,6 +98,21 @@ make
make test # or run the executable in ../build/MaddyTests make test # or run the executable in ../build/MaddyTests
``` ```
## How to run the benchmarks
To get proper test results, the benchmarks should always be compiled as
release build.
```shell
git clone https://github.com/progsource/maddy.git
cd maddy
mkdir tmp
cd tmp
cmake -DMADDY_BUILD_WITH_BENCH=ON -DCMAKE_BUILD_TYPE=Release ..
make BUILD_TYPE=Release
../build/maddy_benchmark
```
## How to contribute ## How to contribute
There are different possibilities: There are different possibilities:

54
bench/CMakeLists.txt Normal file
View File

@@ -0,0 +1,54 @@
# This project is licensed under the MIT license. For more information see the
# LICENSE file.
if (UNIX AND NOT APPLE)
execute_process(COMMAND ${CMAKE_CXX_COMPILER}
-fuse-ld=gold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE ld_version)
if ("${ld_version}" MATCHES "GNU gold")
message(STATUS "Found Gold linker, use faster linker")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold ")
endif()
endif()
# ------------------------------------------------------------------------------
include(FetchContent)
FetchContent_Declare(
nanobench
GIT_REPOSITORY https://github.com/martinus/nanobench.git
GIT_TAG v4.3.11
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(nanobench)
# ------------------------------------------------------------------------------
file(GLOB_RECURSE MADDY_BENCHMARK_FILES
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
# ------------------------------------------------------------------------------
add_compile_definitions(CURRENT_FILE_PATH="${CMAKE_CURRENT_SOURCE_DIR}")
# ------------------------------------------------------------------------------
add_executable(
maddy_benchmark
${MADDY_BENCHMARK_FILES}
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
target_include_directories(maddy_benchmark PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(maddy_benchmark maddy nanobench::nanobench)
set_target_properties(maddy_benchmark PROPERTIES
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -O2 -Wall -Wno-ignored-qualifiers -Wpedantic -Wextra -Wno-deprecated -fno-exceptions -fno-rtti"
)

14
bench/README.md Normal file
View File

@@ -0,0 +1,14 @@
# maddy benchmarks
## How to run
The benchmarks have to be run in release mode to give proper results.
```shell
# in main folder
mkdir tmp
cd tmp
cmake -DMADDY_BUILD_WITH_BENCH=ON -DCMAKE_BUILD_TYPE=Release ..
make BUILD_TYPE=Release
../build/maddy_benchmark
```

416
bench/benchmark_test.md Normal file
View File

@@ -0,0 +1,416 @@
# Benchmark test file
This file is for the benchmark testing.
---
This specification defines which markdown syntax can be parsed by maddy.
There is no HTML allowed in the markdown syntax - or said otherwise - it might
destroy the output, if there was HTML in your markdown.
The Parser expects you to use spaces and not tabs for indentation in the
markdown.
If a line starts with `<` and `config->enabledParsers |= maddy::types::HTML_PARSER;`
is set, it expects that the upcoming line is HTML and therefor will not be
surrounded by a paragraph.
## Headlines
```
# h1 heading
## h2 heading
### h3 heading
#### h4 heading
##### h5 heading
###### h6 heading
```
results in:
```html
<h1>h1 heading</h1>
<h2>h2 heading</h2>
<h3>h3 heading</h3>
<h4>h4 heading</h4>
<h5>h5 heading</h5>
<h6>h6 heading</h6>
```
## Links
```
[Text of the link](http://example.com)
```
results in
```html
<a href="http://example.com">Text of the link</a>
```
```
[Text of the link](http://example.com "title text")
```
results in
```html
<a href="http://example.com" title="title text">Text of the link</a>
```
## Lists
### unordered
Characters "*", "+" or "-" to make an unordered "bullet" list are equivalent.
```
- unordered
* list
+ items
```
results in
```html
<ul>
<li>unordered</li>
<li>list</li>
<li>items</li>
</ul>
```
```
* unordered
* list
* items
* in
+ an
- hierarchy
```
results in
```html
<ul>
<li>unordered
<ul>
<li>list</li>
<li>items
<ul>
<li>in</li>
<li>an</li>
</ul>
</li>
<li>hierarchy</li>
</ul>
</li>
</ul>
```
### ordered
```
1. ordered
2. list
3. items
```
results in
```html
<ol>
<li>ordered</li>
<li>list</li>
<li>items</li>
</ol>
```
```
1. ordered
* list
* items
```
results in
```html
<ol>
<li>ordered</li>
<li>list</li>
<li>items</li>
</ol>
```
```
1. ordered
* list
1. items
* in
1. an
* hierarchy
```
results in
```html
<ol>
<li>ordered</li>
<li>list
<ol>
<li>items</li>
<li>in
<ol>
<li>an</li>
</ol>
</li>
<li>hierarchy</li>
</ol>
</li>
</ol>
```
### combination
```
* combination
* of
1. unordered and
* ordered
* list
```
results in
```html
<ul>
<li>combination</li>
<li>of
<ol>
<li>unordered and</li>
<li>ordered</li>
</ol>
</li>
<li>list</li>
</ul>
```
### checklist
```
- [ ] some item
- [ ] another item
- [x] some checked item
```
results in
```html
<ul class="checklist">
<li><label><input type="checkbox"/>some item
<ul class="checklist">
<li><label><input type="checkbox"/><span>another item</label></li>
</ul>
</label></li>
<li><label><input type="checkbox" checked="checked"/>some checked item</label></li>
</ul>
```
might not work in combination with other lists
## Code Blocks
```
some code
```
results in
```html
<pre><code>
some code
</code></pre>
```
```cpp
int a = 42;
```
results in
```html
<pre class="cpp"><code>
int a = 42;
</code></pre>
```
## Inline code
some text `some inline code` some other text
results in
```html
some text <code>some inline code</code> some other text
```
## quotes
```
> Some quote
```
results in
```html
<blockqoute>
<p>Some quote</p>
</blockquote>
```
## bold
```
**bold text**
__bold text__
```
results in
```html
<strong>bold text</strong>
<strong>bold text</strong>
```
## italic
```
*italic text*
```
results in
```html
<i>italic text</i>
```
## emphasized
This can be disabled by setting `config->enabledParsers &= ~maddy::types::EMPHASIZED_PARSER;`.
```
_emphasized text_
```
results in
```html
<em>emphasized text</em>
```
## strikethrough
```
~~striked through text~~
```
results in
```html
<s>striked through text</s>
```
## horizontal line
```
---
```
results in
```html
<hr/>
```
## break line
```
New\r\nLine
```
results in
```html
New<br>
Line
```
## Images
```
![Image alt text](http://example.com/example.png)
```
results in
```html
<img src="http://example.com/example.png" alt="Image alt text"/>
```
## Tables
```
|table>
Left header | middle header | last header
- | - | -
cell 1 | cell 2 | cell 3
cell 4 | cell 5 | cell 6
- | - | -
foot a | foot b | foot c
|<table
```
becomes
```html
<table>
<thead>
<tr>
<th>Left header</th>
<th>middle header</th>
<th>last header</th>
</tr>
</thead>
<tbody>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
</tr>
<tr>
<td>cell 4</td>
<td>cell 5</td>
<td>cell 6</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>foot a</td>
<td>foot b</td>
<td>foot c</td>
</tr>
</tfoot>
</table>
```
table header and footer are optional
## LaTeX(MathJax) block support
To turn on the LaTeX support - which basically is only a
[MathJax](https://www.mathjax.org/) support and makes sure, that formulas aren't
internally checked for other parsers - it has to be enabled in config:
```cpp
std::shared_ptr<maddy::ParserConfig> config = std::make_shared<maddy::ParserConfig>();
config->enabledParsers |= maddy::types::LATEX_BLOCK_PARSER;
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>(config);
std::string htmlOutput = parser->Parse(markdownInput);
```
After this you can do the following in Markdown:
```
$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$
```
Which results in
```html
$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$\n
```

64
bench/main.cpp Normal file
View File

@@ -0,0 +1,64 @@
/*
* This project is licensed under the MIT license. For more information see the
* LICENSE file.
*/
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#define ANKERL_NANOBENCH_IMPLEMENT
#include <nanobench.h>
#include "maddy/parser.h"
int main()
{
static const std::string markdownFile =
std::string(CURRENT_FILE_PATH) + "/benchmark_test.md";
std::stringstream buffer;
{
std::ifstream file(markdownFile);
if (!file.good() || !file.is_open())
{
std::cout << "could not read file at " << markdownFile << std::endl;
return 1;
}
buffer << file.rdbuf();
file.close();
}
if (!buffer.good() || buffer.str().empty())
{
std::cout << "buffer is invalid" << std::endl;
return 2;
}
// maddy 1.*
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>();
// This is the place in the future to compare maddy with other libraries.
// For now it can be used to check if changes in maddy code result in better
// performance.
ankerl::nanobench::Bench()
.title("maddy test")
.warmup(100)
.relative(true)
.run(
"maddy 1.x",
[&]()
{
buffer.clear(); // clear any error flags
buffer.seekg(0, buffer.beg);
ankerl::nanobench::doNotOptimizeAway(parser->Parse(buffer));
}
);
return 0;
}

View File

@@ -7,9 +7,9 @@ destroy the output, if there was HTML in your markdown.
The Parser expects you to use spaces and not tabs for indentation in the The Parser expects you to use spaces and not tabs for indentation in the
markdown. markdown.
If a line starts with `<` and `config->isHTMLWrappedInParagraph` is false, it If a line starts with `<` and `config->enabledParsers |= maddy::types::HTML_PARSER;`
expects that the upcoming line is HTML and therefor will not be surrounded by a is set, it expects that the upcoming line is HTML and therefor will not be
paragraph. surrounded by a paragraph.
## Headlines ## Headlines
@@ -41,6 +41,14 @@ results in
<a href="http://example.com">Text of the link</a> <a href="http://example.com">Text of the link</a>
``` ```
```
[Text of the link](http://example.com "title text")
```
results in
```html
<a href="http://example.com" title="title text">Text of the link</a>
```
## Lists ## Lists
### unordered ### unordered
@@ -279,7 +287,7 @@ results in
## emphasized ## emphasized
This can be disabled by setting `config->isEmphasizedParserEnabled = false`. This can be disabled by setting `config->enabledParsers &= ~maddy::types::EMPHASIZED_PARSER;`.
``` ```
_emphasized text_ _emphasized text_

View File

@@ -10,8 +10,8 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
// windows compatibility includes // windows compatibility includes
#include <cctype>
#include <algorithm> #include <algorithm>
#include <cctype>
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -36,11 +36,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
BlockParser( BlockParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: result("", std::ios_base::ate | std::ios_base::in | std::ios_base::out) : result("", std::ios_base::ate | std::ios_base::in | std::ios_base::out)
, childParser(nullptr) , childParser(nullptr)
@@ -64,8 +66,7 @@ public:
* @param {std::string&} line * @param {std::string&} line
* @return {void} * @return {void}
*/ */
virtual void virtual void AddLine(std::string& line)
AddLine(std::string& line)
{ {
this->parseBlock(line); this->parseBlock(line);
@@ -113,11 +114,7 @@ public:
* @method * @method
* @return {std::stringstream} * @return {std::stringstream}
*/ */
std::stringstream& std::stringstream& GetResult() { return this->result; }
GetResult()
{
return this->result;
}
/** /**
* Clear * Clear
@@ -129,11 +126,7 @@ public:
* @method * @method
* @return {void} * @return {void}
*/ */
void void Clear() { this->result.str(""); }
Clear()
{
this->result.str("");
}
protected: protected:
std::stringstream result; std::stringstream result;
@@ -143,8 +136,7 @@ protected:
virtual bool isLineParserAllowed() const = 0; virtual bool isLineParserAllowed() const = 0;
virtual void parseBlock(std::string& line) = 0; virtual void parseBlock(std::string& line) = 0;
void void parseLine(std::string& line)
parseLine(std::string& line)
{ {
if (parseLineCallback) if (parseLineCallback)
{ {
@@ -152,38 +144,34 @@ protected:
} }
} }
uint32_t uint32_t getIndentationWidth(const std::string& line) const
getIndentationWidth(const std::string& line) const
{ {
bool hasMetNonSpace = false; bool hasMetNonSpace = false;
uint32_t indentation = static_cast<uint32_t>( uint32_t indentation = static_cast<uint32_t>(std::count_if(
std::count_if( line.begin(),
line.begin(), line.end(),
line.end(), [&hasMetNonSpace](unsigned char c)
[&hasMetNonSpace](unsigned char c) {
if (hasMetNonSpace)
{ {
if (hasMetNonSpace)
{
return false;
}
if (std::isspace(c))
{
return true;
}
hasMetNonSpace = true;
return false; return false;
} }
)
); if (std::isspace(c))
{
return true;
}
hasMetNonSpace = true;
return false;
}
));
return indentation; return indentation;
} }
std::shared_ptr<BlockParser> std::shared_ptr<BlockParser> getBlockParserForLine(const std::string& line)
getBlockParserForLine(const std::string& line)
{ {
if (getBlockParserForLineCallback) if (getBlockParserForLineCallback)
{ {
@@ -195,7 +183,8 @@ protected:
private: private:
std::function<void(std::string&)> parseLineCallback; std::function<void(std::string&)> parseLineCallback;
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback; std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback;
}; // class BlockParser }; // class BlockParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -36,8 +36,7 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::regex re(R"((\r\n|\r))"); static std::regex re(R"((\r\n|\r))");
static std::string replacement = "<br>"; static std::string replacement = "<br>";

View File

@@ -31,11 +31,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
ChecklistParser( ChecklistParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -51,8 +53,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re(R"(^- \[[x| ]\] .*)"); static std::regex re(R"(^- \[[x| ]\] .*)");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -64,27 +65,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return true; }
isInlineBlockAllowed() const override
{
return true;
}
bool bool isLineParserAllowed() const override { return true; }
isLineParserAllowed() const override
{
return true;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
bool isStartOfNewListItem = IsStartingLine(line); bool isStartOfNewListItem = IsStartingLine(line);
uint32_t indentation = getIndentationWidth(line); uint32_t indentation = getIndentationWidth(line);
@@ -97,7 +85,8 @@ protected:
line = std::regex_replace(line, emptyBoxRegex, emptyBoxReplacement); line = std::regex_replace(line, emptyBoxRegex, emptyBoxReplacement);
static std::regex boxRegex(R"(^\[x\])"); static std::regex boxRegex(R"(^\[x\])");
static std::string boxReplacement = "<input type=\"checkbox\" checked=\"checked\"/>"; static std::string boxReplacement =
"<input type=\"checkbox\" checked=\"checked\"/>";
line = std::regex_replace(line, boxRegex, boxReplacement); line = std::regex_replace(line, boxRegex, boxReplacement);
if (!this->isStarted) if (!this->isStarted)
@@ -113,11 +102,9 @@ protected:
return; return;
} }
if ( if (line.empty() ||
line.empty() || line.find("</label></li><li><label>") != std::string::npos ||
line.find("</label></li><li><label>") != std::string::npos || line.find("</label></li></ul>") != std::string::npos)
line.find("</label></li></ul>") != std::string::npos
)
{ {
line = "</label></li></ul>" + line; line = "</label></li></ul>" + line;
this->isFinished = true; this->isFinished = true;

View File

@@ -7,8 +7,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <functional> #include <functional>
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/blockparser.h" #include "maddy/blockparser.h"
@@ -47,11 +47,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
CodeBlockParser( CodeBlockParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -71,8 +73,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re("^(?:`){3}(.*)$"); static std::regex re("^(?:`){3}(.*)$");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -84,27 +85,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return false; }
isInlineBlockAllowed() const override
{
return false;
}
bool bool isLineParserAllowed() const override { return false; }
isLineParserAllowed() const override
{
return false;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
if (line == "```") if (line == "```")
{ {

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -38,10 +38,11 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::regex re(R"((?!.*`.*|.*<code>.*)_(?!.*`.*|.*<\/code>.*)([^_]*)_(?!.*`.*|.*<\/code>.*))"); static std::regex re(
R"((?!.*`.*|.*<code>.*)_(?!.*`.*|.*<\/code>.*)([^_]*)_(?!.*`.*|.*<\/code>.*))"
);
static std::string replacement = "<em>$1</em>"; static std::string replacement = "<em>$1</em>";
line = std::regex_replace(line, re, replacement); line = std::regex_replace(line, re, replacement);

View File

@@ -7,8 +7,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <functional> #include <functional>
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/blockparser.h" #include "maddy/blockparser.h"
@@ -53,13 +53,17 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
HeadlineParser( HeadlineParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback,
bool isInlineParserAllowed = true
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isInlineParserAllowed(isInlineParserAllowed)
{} {}
/** /**
@@ -71,8 +75,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re("^(?:#){1,6} (.*)"); static std::regex re("^(?:#){1,6} (.*)");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -87,43 +90,33 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return true; }
IsFinished() const override
{
return true;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return false; }
isInlineBlockAllowed() const override
bool isLineParserAllowed() const override
{ {
return false; return this->isInlineParserAllowed;
} }
bool void parseBlock(std::string& line) override
isLineParserAllowed() const override
{
return false;
}
void
parseBlock(std::string& line) override
{ {
static std::vector<std::regex> hlRegex = { static std::vector<std::regex> hlRegex = {
std::regex("^# (.*)") std::regex("^# (.*)"),
, std::regex("^(?:#){2} (.*)") std::regex("^(?:#){2} (.*)"),
, std::regex("^(?:#){3} (.*)") std::regex("^(?:#){3} (.*)"),
, std::regex("^(?:#){4} (.*)") std::regex("^(?:#){4} (.*)"),
, std::regex("^(?:#){5} (.*)") std::regex("^(?:#){5} (.*)"),
, std::regex("^(?:#){6} (.*)") std::regex("^(?:#){6} (.*)")
}; };
static std::vector<std::string> hlReplacement = { static std::vector<std::string> hlReplacement = {
"<h1>$1</h1>" "<h1>$1</h1>",
, "<h2>$1</h2>" "<h2>$1</h2>",
, "<h3>$1</h3>" "<h3>$1</h3>",
, "<h4>$1</h4>" "<h4>$1</h4>",
, "<h5>$1</h5>" "<h5>$1</h5>",
, "<h6>$1</h6>" "<h6>$1</h6>"
}; };
for (uint8_t i = 0; i < 6; ++i) for (uint8_t i = 0; i < 6; ++i)
@@ -131,6 +124,9 @@ protected:
line = std::regex_replace(line, hlRegex[i], hlReplacement[i]); line = std::regex_replace(line, hlRegex[i], hlReplacement[i]);
} }
} }
private:
bool isInlineParserAllowed;
}; // class HeadlineParser }; // class HeadlineParser
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -7,8 +7,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <functional> #include <functional>
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/blockparser.h" #include "maddy/blockparser.h"
@@ -35,11 +35,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
HorizontalLineParser( HorizontalLineParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, lineRegex("^---$") , lineRegex("^---$")
@@ -54,8 +56,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re("^---$"); static std::regex re("^---$");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -70,27 +71,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return true; }
IsFinished() const override
{
return true;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return false; }
isInlineBlockAllowed() const override
{
return false;
}
bool bool isLineParserAllowed() const override { return false; }
isLineParserAllowed() const override
{
return false;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
static std::string replacement = "<hr/>"; static std::string replacement = "<hr/>";

View File

@@ -30,11 +30,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
HtmlParser( HtmlParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -52,11 +54,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line) { return line[0] == '<'; }
IsStartingLine(const std::string& line)
{
return line[0] == '<';
}
/** /**
* IsFinished * IsFinished
@@ -66,27 +64,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return false; }
isInlineBlockAllowed() const override
{
return false;
}
bool bool isLineParserAllowed() const override { return false; }
isLineParserAllowed() const override
{
return false;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
if (!this->isStarted) if (!this->isStarted)
{ {

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -38,8 +38,7 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::regex re(R"(\!\[([^\]]*)\]\(([^\]]*)\))"); static std::regex re(R"(\!\[([^\]]*)\]\(([^\]]*)\))");
static std::string replacement = "<img src=\"$2\" alt=\"$1\"/>"; static std::string replacement = "<img src=\"$2\" alt=\"$1\"/>";

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -36,8 +36,7 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::regex re("`([^`]*)`"); static std::regex re("`([^`]*)`");
static std::string replacement = "<code>$1</code>"; static std::string replacement = "<code>$1</code>";

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -36,10 +36,11 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::regex re(R"((?!.*`.*|.*<code>.*)\*(?!.*`.*|.*<\/code>.*)([^\*]*)\*(?!.*`.*|.*<\/code>.*))"); static std::regex re(
R"((?!.*`.*|.*<code>.*)\*(?!.*`.*|.*<\/code>.*)([^\*]*)\*(?!.*`.*|.*<\/code>.*))"
);
static std::string replacement = "<i>$1</i>"; static std::string replacement = "<i>$1</i>";
line = std::regex_replace(line, re, replacement); line = std::regex_replace(line, re, replacement);
} }

View File

@@ -7,8 +7,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <functional> #include <functional>
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/blockparser.h" #include "maddy/blockparser.h"
@@ -51,11 +51,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
LatexBlockParser( LatexBlockParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -75,8 +77,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re(R"(^(?:\$){2}(.*)$)"); static std::regex re(R"(^(?:\$){2}(.*)$)");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -88,27 +89,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return false; }
isInlineBlockAllowed() const override
{
return false;
}
bool bool isLineParserAllowed() const override { return false; }
isLineParserAllowed() const override
{
return false;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
if (!this->isStarted && line.substr(0, 2) == "$$") if (!this->isStarted && line.substr(0, 2) == "$$")
{ {
@@ -116,7 +104,8 @@ protected:
this->isFinished = false; this->isFinished = false;
} }
if (this->isStarted && !this->isFinished && line.size() > 1 && line.substr(line.size() - 2, 2) == "$$") if (this->isStarted && !this->isFinished && line.size() > 1 &&
line.substr(line.size() - 2, 2) == "$$")
{ {
this->isFinished = true; this->isFinished = true;
this->isStarted = false; this->isStarted = false;

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -38,13 +38,19 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::regex re(R"(\[([^\]]*)\]\(([^\]]*)\))"); // Match [name](http:://link "title text")
static std::string replacement = "<a href=\"$2\">$1</a>"; // NOTE: the 'no quote' bit at the beginning (^") is a hack for now:
// there should eventually be something that replaces it with '%22'.
static std::regex re(R"(\[([^\]]*)\]\( *([^)^ ^"]*) *\"([^\"]*)\" *\))");
static std::string replacement = "<a href=\"$2\" title=\"$3\">$1</a>";
line = std::regex_replace(line, re, replacement); line = std::regex_replace(line, re, replacement);
// Match [name](http:://link)
static std::regex re2(R"(\[([^\]]*)\]\( *([^)^ ^"]*) *\))");
static std::string replacement2 = "<a href=\"$2\">$1</a>";
line = std::regex_replace(line, re2, replacement2);
} }
}; // class LinkParser }; // class LinkParser

View File

@@ -31,11 +31,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
OrderedListParser( OrderedListParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -51,8 +53,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re("^1\\. .*"); static std::regex re("^1\\. .*");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -64,27 +65,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return true; }
isInlineBlockAllowed() const override
{
return true;
}
bool bool isLineParserAllowed() const override { return true; }
isLineParserAllowed() const override
{
return true;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
bool isStartOfNewListItem = this->isStartOfNewListItem(line); bool isStartOfNewListItem = this->isStartOfNewListItem(line);
uint32_t indentation = getIndentationWidth(line); uint32_t indentation = getIndentationWidth(line);
@@ -107,12 +95,9 @@ protected:
return; return;
} }
if ( if (line.empty() || line.find("</li><li>") != std::string::npos ||
line.empty() || line.find("</li></ol>") != std::string::npos ||
line.find("</li><li>") != std::string::npos || line.find("</li></ul>") != std::string::npos)
line.find("</li></ol>") != std::string::npos ||
line.find("</li></ul>") != std::string::npos
)
{ {
line = "</li></ol>" + line; line = "</li></ol>" + line;
this->isFinished = true; this->isFinished = true;
@@ -129,8 +114,7 @@ private:
bool isStarted; bool isStarted;
bool isFinished; bool isFinished;
bool bool isStartOfNewListItem(const std::string& line) const
isStartOfNewListItem(const std::string& line) const
{ {
static std::regex re(R"(^(?:[1-9]+[0-9]*\. |\* ).*)"); static std::regex re(R"(^(?:[1-9]+[0-9]*\. |\* ).*)");
return std::regex_match(line, re); return std::regex_match(line, re);

View File

@@ -30,11 +30,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
ParagraphParser( ParagraphParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback, std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback,
bool isEnabled bool isEnabled
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
@@ -54,11 +56,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line) { return !line.empty(); }
IsStartingLine(const std::string& line)
{
return !line.empty();
}
/** /**
* IsFinished * IsFinished
@@ -68,27 +66,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return false; }
isInlineBlockAllowed() const override
{
return false;
}
bool bool isLineParserAllowed() const override { return true; }
isLineParserAllowed() const override
{
return true;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
if (this->isEnabled && !this->isStarted) if (this->isEnabled && !this->isStarted)
{ {

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <memory>
#include <functional> #include <functional>
#include <memory>
#include <string> #include <string>
#include "maddy/parserconfig.h" #include "maddy/parserconfig.h"
@@ -56,8 +56,12 @@ public:
* *
* Check https://github.com/progsource/maddy/blob/master/CHANGELOG.md * Check https://github.com/progsource/maddy/blob/master/CHANGELOG.md
* for the changelog. * for the changelog.
*/ */
static const std::string& version() { static const std::string v = "1.2.1"; return v; } static const std::string& version()
{
static const std::string v = "1.5.0";
return v;
}
/** /**
* ctor * ctor
@@ -66,80 +70,52 @@ public:
* *
* @method * @method
*/ */
Parser(std::shared_ptr<ParserConfig> config = nullptr) Parser(std::shared_ptr<ParserConfig> config = nullptr) : config(config)
: config(config)
{ {
// deprecated backward compatibility if (!this->config ||
// will be removed in 1.4.0 latest including the booleans (this->config->enabledParsers & maddy::types::BREAKLINE_PARSER) != 0)
if (this->config && !this->config->isEmphasizedParserEnabled)
{
this->config->enabledParsers &= ~maddy::types::EMPHASIZED_PARSER;
}
if (this->config && !this->config->isHTMLWrappedInParagraph)
{
this->config->enabledParsers |= maddy::types::HTML_PARSER;
}
if (
!this->config ||
(this->config->enabledParsers & maddy::types::BREAKLINE_PARSER) != 0
)
{ {
this->breakLineParser = std::make_shared<BreakLineParser>(); this->breakLineParser = std::make_shared<BreakLineParser>();
} }
if ( if (!this->config ||
!this->config || (this->config->enabledParsers & maddy::types::EMPHASIZED_PARSER) != 0)
(this->config->enabledParsers & maddy::types::EMPHASIZED_PARSER) != 0
)
{ {
this->emphasizedParser = std::make_shared<EmphasizedParser>(); this->emphasizedParser = std::make_shared<EmphasizedParser>();
} }
if ( if (!this->config ||
!this->config || (this->config->enabledParsers & maddy::types::IMAGE_PARSER) != 0)
(this->config->enabledParsers & maddy::types::IMAGE_PARSER) != 0
)
{ {
this->imageParser = std::make_shared<ImageParser>(); this->imageParser = std::make_shared<ImageParser>();
} }
if ( if (!this->config ||
!this->config || (this->config->enabledParsers & maddy::types::INLINE_CODE_PARSER) != 0)
(this->config->enabledParsers & maddy::types::INLINE_CODE_PARSER) != 0
)
{ {
this->inlineCodeParser = std::make_shared<InlineCodeParser>(); this->inlineCodeParser = std::make_shared<InlineCodeParser>();
} }
if ( if (!this->config ||
!this->config || (this->config->enabledParsers & maddy::types::ITALIC_PARSER) != 0)
(this->config->enabledParsers & maddy::types::ITALIC_PARSER) != 0
)
{ {
this->italicParser = std::make_shared<ItalicParser>(); this->italicParser = std::make_shared<ItalicParser>();
} }
if ( if (!this->config ||
!this->config || (this->config->enabledParsers & maddy::types::LINK_PARSER) != 0)
(this->config->enabledParsers & maddy::types::LINK_PARSER) != 0
)
{ {
this->linkParser = std::make_shared<LinkParser>(); this->linkParser = std::make_shared<LinkParser>();
} }
if ( if (!this->config || (this->config->enabledParsers &
!this->config || maddy::types::STRIKETHROUGH_PARSER) != 0)
(this->config->enabledParsers & maddy::types::STRIKETHROUGH_PARSER) != 0
)
{ {
this->strikeThroughParser = std::make_shared<StrikeThroughParser>(); this->strikeThroughParser = std::make_shared<StrikeThroughParser>();
} }
if ( if (!this->config ||
!this->config || (this->config->enabledParsers & maddy::types::STRONG_PARSER) != 0)
(this->config->enabledParsers & maddy::types::STRONG_PARSER) != 0
)
{ {
this->strongParser = std::make_shared<StrongParser>(); this->strongParser = std::make_shared<StrongParser>();
} }
@@ -152,8 +128,7 @@ public:
* @param {const std::istream&} markdown * @param {const std::istream&} markdown
* @return {std::string} HTML * @return {std::string} HTML
*/ */
std::string std::string Parse(std::istream& markdown) const
Parse(std::istream& markdown) const
{ {
std::string result = ""; std::string result = "";
std::shared_ptr<BlockParser> currentBlockParser = nullptr; std::shared_ptr<BlockParser> currentBlockParser = nullptr;
@@ -204,8 +179,7 @@ private:
std::shared_ptr<StrongParser> strongParser; std::shared_ptr<StrongParser> strongParser;
// block parser have to run before // block parser have to run before
void void runLineParser(std::string& line) const
runLineParser(std::string& line) const
{ {
// Attention! ImageParser has to be before LinkParser // Attention! ImageParser has to be before LinkParser
if (this->imageParser) if (this->imageParser)
@@ -250,155 +224,114 @@ private:
} }
} }
std::shared_ptr<BlockParser> std::shared_ptr<BlockParser> getBlockParserForLine(const std::string& line
getBlockParserForLine(const std::string& line) const ) const
{ {
std::shared_ptr<BlockParser> parser; std::shared_ptr<BlockParser> parser;
if ( if ((!this->config || (this->config->enabledParsers &
( maddy::types::CODE_BLOCK_PARSER) != 0) &&
!this->config || maddy::CodeBlockParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::CODE_BLOCK_PARSER) != 0
) &&
maddy::CodeBlockParser::IsStartingLine(line)
)
{ {
parser = std::make_shared<maddy::CodeBlockParser>( parser = std::make_shared<maddy::CodeBlockParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
else if ( else if (this->config &&
this->config && (this->config->enabledParsers & maddy::types::LATEX_BLOCK_PARSER
(this->config->enabledParsers & maddy::types::LATEX_BLOCK_PARSER) != 0 && ) != 0 &&
maddy::LatexBlockParser::IsStartingLine(line) maddy::LatexBlockParser::IsStartingLine(line))
)
{ {
parser = std::make_shared<LatexBlockParser>( parser = std::make_shared<LatexBlockParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::HEADLINE_PARSER) != 0) &&
!this->config || maddy::HeadlineParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::HEADLINE_PARSER) != 0
) &&
maddy::HeadlineParser::IsStartingLine(line)
)
{ {
parser = std::make_shared<maddy::HeadlineParser>( if (!this->config || this->config->isHeadlineInlineParsingEnabled)
nullptr, {
nullptr parser = std::make_shared<maddy::HeadlineParser>(
); [this](std::string& line) { this->runLineParser(line); },
nullptr,
true
);
}
else
{
parser =
std::make_shared<maddy::HeadlineParser>(nullptr, nullptr, false);
}
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::HORIZONTAL_LINE_PARSER) != 0) &&
!this->config || maddy::HorizontalLineParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::HORIZONTAL_LINE_PARSER) != 0
) &&
maddy::HorizontalLineParser::IsStartingLine(line)
)
{ {
parser = std::make_shared<maddy::HorizontalLineParser>( parser = std::make_shared<maddy::HorizontalLineParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::QUOTE_PARSER) != 0) &&
!this->config || maddy::QuoteParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::QUOTE_PARSER) != 0
) &&
maddy::QuoteParser::IsStartingLine(line)
)
{ {
parser = std::make_shared<maddy::QuoteParser>( parser = std::make_shared<maddy::QuoteParser>(
[this](std::string& line){ this->runLineParser(line); }, [this](std::string& line) { this->runLineParser(line); },
[this](const std::string& line){ return this->getBlockParserForLine(line); } [this](const std::string& line)
{ return this->getBlockParserForLine(line); }
); );
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::TABLE_PARSER) != 0) &&
!this->config || maddy::TableParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::TABLE_PARSER) != 0
) &&
maddy::TableParser::IsStartingLine(line)
)
{ {
parser = std::make_shared<maddy::TableParser>( parser = std::make_shared<maddy::TableParser>(
[this](std::string& line){ this->runLineParser(line); }, [this](std::string& line) { this->runLineParser(line); }, nullptr
nullptr
); );
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::CHECKLIST_PARSER) != 0) &&
!this->config || maddy::ChecklistParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::CHECKLIST_PARSER) != 0
) &&
maddy::ChecklistParser::IsStartingLine(line)
)
{ {
parser = this->createChecklistParser(); parser = this->createChecklistParser();
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::ORDERED_LIST_PARSER) != 0) &&
!this->config || maddy::OrderedListParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::ORDERED_LIST_PARSER) != 0
) &&
maddy::OrderedListParser::IsStartingLine(line)
)
{ {
parser = this->createOrderedListParser(); parser = this->createOrderedListParser();
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::UNORDERED_LIST_PARSER) != 0) &&
!this->config || maddy::UnorderedListParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::UNORDERED_LIST_PARSER) != 0
) &&
maddy::UnorderedListParser::IsStartingLine(line)
)
{ {
parser = this->createUnorderedListParser(); parser = this->createUnorderedListParser();
} }
else if ( else if (this->config &&
this->config && (this->config->enabledParsers & maddy::types::HTML_PARSER) != 0 &&
(this->config->enabledParsers & maddy::types::HTML_PARSER) != 0 && maddy::HtmlParser::IsStartingLine(line))
maddy::HtmlParser::IsStartingLine(line)
)
{ {
parser = std::make_shared<maddy::HtmlParser>(nullptr, nullptr); parser = std::make_shared<maddy::HtmlParser>(nullptr, nullptr);
} }
else if ( else if (maddy::ParagraphParser::IsStartingLine(line))
maddy::ParagraphParser::IsStartingLine(line)
)
{ {
parser = std::make_shared<maddy::ParagraphParser>( parser = std::make_shared<maddy::ParagraphParser>(
[this](std::string& line){ this->runLineParser(line); }, [this](std::string& line) { this->runLineParser(line); },
nullptr, nullptr,
(!this->config || (this->config->enabledParsers & maddy::types::PARAGRAPH_PARSER) != 0) (!this->config ||
(this->config->enabledParsers & maddy::types::PARAGRAPH_PARSER) != 0)
); );
} }
return parser; return parser;
} }
std::shared_ptr<BlockParser> std::shared_ptr<BlockParser> createChecklistParser() const
createChecklistParser() const
{ {
return std::make_shared<maddy::ChecklistParser>( return std::make_shared<maddy::ChecklistParser>(
[this](std::string& line){ this->runLineParser(line); }, [this](std::string& line) { this->runLineParser(line); },
[this](const std::string& line) [this](const std::string& line)
{ {
std::shared_ptr<BlockParser> parser; std::shared_ptr<BlockParser> parser;
if ( if ((!this->config || (this->config->enabledParsers &
( maddy::types::CHECKLIST_PARSER) != 0) &&
!this->config || maddy::ChecklistParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::CHECKLIST_PARSER) != 0
) &&
maddy::ChecklistParser::IsStartingLine(line)
)
{ {
parser = this->createChecklistParser(); parser = this->createChecklistParser();
} }
@@ -408,32 +341,24 @@ private:
); );
} }
std::shared_ptr<BlockParser> std::shared_ptr<BlockParser> createOrderedListParser() const
createOrderedListParser() const
{ {
return std::make_shared<maddy::OrderedListParser>( return std::make_shared<maddy::OrderedListParser>(
[this](std::string& line){ this->runLineParser(line); }, [this](std::string& line) { this->runLineParser(line); },
[this](const std::string& line) [this](const std::string& line)
{ {
std::shared_ptr<BlockParser> parser; std::shared_ptr<BlockParser> parser;
if ( if ((!this->config || (this->config->enabledParsers &
( maddy::types::ORDERED_LIST_PARSER) != 0) &&
!this->config || maddy::OrderedListParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::ORDERED_LIST_PARSER) != 0
) &&
maddy::OrderedListParser::IsStartingLine(line)
)
{ {
parser = this->createOrderedListParser(); parser = this->createOrderedListParser();
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::UNORDERED_LIST_PARSER) != 0
!this->config || ) &&
(this->config->enabledParsers & maddy::types::UNORDERED_LIST_PARSER) != 0 maddy::UnorderedListParser::IsStartingLine(line))
) &&
maddy::UnorderedListParser::IsStartingLine(line)
)
{ {
parser = this->createUnorderedListParser(); parser = this->createUnorderedListParser();
} }
@@ -443,32 +368,24 @@ private:
); );
} }
std::shared_ptr<BlockParser> std::shared_ptr<BlockParser> createUnorderedListParser() const
createUnorderedListParser() const
{ {
return std::make_shared<maddy::UnorderedListParser>( return std::make_shared<maddy::UnorderedListParser>(
[this](std::string& line){ this->runLineParser(line); }, [this](std::string& line) { this->runLineParser(line); },
[this](const std::string& line) [this](const std::string& line)
{ {
std::shared_ptr<BlockParser> parser; std::shared_ptr<BlockParser> parser;
if ( if ((!this->config || (this->config->enabledParsers &
( maddy::types::ORDERED_LIST_PARSER) != 0) &&
!this->config || maddy::OrderedListParser::IsStartingLine(line))
(this->config->enabledParsers & maddy::types::ORDERED_LIST_PARSER) != 0
) &&
maddy::OrderedListParser::IsStartingLine(line)
)
{ {
parser = this->createOrderedListParser(); parser = this->createOrderedListParser();
} }
else if ( else if ((!this->config || (this->config->enabledParsers &
( maddy::types::UNORDERED_LIST_PARSER) != 0
!this->config || ) &&
(this->config->enabledParsers & maddy::types::UNORDERED_LIST_PARSER) != 0 maddy::UnorderedListParser::IsStartingLine(line))
) &&
maddy::UnorderedListParser::IsStartingLine(line)
)
{ {
parser = this->createUnorderedListParser(); parser = this->createUnorderedListParser();
} }

View File

@@ -14,6 +14,7 @@ namespace maddy {
namespace types { namespace types {
// clang-format off
/** /**
* PARSER_TYPE * PARSER_TYPE
* *
@@ -46,6 +47,7 @@ enum PARSER_TYPE : uint32_t
DEFAULT = 0b0111111111110111111, DEFAULT = 0b0111111111110111111,
ALL = 0b1111111111111111111, ALL = 0b1111111111111111111,
}; };
// clang-format on
} // namespace types } // namespace types
@@ -57,24 +59,19 @@ enum PARSER_TYPE : uint32_t
struct ParserConfig struct ParserConfig
{ {
/** /**
* @deprecated will be removed in 1.4.0 latest * en-/disable headline inline-parsing
* *
* this flag = false == `enabledParsers &= ~maddy::types::EMPHASIZED_PARSER` * default: enabled
*/ */
bool isEmphasizedParserEnabled; bool isHeadlineInlineParsingEnabled;
/** /**
* @deprecated will be removed in 1.4.0 latest * enabled parsers bitfield
* */
* this flag = false == `enabledParsers |= maddy::types::HTML_PARSER`
*/
bool isHTMLWrappedInParagraph;
uint32_t enabledParsers; uint32_t enabledParsers;
ParserConfig() ParserConfig()
: isEmphasizedParserEnabled(true) : isHeadlineInlineParsingEnabled(true)
, isHTMLWrappedInParagraph(true)
, enabledParsers(maddy::types::DEFAULT) , enabledParsers(maddy::types::DEFAULT)
{} {}
}; // class ParserConfig }; // class ParserConfig

View File

@@ -31,11 +31,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
QuoteParser( QuoteParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -51,8 +53,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re(R"(^\>.*)"); static std::regex re(R"(^\>.*)");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -67,8 +68,7 @@ public:
* @param {std::string&} line * @param {std::string&} line
* @return {void} * @return {void}
*/ */
void void AddLine(std::string& line) override
AddLine(std::string& line) override
{ {
if (!this->isStarted) if (!this->isStarted)
{ {
@@ -122,27 +122,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return true; }
isInlineBlockAllowed() const override
{
return true;
}
bool bool isLineParserAllowed() const override { return true; }
isLineParserAllowed() const override
{
return true;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
static std::regex lineRegexWithSpace(R"(^\> )"); static std::regex lineRegexWithSpace(R"(^\> )");
line = std::regex_replace(line, lineRegexWithSpace, ""); line = std::regex_replace(line, lineRegexWithSpace, "");

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -36,10 +36,11 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::regex re(R"((?!.*`.*|.*<code>.*)\~\~(?!.*`.*|.*<\/code>.*)([^\~]*)\~\~(?!.*`.*|.*<\/code>.*))"); static std::regex re(
R"((?!.*`.*|.*<code>.*)\~\~(?!.*`.*|.*<\/code>.*)([^\~]*)\~\~(?!.*`.*|.*<\/code>.*))"
);
static std::string replacement = "<s>$1</s>"; static std::string replacement = "<s>$1</s>";
line = std::regex_replace(line, re, replacement); line = std::regex_replace(line, re, replacement);

View File

@@ -6,8 +6,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/lineparser.h" #include "maddy/lineparser.h"
@@ -38,13 +38,15 @@ public:
* @param {std::string&} line The line to interpret * @param {std::string&} line The line to interpret
* @return {void} * @return {void}
*/ */
void void Parse(std::string& line) override
Parse(std::string& line) override
{ {
static std::vector<std::regex> res static std::vector<std::regex> res{
{ std::regex{
std::regex{R"((?!.*`.*|.*<code>.*)\*\*(?!.*`.*|.*<\/code>.*)([^\*\*]*)\*\*(?!.*`.*|.*<\/code>.*))"}, R"((?!.*`.*|.*<code>.*)\*\*(?!.*`.*|.*<\/code>.*)([^\*\*]*)\*\*(?!.*`.*|.*<\/code>.*))"
std::regex{R"((?!.*`.*|.*<code>.*)__(?!.*`.*|.*<\/code>.*)([^__]*)__(?!.*`.*|.*<\/code>.*))"} },
std::regex{
R"((?!.*`.*|.*<code>.*)__(?!.*`.*|.*<\/code>.*)([^__]*)__(?!.*`.*|.*<\/code>.*))"
}
}; };
static std::string replacement = "<strong>$1</strong>"; static std::string replacement = "<strong>$1</strong>";
for (const auto& re : res) for (const auto& re : res)

View File

@@ -7,8 +7,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <functional> #include <functional>
#include <string>
#include <regex> #include <regex>
#include <string>
#include "maddy/blockparser.h" #include "maddy/blockparser.h"
@@ -33,11 +33,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
TableParser( TableParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -55,8 +57,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::string matchString("|table>"); static std::string matchString("|table>");
return line == matchString; return line == matchString;
@@ -71,8 +72,7 @@ public:
* @param {std::string&} line * @param {std::string&} line
* @return {void} * @return {void}
*/ */
void void AddLine(std::string& line) override
AddLine(std::string& line) override
{ {
if (!this->isStarted && line == "|table>") if (!this->isStarted && line == "|table>")
{ {
@@ -124,27 +124,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return false; }
isInlineBlockAllowed() const override
{
return false;
}
bool bool isLineParserAllowed() const override { return true; }
isLineParserAllowed() const override
{
return true;
}
void void parseBlock(std::string&) override
parseBlock(std::string&) override
{ {
result << "<table>"; result << "<table>";

View File

@@ -31,11 +31,13 @@ public:
* *
* @method * @method
* @param {std::function<void(std::string&)>} parseLineCallback * @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback * @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/ */
UnorderedListParser( UnorderedListParser(
std::function<void(std::string&)> parseLineCallback, std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
) )
: BlockParser(parseLineCallback, getBlockParserForLineCallback) : BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false) , isStarted(false)
@@ -51,8 +53,7 @@ public:
* @param {const std::string&} line * @param {const std::string&} line
* @return {bool} * @return {bool}
*/ */
static bool static bool IsStartingLine(const std::string& line)
IsStartingLine(const std::string& line)
{ {
static std::regex re("^[+*-] .*"); static std::regex re("^[+*-] .*");
return std::regex_match(line, re); return std::regex_match(line, re);
@@ -64,27 +65,14 @@ public:
* @method * @method
* @return {bool} * @return {bool}
*/ */
bool bool IsFinished() const override { return this->isFinished; }
IsFinished() const override
{
return this->isFinished;
}
protected: protected:
bool bool isInlineBlockAllowed() const override { return true; }
isInlineBlockAllowed() const override
{
return true;
}
bool bool isLineParserAllowed() const override { return true; }
isLineParserAllowed() const override
{
return true;
}
void void parseBlock(std::string& line) override
parseBlock(std::string& line) override
{ {
bool isStartOfNewListItem = IsStartingLine(line); bool isStartOfNewListItem = IsStartingLine(line);
uint32_t indentation = getIndentationWidth(line); uint32_t indentation = getIndentationWidth(line);
@@ -105,12 +93,9 @@ protected:
return; return;
} }
if ( if (line.empty() || line.find("</li><li>") != std::string::npos ||
line.empty() || line.find("</li></ol>") != std::string::npos ||
line.find("</li><li>") != std::string::npos || line.find("</li></ul>") != std::string::npos)
line.find("</li></ol>") != std::string::npos ||
line.find("</li></ul>") != std::string::npos
)
{ {
line = "</li></ul>" + line; line = "</li></ul>" + line;
this->isFinished = true; this->isFinished = true;

View File

@@ -21,7 +21,7 @@ include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
googletest googletest
GIT_REPOSITORY https://github.com/google/googletest.git GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG b796f7d44681514f58a683a3a71ff17c94edb0c1 # v1.13.0 GIT_TAG v1.17.0
) )
FetchContent_MakeAvailable(googletest) FetchContent_MakeAvailable(googletest)

View File

@@ -15,10 +15,10 @@ class MADDY_CHECKLISTPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::ChecklistParser> clParser; std::shared_ptr<maddy::ChecklistParser> clParser;
void void SetUp() override
SetUp() override
{ {
std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)> getBlockParserForLineCallback = [](const std::string& line) std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)>
getBlockParserForLineCallback = [](const std::string& line)
{ {
if (maddy::ChecklistParser::IsStartingLine(line)) if (maddy::ChecklistParser::IsStartingLine(line))
{ {
@@ -32,15 +32,16 @@ protected:
}; };
this->clParser = std::make_shared<maddy::ChecklistParser>( this->clParser = std::make_shared<maddy::ChecklistParser>(
nullptr, nullptr, getBlockParserForLineCallback
getBlockParserForLineCallback
); );
} }
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_F(MADDY_CHECKLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList) TEST_F(
MADDY_CHECKLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList
)
{ {
ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [ ] a")); ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [ ] a"));
ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [x] b")); ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [x] b"));
@@ -53,12 +54,11 @@ TEST_F(MADDY_CHECKLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHtmlChecklist) TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHtmlChecklist)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {"- [ ] a", "- [x] b", ""};
"- [ ] a" std::string expected =
, "- [x] b" "<ul class=\"checklist\"><li><label><input type=\"checkbox\"/> "
, "" "a</label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> "
}; "b</label></li></ul>";
std::string expected = "<ul class=\"checklist\"><li><label><input type=\"checkbox\"/> a</label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> b</label></li></ul>";
for (std::string md : markdown) for (std::string md : markdown)
{ {
@@ -76,14 +76,15 @@ TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHtmlChecklist)
TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList) TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"- [ ] a" "- [ ] a", " - [ ] d", " - [ ] e", "- [ ] b", " - [x] c", ""
, " - [ ] d"
, " - [ ] e"
, "- [ ] b"
, " - [x] c"
, ""
}; };
std::string expected = "<ul class=\"checklist\"><li><label><input type=\"checkbox\"/> a<ul class=\"checklist\"><li><label><input type=\"checkbox\"/> d</label></li><li><label><input type=\"checkbox\"/> e</label></li></ul></label></li><li><label><input type=\"checkbox\"/> b<ul class=\"checklist\"><li><label><input type=\"checkbox\" checked=\"checked\"/> c</label></li></ul></label></li></ul>"; std::string expected =
"<ul class=\"checklist\"><li><label><input type=\"checkbox\"/> a<ul "
"class=\"checklist\"><li><label><input type=\"checkbox\"/> "
"d</label></li><li><label><input type=\"checkbox\"/> "
"e</label></li></ul></label></li><li><label><input type=\"checkbox\"/> "
"b<ul class=\"checklist\"><li><label><input type=\"checkbox\" "
"checked=\"checked\"/> c</label></li></ul></label></li></ul>";
for (std::string md : markdown) for (std::string md : markdown)
{ {

View File

@@ -15,13 +15,9 @@ class MADDY_CODEBLOCKPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::CodeBlockParser> cbParser; std::shared_ptr<maddy::CodeBlockParser> cbParser;
void void SetUp() override
SetUp() override
{ {
this->cbParser = std::make_shared<maddy::CodeBlockParser>( this->cbParser = std::make_shared<maddy::CodeBlockParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
}; };
@@ -40,13 +36,11 @@ TEST_F(MADDY_CODEBLOCKPARSER, IsFinishedReturnsFalseInTheBeginning)
TEST_F(MADDY_CODEBLOCKPARSER, ItReplacesMarkdownWithAnHtmlCodeBlock) TEST_F(MADDY_CODEBLOCKPARSER, ItReplacesMarkdownWithAnHtmlCodeBlock)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"```" "```", "some code", "some other code", "```"
, "some code"
, "some other code"
, "```"
}; };
std::string expected = "<pre><code>\nsome code\nsome other code\n</code></pre>"; std::string expected =
"<pre><code>\nsome code\nsome other code\n</code></pre>";
for (std::string md : markdown) for (std::string md : markdown)
{ {
@@ -63,13 +57,11 @@ TEST_F(MADDY_CODEBLOCKPARSER, ItReplacesMarkdownWithAnHtmlCodeBlock)
TEST_F(MADDY_CODEBLOCKPARSER, ItShouldUseAnythingBehindFirstBackticksAsClass) TEST_F(MADDY_CODEBLOCKPARSER, ItShouldUseAnythingBehindFirstBackticksAsClass)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"```cpp" "```cpp", "some code", "some other code", "```"
, "some code"
, "some other code"
, "```"
}; };
std::string expected = "<pre class=\"cpp\"><code>\nsome code\nsome other code\n</code></pre>"; std::string expected =
"<pre class=\"cpp\"><code>\nsome code\nsome other code\n</code></pre>";
for (std::string md : markdown) for (std::string md : markdown)
{ {

View File

@@ -24,7 +24,8 @@ TEST(MADDY_EMPHASIZEDPARSER, ItReplacesMarkdownWithEmphasizedHTML)
TEST(MADDY_EMPHASIZEDPARSER, ItDoesNotParseInsideInlineCode) TEST(MADDY_EMPHASIZEDPARSER, ItDoesNotParseInsideInlineCode)
{ {
std::string text = "some text `*bla*` `/**text*/` testing _it_ out"; std::string text = "some text `*bla*` `/**text*/` testing _it_ out";
std::string expected = "some text `*bla*` `/**text*/` testing <em>it</em> out"; std::string expected =
"some text `*bla*` `/**text*/` testing <em>it</em> out";
auto emphasizedParser = std::make_shared<maddy::EmphasizedParser>(); auto emphasizedParser = std::make_shared<maddy::EmphasizedParser>();
emphasizedParser->Parse(text); emphasizedParser->Parse(text);

View File

@@ -15,19 +15,17 @@ class MADDY_HEADLINEPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::HeadlineParser> hlParser; std::shared_ptr<maddy::HeadlineParser> hlParser;
void void SetUp() override
SetUp() override
{ {
this->hlParser = std::make_shared<maddy::HeadlineParser>( this->hlParser = std::make_shared<maddy::HeadlineParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_F(MADDY_HEADLINEPARSER, IsStartingLineReturnsTrueWhenFacedWithOneToSixHashes) TEST_F(
MADDY_HEADLINEPARSER, IsStartingLineReturnsTrueWhenFacedWithOneToSixHashes
)
{ {
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("# a")); ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("# a"));
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("## a")); ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("## a"));
@@ -45,21 +43,16 @@ TEST_F(MADDY_HEADLINEPARSER, IsFinishedAlwaysReturnsTrue)
TEST_F(MADDY_HEADLINEPARSER, ItReplacesMarkdownWithAnHtmlHeadline) TEST_F(MADDY_HEADLINEPARSER, ItReplacesMarkdownWithAnHtmlHeadline)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"# a" "# a", "## a", "### a", "#### a", "##### a", "###### a"
, "## a"
, "### a"
, "#### a"
, "##### a"
, "###### a"
}; };
std::vector<std::string> expected = { std::vector<std::string> expected = {
"<h1>a</h1>" "<h1>a</h1>",
, "<h2>a</h2>" "<h2>a</h2>",
, "<h3>a</h3>" "<h3>a</h3>",
, "<h4>a</h4>" "<h4>a</h4>",
, "<h5>a</h5>" "<h5>a</h5>",
, "<h6>a</h6>" "<h6>a</h6>"
}; };
for (uint8_t i = 0; i < 6; ++i) for (uint8_t i = 0; i < 6; ++i)

View File

@@ -15,19 +15,18 @@ class MADDY_HORIZONTALLINEPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::HorizontalLineParser> hlParser; std::shared_ptr<maddy::HorizontalLineParser> hlParser;
void void SetUp() override
SetUp() override
{ {
this->hlParser = std::make_shared<maddy::HorizontalLineParser>( this->hlParser =
nullptr, std::make_shared<maddy::HorizontalLineParser>(nullptr, nullptr);
nullptr
);
} }
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_F(MADDY_HORIZONTALLINEPARSER, IsStartingLineReturnsTrueWhenFacedWithThreeDashes) TEST_F(
MADDY_HORIZONTALLINEPARSER, IsStartingLineReturnsTrueWhenFacedWithThreeDashes
)
{ {
ASSERT_TRUE(maddy::HorizontalLineParser::IsStartingLine("---")); ASSERT_TRUE(maddy::HorizontalLineParser::IsStartingLine("---"));
} }

View File

@@ -15,13 +15,9 @@ class MADDY_HTMLPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::HtmlParser> pParser; std::shared_ptr<maddy::HtmlParser> pParser;
void void SetUp() override
SetUp() override
{ {
this->pParser = std::make_shared<maddy::HtmlParser>( this->pParser = std::make_shared<maddy::HtmlParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
}; };
@@ -35,11 +31,7 @@ TEST_F(MADDY_HTMLPARSER, IsFinishedReturnsFalseInTheBeginning)
TEST_F(MADDY_HTMLPARSER, IsStartingLineReturnsFalseWhenFacedWithNoSmallerThan) TEST_F(MADDY_HTMLPARSER, IsStartingLineReturnsFalseWhenFacedWithNoSmallerThan)
{ {
const std::vector<std::string> markdown = { const std::vector<std::string> markdown = {
"> quote" "> quote", "some text", "* list", "1. numbered list", "|table>"
, "some text"
, "* list"
, "1. numbered list"
, "|table>"
}; };
for (size_t i = 0; i < markdown.size(); ++i) for (size_t i = 0; i < markdown.size(); ++i)
@@ -57,17 +49,18 @@ TEST_F(MADDY_HTMLPARSER, IsStartingLineReturnsTrueWhenFacedWithSmallerThan)
TEST_F(MADDY_HTMLPARSER, ItReplacesNoHtml) TEST_F(MADDY_HTMLPARSER, ItReplacesNoHtml)
{ {
const std::vector<std::string> markdown { const std::vector<std::string> markdown{
"some text in a paragraph" "some text in a paragraph",
, "" "",
, "<div> some HTML</div>" "<div> some HTML</div>",
, "" "",
, "<div>more" "<div>more",
, "HTML" "HTML",
, "</div>" "</div>",
, "" ""
}; };
const std::string expected = "some text in a paragraph <div> some HTML</div><div>more HTML </div>"; const std::string expected =
"some text in a paragraph <div> some HTML</div><div>more HTML </div>";
for (std::string md : markdown) for (std::string md : markdown)
{ {

View File

@@ -13,7 +13,8 @@
TEST(MADDY_IMAGEPARSER, ItReplacesMarkdownWithAnImage) TEST(MADDY_IMAGEPARSER, ItReplacesMarkdownWithAnImage)
{ {
std::string text = "Some text ![Image Title](http://example.com/a.png)"; std::string text = "Some text ![Image Title](http://example.com/a.png)";
std::string expected = "Some text <img src=\"http://example.com/a.png\" alt=\"Image Title\"/>"; std::string expected =
"Some text <img src=\"http://example.com/a.png\" alt=\"Image Title\"/>";
auto imageParser = std::make_shared<maddy::ImageParser>(); auto imageParser = std::make_shared<maddy::ImageParser>();
imageParser->Parse(text); imageParser->Parse(text);
@@ -23,8 +24,12 @@ TEST(MADDY_IMAGEPARSER, ItReplacesMarkdownWithAnImage)
TEST(MADDY_IMAGEPARSER, ItReplacesMarkdownWithImages) TEST(MADDY_IMAGEPARSER, ItReplacesMarkdownWithImages)
{ {
std::string text = "Some text ![Image Title](http://example.com/a.png) bla ![Image Title](http://example.com/a.png)"; std::string text =
std::string expected = "Some text <img src=\"http://example.com/a.png\" alt=\"Image Title\"/> bla <img src=\"http://example.com/a.png\" alt=\"Image Title\"/>"; "Some text ![Image Title](http://example.com/a.png) bla ![Image "
"Title](http://example.com/a.png)";
std::string expected =
"Some text <img src=\"http://example.com/a.png\" alt=\"Image Title\"/> bla "
"<img src=\"http://example.com/a.png\" alt=\"Image Title\"/>";
auto imageParser = std::make_shared<maddy::ImageParser>(); auto imageParser = std::make_shared<maddy::ImageParser>();
imageParser->Parse(text); imageParser->Parse(text);

View File

@@ -13,7 +13,8 @@
TEST(MADDY_INLINECODEPARSER, ItReplacesMarkdownWithCodeHTML) TEST(MADDY_INLINECODEPARSER, ItReplacesMarkdownWithCodeHTML)
{ {
std::string text = "some text `bla` text testing `it` out"; std::string text = "some text `bla` text testing `it` out";
std::string expected = "some text <code>bla</code> text testing <code>it</code> out"; std::string expected =
"some text <code>bla</code> text testing <code>it</code> out";
auto emphasizedParser = std::make_shared<maddy::InlineCodeParser>(); auto emphasizedParser = std::make_shared<maddy::InlineCodeParser>();
emphasizedParser->Parse(text); emphasizedParser->Parse(text);

View File

@@ -12,7 +12,6 @@
TEST(MADDY_ITALICPARSER, ItReplacesMarkdownWithItalicHTML) TEST(MADDY_ITALICPARSER, ItReplacesMarkdownWithItalicHTML)
{ {
std::string text = "some text *bla* text testing *it* out"; std::string text = "some text *bla* text testing *it* out";
std::string expected = "some text <i>bla</i> text testing <i>it</i> out"; std::string expected = "some text <i>bla</i> text testing <i>it</i> out";
auto italicParser = std::make_shared<maddy::ItalicParser>(); auto italicParser = std::make_shared<maddy::ItalicParser>();

View File

@@ -15,13 +15,10 @@ class MADDY_LATEXBLOCKPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::LatexBlockParser> lbParser; std::shared_ptr<maddy::LatexBlockParser> lbParser;
void void SetUp() override
SetUp() override
{ {
this->lbParser = std::make_shared<maddy::LatexBlockParser>( this->lbParser =
nullptr, std::make_shared<maddy::LatexBlockParser>(nullptr, nullptr);
nullptr
);
} }
}; };
@@ -60,9 +57,7 @@ TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesOneLineMarkdownWithALatexBlock)
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesABlockMarkdownWithALatexBlock) TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesABlockMarkdownWithALatexBlock)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"$$", "$$", "x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.", "$$"
"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.",
"$$"
}; };
std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.\n$$\n"; std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.\n$$\n";
@@ -82,9 +77,7 @@ TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesABlockMarkdownWithALatexBlock)
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesAMultilineBlockMarkdownWithALatexBlock) TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesAMultilineBlockMarkdownWithALatexBlock)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"$$", "$$", "x = {-b \\pm \\sqrt{b^2-4ac}", "\\over 2a}.$$"
"x = {-b \\pm \\sqrt{b^2-4ac}",
"\\over 2a}.$$"
}; };
std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac}\n\\over 2a}.$$\n"; std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac}\n\\over 2a}.$$\n";

View File

@@ -13,7 +13,8 @@
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithALink) TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithALink)
{ {
std::string text = "Some text [Link Title](http://example.com)"; std::string text = "Some text [Link Title](http://example.com)";
std::string expected = "Some text <a href=\"http://example.com\">Link Title</a>"; std::string expected =
"Some text <a href=\"http://example.com\">Link Title</a>";
auto linkParser = std::make_shared<maddy::LinkParser>(); auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text); linkParser->Parse(text);
@@ -23,8 +24,12 @@ TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithALink)
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithLinks) TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithLinks)
{ {
std::string text = "Some text [Link Title](http://example.com) bla [Link Title](http://example.com)"; std::string text =
std::string expected = "Some text <a href=\"http://example.com\">Link Title</a> bla <a href=\"http://example.com\">Link Title</a>"; "Some text [Link Title](http://example.com) bla [Link "
"Title](http://example.com)";
std::string expected =
"Some text <a href=\"http://example.com\">Link Title</a> bla <a "
"href=\"http://example.com\">Link Title</a>";
auto linkParser = std::make_shared<maddy::LinkParser>(); auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text); linkParser->Parse(text);
@@ -32,9 +37,152 @@ TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithLinks)
ASSERT_EQ(expected, text); ASSERT_EQ(expected, text);
} }
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithSpacesAfterLink)
{
std::string text =
"Some text [Link Title](http://example.com ) bla [Link "
"Title](http://example.com)";
std::string expected =
"Some text <a href=\"http://example.com\">Link Title</a> bla <a "
"href=\"http://example.com\">Link Title</a>";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItHandlesURLsWithOfficiallyIllegalCharacters)
{
// Some links in the real world have characters that are not
// 'official' characters that are supposedly allowed in URLs.
std::string text =
"Wikipedia's [Möbius strip]"
"(https://en.wikipedia.org/wiki/Möbius_strip) link.";
std::string expected =
"Wikipedia's <a "
"href=\"https://en.wikipedia.org/wiki/Möbius_strip\">"
"Möbius strip</a> link.";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(
MADDY_LINKPARSER, ItReplacesMarkdownProperlyEvenWithMultipleParenthesisInLine
)
{
std::string text =
"(This is a [link](/ABC/some_file) (the URL will not include this).)";
std::string expected =
"(This is a <a href=\"/ABC/some_file\">link</a> (the URL will not include "
"this).)";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItDoesntReplaceMarkdownWithSpaceInURL)
{
// Spaces are not allowed in URLs, so don't match them.
std::string text = "This is an invalid [link](/ABC/some file)";
std::string expected = "This is an invalid [link](/ABC/some file)";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithTitleText)
{
std::string text = "Link to [name](http:://example.com \"title text\")";
std::string expected =
"Link to <a href=\"http:://example.com\" title=\"title text\">name</a>";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithSpacesWithTitleText)
{
std::string text = "Link to [name](http:://example.com \"title text\")";
std::string expected =
"Link to <a href=\"http:://example.com\" title=\"title text\">name</a>";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithMoreSpacesWithTitleText)
{
std::string text =
"Link to [name](http:://example.com \"title text\" )";
std::string expected =
"Link to <a href=\"http:://example.com\" title=\"title text\">name</a>";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithParentheticalText)
{
std::string text = "Link to [name](http:://example.com \"title (text)\")";
std::string expected =
"Link to <a href=\"http:://example.com\" title=\"title (text)\">name</a>";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItDoesntReplaceMarkdownWithTooManyQuotes)
{
// If you have too many quotation marks, don't match:
std::string text =
"This is an invalid [link](/ABC/some_file \"title \" text \")";
std::string expected =
"This is an invalid [link](/ABC/some_file \"title \" text \")";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}
TEST(MADDY_LINKPARSER, ItDoesntReplaceMarkdownWithQuoteInLink)
{
// This is actually legal markdown, but hard to parse with regexes;
// See disabled 'ItReplacesMarkdownWithQuoteInLink' below.
//
// For now, don't try to translate it; it would produce invalid HTML.
std::string text = "Some text [Link Title](http://example.com/\"foo ) bla.";
std::string current_expected =
"Some text [Link Title](http://example.com/\"foo ) bla.";
std::string correct_expected =
"Some text <a href=\"http://example.com/%22foo\">Link Title</a> bla.";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(current_expected, text);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
class DISABLED_MADDY_LINKPARSER : public ::testing::Test { }; class DISABLED_MADDY_LINKPARSER : public ::testing::Test
{};
// This test is disabled for now, so make sure, to first run the ImageParser // This test is disabled for now, so make sure, to first run the ImageParser
// before using the LinkParser // before using the LinkParser
@@ -48,3 +196,17 @@ TEST_F(DISABLED_MADDY_LINKPARSER, ItReplacesNoImageMarkdownWithLinks)
ASSERT_EQ(expected, text); ASSERT_EQ(expected, text);
} }
TEST(DISABLED_MADDY_LINKPARSER, ItReplacesMarkdownWithQuoteInLink)
{
// This is legal markdown, but hard to parse with regexes; dropping it
// here for a future update.
std::string text = "Some text [Link Title](http://example.com/\"foo ) bla.";
std::string expected =
"Some text <a href=\"http://example.com/%22foo\">Link Title</a> bla.";
auto linkParser = std::make_shared<maddy::LinkParser>();
linkParser->Parse(text);
ASSERT_EQ(expected, text);
}

View File

@@ -15,10 +15,10 @@ class MADDY_ORDEREDLISTPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::OrderedListParser> olParser; std::shared_ptr<maddy::OrderedListParser> olParser;
void void SetUp() override
SetUp() override
{ {
std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)> getBlockParserForLineCallback = [](const std::string& line) std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)>
getBlockParserForLineCallback = [](const std::string& line)
{ {
if (maddy::OrderedListParser::IsStartingLine(line)) if (maddy::OrderedListParser::IsStartingLine(line))
{ {
@@ -32,15 +32,16 @@ protected:
}; };
this->olParser = std::make_shared<maddy::OrderedListParser>( this->olParser = std::make_shared<maddy::OrderedListParser>(
nullptr, nullptr, getBlockParserForLineCallback
getBlockParserForLineCallback
); );
} }
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_F(MADDY_ORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList) TEST_F(
MADDY_ORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList
)
{ {
ASSERT_TRUE(maddy::OrderedListParser::IsStartingLine("1. a")); ASSERT_TRUE(maddy::OrderedListParser::IsStartingLine("1. a"));
} }
@@ -52,11 +53,7 @@ TEST_F(MADDY_ORDEREDLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlOrderedList) TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlOrderedList)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {"1. a", "* b", ""};
"1. a"
, "* b"
, ""
};
std::string expected = "<ol><li>a</li><li>b</li></ol>"; std::string expected = "<ol><li>a</li><li>b</li></ol>";
for (std::string md : markdown) for (std::string md : markdown)
@@ -75,14 +72,11 @@ TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlOrderedList)
TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList) TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"1. a" "1. a", " 1. d", " * e", "* b", " 1. c", ""
, " 1. d"
, " * e"
, "* b"
, " 1. c"
, ""
}; };
std::string expected = "<ol><li>a<ol><li>d</li><li>e</li></ol></li><li>b<ol><li>c</li></ol></li></ol>"; std::string expected =
"<ol><li>a<ol><li>d</li><li>e</li></ol></li><li>b<ol><li>c</li></ol></li></"
"ol>";
for (std::string md : markdown) for (std::string md : markdown)
{ {
@@ -97,14 +91,11 @@ TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
ASSERT_EQ(expected, outputString); ASSERT_EQ(expected, outputString);
} }
TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesNumberedMarkdownListWithAnHtmlOrderedList) TEST_F(
MADDY_ORDEREDLISTPARSER, ItReplacesNumberedMarkdownListWithAnHtmlOrderedList
)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {"1. a", "94. b", "103. c", ""};
"1. a"
, "94. b"
, "103. c"
, ""
};
std::string expected = "<ol><li>a</li><li>b</li><li>c</li></ol>"; std::string expected = "<ol><li>a</li><li>b</li><li>c</li></ol>";
for (std::string md : markdown) for (std::string md : markdown)

View File

@@ -15,14 +15,10 @@ class MADDY_PARAGRAPHPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::ParagraphParser> pParser; std::shared_ptr<maddy::ParagraphParser> pParser;
void void SetUp() override
SetUp() override
{ {
this->pParser = std::make_shared<maddy::ParagraphParser>( this->pParser =
nullptr, std::make_shared<maddy::ParagraphParser>(nullptr, nullptr, true);
nullptr,
true
);
} }
}; };
@@ -40,11 +36,7 @@ TEST_F(MADDY_PARAGRAPHPARSER, IsFinishedReturnsFalseInTheBeginning)
TEST_F(MADDY_PARAGRAPHPARSER, ItReplacesMarkdownWithAnHtmlLine) TEST_F(MADDY_PARAGRAPHPARSER, ItReplacesMarkdownWithAnHtmlLine)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {"Some text", "and some other text", ""};
"Some text"
, "and some other text"
, ""
};
std::string expected = "<p>Some text and some other text </p>"; std::string expected = "<p>Some text and some other text </p>";
for (std::string md : markdown) for (std::string md : markdown)

View File

@@ -3,10 +3,11 @@
* LICENSE file. * LICENSE file.
*/ */
#include "maddy/test_maddy_parser.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "maddy/parser.h" #include "maddy/parser.h"
#include "maddy/test_maddy_parser.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -20,21 +21,6 @@ TEST(MADDY_PARSER, ItShouldParse)
ASSERT_EQ(testHtml, output); ASSERT_EQ(testHtml, output);
} }
TEST(MADDY_PARSER, ItShouldParseWithConfig)
{
auto config = std::make_shared<maddy::ParserConfig>();
config->isEmphasizedParserEnabled = false;
config->isHTMLWrappedInParagraph = false;
auto parser = std::make_shared<maddy::Parser>(config);
std::stringstream markdown(testMarkdown);
const std::string output = parser->Parse(markdown);
ASSERT_EQ(testHtml2, output);
}
TEST(MADDY_PARSER, ItShouldParseWithBitwiseConfig) TEST(MADDY_PARSER, ItShouldParseWithBitwiseConfig)
{ {
auto config = std::make_shared<maddy::ParserConfig>(); auto config = std::make_shared<maddy::ParserConfig>();
@@ -53,8 +39,8 @@ TEST(MADDY_PARSER, ItShouldParseWithBitwiseConfig)
TEST(MADDY_PARSER, ItShouldParseWithSmallConfig) TEST(MADDY_PARSER, ItShouldParseWithSmallConfig)
{ {
auto config = std::make_shared<maddy::ParserConfig>(); auto config = std::make_shared<maddy::ParserConfig>();
config->enabledParsers = maddy::types::EMPHASIZED_PARSER | config->enabledParsers =
maddy::types::STRONG_PARSER; maddy::types::EMPHASIZED_PARSER | maddy::types::STRONG_PARSER;
auto parser = std::make_shared<maddy::Parser>(config); auto parser = std::make_shared<maddy::Parser>(config);
@@ -64,3 +50,35 @@ TEST(MADDY_PARSER, ItShouldParseWithSmallConfig)
ASSERT_EQ(testHtml3, output); ASSERT_EQ(testHtml3, output);
} }
TEST(MADDY_PARSER, ItShouldParseInlineCodeInHeadlines)
{
const std::string headlineTest = R"(
# Some **test** markdown
)";
const std::string expectedHTML =
"<h1>Some <strong>test</strong> markdown</h1>";
std::stringstream markdown(headlineTest);
auto parser = std::make_shared<maddy::Parser>();
const std::string output = parser->Parse(markdown);
ASSERT_EQ(expectedHTML, output);
}
TEST(MADDY_PARSER, ItShouldNotParseInlineCodeInHeadlineIfDisabled)
{
const std::string headlineTest = R"(
# Some **test** markdown
)";
const std::string expectedHTML = "<h1>Some **test** markdown</h1>";
std::stringstream markdown(headlineTest);
auto config = std::make_shared<maddy::ParserConfig>();
config->isHeadlineInlineParsingEnabled = false;
auto parser = std::make_shared<maddy::Parser>(config);
const std::string output = parser->Parse(markdown);
ASSERT_EQ(expectedHTML, output);
}

View File

@@ -6,7 +6,8 @@
#include <string> #include <string>
const std::string testMarkdown = "# This is a test\n\ const std::string testMarkdown =
"# This is a test\n\
\n\ \n\
This should result in a praragraph\n\ This should result in a praragraph\n\
it's that simple.\n\ it's that simple.\n\
@@ -69,6 +70,71 @@ foot a|foot b|foot c\n\
\n\ \n\
"; ";
const std::string testHtml = "<h1>This is a test</h1><p>This should result in a praragraph it's that simple. </p><ul><li>an <i>unordered</i> list<ul><li>with some <strong>hierarchy</strong><ol><li>and an <em>ordered</em></li><li>list</li><li>directly</li></ol></li><li>inside</li></ul></li></ul><pre><code>\nvar c = 'blub';\n</code></pre><blockquote><p>A Quote </p><p>With some <s>text</s> blocks inside </p><ul><li>even a list </li><li>should be </li><li>possible </li></ul></blockquote><p>And well <code>inline code</code> should also work. </p><h2>Another Headline</h2><p>And not to forget <a href=\"http://progsource.de\">link to progsource</a> should work. And well - let's see how an image would be shown: </p><p><img src=\"http://progsource.de/img/progsource.png\" alt=\"an image\"/> </p><hr/><p><a name=\"to top\"></a> </p><h3>and more headlines</h3><ul class=\"checklist\"><li><label><input type=\"checkbox\"/> how</label></li><li><label><input type=\"checkbox\"/> about<ul class=\"checklist\"><li><label><input type=\"checkbox\"/> a</label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> nice</label></li></ul></label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> check</label></li><li><label><input type=\"checkbox\"/> list</label></li></ul><h4>even a table</h4><table><thead><tr><th>Left header</th><th>middle header</th><th>last header</th></tr></thead><tbody><tr><td>cell 1</td><td>cell <strong>2</strong></td><td>cell 3</td></tr><tr><td>cell 4</td><td>cell 5</td><td>cell 6</td></tr></tbody><tfoot><tr><td>foot a</td><td>foot b</td><td>foot c</td></tr></tfoot></table><h5>h5</h5><h6>h6</h6>"; const std::string testHtml =
const std::string testHtml2 = "<h1>This is a test</h1><p>This should result in a praragraph it's that simple. </p><ul><li>an <i>unordered</i> list<ul><li>with some <strong>hierarchy</strong><ol><li>and an _ordered_</li><li>list</li><li>directly</li></ol></li><li>inside</li></ul></li></ul><pre><code>\nvar c = 'blub';\n</code></pre><blockquote><p>A Quote </p><p>With some <s>text</s> blocks inside </p><ul><li>even a list </li><li>should be </li><li>possible </li></ul></blockquote><p>And well <code>inline code</code> should also work. </p><h2>Another Headline</h2><p>And not to forget <a href=\"http://progsource.de\">link to progsource</a> should work. And well - let's see how an image would be shown: </p><p><img src=\"http://progsource.de/img/progsource.png\" alt=\"an image\"/> </p><hr/><a name=\"to top\"></a><h3>and more headlines</h3><ul class=\"checklist\"><li><label><input type=\"checkbox\"/> how</label></li><li><label><input type=\"checkbox\"/> about<ul class=\"checklist\"><li><label><input type=\"checkbox\"/> a</label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> nice</label></li></ul></label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> check</label></li><li><label><input type=\"checkbox\"/> list</label></li></ul><h4>even a table</h4><table><thead><tr><th>Left header</th><th>middle header</th><th>last header</th></tr></thead><tbody><tr><td>cell 1</td><td>cell <strong>2</strong></td><td>cell 3</td></tr><tr><td>cell 4</td><td>cell 5</td><td>cell 6</td></tr></tbody><tfoot><tr><td>foot a</td><td>foot b</td><td>foot c</td></tr></tfoot></table><h5>h5</h5><h6>h6</h6>"; "<h1>This is a test</h1><p>This should result in a praragraph it's that "
const std::string testHtml3 = "# This is a test <br/>This should result in a praragraph it's that simple. <br/>* an *unordered* list * with some <strong>hierarchy</strong> 1. and an <em>ordered</em> * list * directly * inside <br/>``` var c = 'blub'; ``` <br/>> A Quote > > With some ~~text~~ blocks inside > > * even a list > * should be > * possible > <br/>And well `inline code` should also work. <br/>## Another Headline <br/>And not to forget [link to progsource](http://progsource.de) should work. And well - let's see how an image would be shown: <br/>![an image](http://progsource.de/img/progsource.png) <br/>--- <br/><a name=\"to top\"></a> <br/>### and more headlines <br/>- [ ] how - [ ] about - [ ] a - [x] nice - [x] check - [ ] list <br/>#### even a table <br/>|table> Left header|middle header|last header - | - | - cell 1|cell <strong>2</strong>|cell 3 cell 4|cell 5|cell 6 - | - | - foot a|foot b|foot c |<table <br/>##### h5 ###### h6 <br/>"; "simple. </p><ul><li>an <i>unordered</i> list<ul><li>with some "
"<strong>hierarchy</strong><ol><li>and an "
"<em>ordered</em></li><li>list</li><li>directly</li></ol></li><li>inside</"
"li></ul></li></ul><pre><code>\nvar c = "
"'blub';\n</code></pre><blockquote><p>A Quote </p><p>With some <s>text</s> "
"blocks inside </p><ul><li>even a list </li><li>should be </li><li>possible "
"</li></ul></blockquote><p>And well <code>inline code</code> should also "
"work. </p><h2>Another Headline</h2><p>And not to forget <a "
"href=\"http://progsource.de\">link to progsource</a> should work. And well "
"- let's see how an image would be shown: </p><p><img "
"src=\"http://progsource.de/img/progsource.png\" alt=\"an image\"/> "
"</p><hr/><p><a name=\"to top\"></a> </p><h3>and more headlines</h3><ul "
"class=\"checklist\"><li><label><input type=\"checkbox\"/> "
"how</label></li><li><label><input type=\"checkbox\"/> about<ul "
"class=\"checklist\"><li><label><input type=\"checkbox\"/> "
"a</label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> "
"nice</label></li></ul></label></li><li><label><input type=\"checkbox\" "
"checked=\"checked\"/> check</label></li><li><label><input "
"type=\"checkbox\"/> list</label></li></ul><h4>even a "
"table</h4><table><thead><tr><th>Left header</th><th>middle "
"header</th><th>last header</th></tr></thead><tbody><tr><td>cell "
"1</td><td>cell <strong>2</strong></td><td>cell 3</td></tr><tr><td>cell "
"4</td><td>cell 5</td><td>cell 6</td></tr></tbody><tfoot><tr><td>foot "
"a</td><td>foot b</td><td>foot "
"c</td></tr></tfoot></table><h5>h5</h5><h6>h6</h6>";
const std::string testHtml2 =
"<h1>This is a test</h1><p>This should result in a praragraph it's that "
"simple. </p><ul><li>an <i>unordered</i> list<ul><li>with some "
"<strong>hierarchy</strong><ol><li>and an "
"_ordered_</li><li>list</li><li>directly</li></ol></li><li>inside</li></ul></"
"li></ul><pre><code>\nvar c = 'blub';\n</code></pre><blockquote><p>A Quote "
"</p><p>With some <s>text</s> blocks inside </p><ul><li>even a list "
"</li><li>should be </li><li>possible </li></ul></blockquote><p>And well "
"<code>inline code</code> should also work. </p><h2>Another "
"Headline</h2><p>And not to forget <a href=\"http://progsource.de\">link to "
"progsource</a> should work. And well - let's see how an image would be "
"shown: </p><p><img src=\"http://progsource.de/img/progsource.png\" alt=\"an "
"image\"/> </p><hr/><a name=\"to top\"></a><h3>and more headlines</h3><ul "
"class=\"checklist\"><li><label><input type=\"checkbox\"/> "
"how</label></li><li><label><input type=\"checkbox\"/> about<ul "
"class=\"checklist\"><li><label><input type=\"checkbox\"/> "
"a</label></li><li><label><input type=\"checkbox\" checked=\"checked\"/> "
"nice</label></li></ul></label></li><li><label><input type=\"checkbox\" "
"checked=\"checked\"/> check</label></li><li><label><input "
"type=\"checkbox\"/> list</label></li></ul><h4>even a "
"table</h4><table><thead><tr><th>Left header</th><th>middle "
"header</th><th>last header</th></tr></thead><tbody><tr><td>cell "
"1</td><td>cell <strong>2</strong></td><td>cell 3</td></tr><tr><td>cell "
"4</td><td>cell 5</td><td>cell 6</td></tr></tbody><tfoot><tr><td>foot "
"a</td><td>foot b</td><td>foot "
"c</td></tr></tfoot></table><h5>h5</h5><h6>h6</h6>";
const std::string testHtml3 =
"# This is a test <br/>This should result in a praragraph it's that simple. "
"<br/>* an *unordered* list * with some <strong>hierarchy</strong> 1. "
"and an <em>ordered</em> * list * directly * inside <br/>``` var c "
"= 'blub'; ``` <br/>> A Quote > > With some ~~text~~ blocks inside > > * "
"even a list > * should be > * possible > <br/>And well `inline code` should "
"also work. <br/>## Another Headline <br/>And not to forget [link to "
"progsource](http://progsource.de) should work. And well - let's see how an "
"image would be shown: <br/>![an "
"image](http://progsource.de/img/progsource.png) <br/>--- <br/><a name=\"to "
"top\"></a> <br/>### and more headlines <br/>- [ ] how - [ ] about - [ ] a "
" - [x] nice - [x] check - [ ] list <br/>#### even a table <br/>|table> "
"Left header|middle header|last header - | - | - cell 1|cell "
"<strong>2</strong>|cell 3 cell 4|cell 5|cell 6 - | - | - foot a|foot b|foot "
"c |<table <br/>##### h5 ###### h6 <br/>";

View File

@@ -15,19 +15,17 @@ class MADDY_QUOTEPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::QuoteParser> quoteParser; std::shared_ptr<maddy::QuoteParser> quoteParser;
void void SetUp() override
SetUp() override
{ {
this->quoteParser = std::make_shared<maddy::QuoteParser>( this->quoteParser = std::make_shared<maddy::QuoteParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_F(MADDY_QUOTEPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfAQuote) TEST_F(
MADDY_QUOTEPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfAQuote
)
{ {
ASSERT_TRUE(maddy::QuoteParser::IsStartingLine("> a")); ASSERT_TRUE(maddy::QuoteParser::IsStartingLine("> a"));
} }
@@ -39,13 +37,7 @@ TEST_F(MADDY_QUOTEPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_QUOTEPARSER, ItReplacesMarkdownWithAnHtmlBlockQuote) TEST_F(MADDY_QUOTEPARSER, ItReplacesMarkdownWithAnHtmlBlockQuote)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {"> a", "> b", ">", "> c", ""};
"> a"
, "> b"
, ">"
, "> c"
, ""
};
std::string expected = "<blockquote>a b c </blockquote>"; std::string expected = "<blockquote>a b c </blockquote>";
for (std::string md : markdown) for (std::string md : markdown)

View File

@@ -23,8 +23,10 @@ TEST(MADDY_STRIKETHROUGHPARSER, ItReplacesMarkdownWithStrikeThroughHTML)
TEST(MADDY_STRIKETHROUGHPARSER, ItDoesNotParseInsideInlineCode) TEST(MADDY_STRIKETHROUGHPARSER, ItDoesNotParseInsideInlineCode)
{ {
std::string text = "some text `~~bla~~` ` ~~text~~ ` testing <code>~~it~~</code> out"; std::string text =
std::string expected = "some text `~~bla~~` ` ~~text~~ ` testing <code>~~it~~</code> out"; "some text `~~bla~~` ` ~~text~~ ` testing <code>~~it~~</code> out";
std::string expected =
"some text `~~bla~~` ` ~~text~~ ` testing <code>~~it~~</code> out";
auto strikeThroughParser = std::make_shared<maddy::StrikeThroughParser>(); auto strikeThroughParser = std::make_shared<maddy::StrikeThroughParser>();
strikeThroughParser->Parse(text); strikeThroughParser->Parse(text);

View File

@@ -18,16 +18,11 @@ TEST(MADDY_STRONGPARSER, ItReplacesMarkdownWithStrongHTML)
std::string expected; std::string expected;
}; };
std::vector<testIt> tests std::vector<testIt> tests{
{ {"some text **bla** text testing **it** out",
{ "some text <strong>bla</strong> text testing <strong>it</strong> out"},
"some text **bla** text testing **it** out", {"some text __bla__ text testing __it__ out",
"some text <strong>bla</strong> text testing <strong>it</strong> out" "some text <strong>bla</strong> text testing <strong>it</strong> out"},
},
{
"some text __bla__ text testing __it__ out",
"some text <strong>bla</strong> text testing <strong>it</strong> out"
},
}; };
auto strongParser = std::make_shared<maddy::StrongParser>(); auto strongParser = std::make_shared<maddy::StrongParser>();
@@ -47,16 +42,11 @@ TEST(MADDY_STRONGPARSER, ItReplacesEmphasizedMarkdownNotWithStrongHTML)
std::string expected; std::string expected;
}; };
std::vector<testIt> tests std::vector<testIt> tests{
{ {"some text *bla* text testing **it** out",
{ "some text *bla* text testing <strong>it</strong> out"},
"some text *bla* text testing **it** out", {"some text _bla_ text testing __it__ out",
"some text *bla* text testing <strong>it</strong> out" "some text _bla_ text testing <strong>it</strong> out"},
},
{
"some text _bla_ text testing __it__ out",
"some text _bla_ text testing <strong>it</strong> out"
},
}; };
auto strongParser = std::make_shared<maddy::StrongParser>(); auto strongParser = std::make_shared<maddy::StrongParser>();
@@ -76,16 +66,13 @@ TEST(MADDY_STRONGPARSER, ItDoesNotParseInsideInlineCode)
std::string expected; std::string expected;
}; };
std::vector<testIt> tests std::vector<testIt> tests{
{
{ {
"some text **bla** `/**text**/` testing `**it**` out", "some text **bla** `/**text**/` testing `**it**` out",
"some text **bla** `/**text**/` testing `**it**` out", "some text **bla** `/**text**/` testing `**it**` out",
}, },
{ {"some text _bla_ text testing __it__ out",
"some text _bla_ text testing __it__ out", "some text _bla_ text testing <strong>it</strong> out"},
"some text _bla_ text testing <strong>it</strong> out"
},
}; };
auto strongParser = std::make_shared<maddy::StrongParser>(); auto strongParser = std::make_shared<maddy::StrongParser>();

View File

@@ -15,19 +15,17 @@ class MADDY_TABLEPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::TableParser> tableParser; std::shared_ptr<maddy::TableParser> tableParser;
void void SetUp() override
SetUp() override
{ {
this->tableParser = std::make_shared<maddy::TableParser>( this->tableParser = std::make_shared<maddy::TableParser>(nullptr, nullptr);
nullptr,
nullptr
);
} }
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_F(MADDY_TABLEPARSER, IsStartingLineReturnsTrueWhenFacedWithTheBeginningOfATable) TEST_F(
MADDY_TABLEPARSER, IsStartingLineReturnsTrueWhenFacedWithTheBeginningOfATable
)
{ {
ASSERT_EQ(true, maddy::TableParser::IsStartingLine("|table>")); ASSERT_EQ(true, maddy::TableParser::IsStartingLine("|table>"));
} }
@@ -40,16 +38,21 @@ TEST_F(MADDY_TABLEPARSER, IsFinishedReturnsFalseInTheBeginning)
TEST_F(MADDY_TABLEPARSER, ItReplacesMarkdownWithAnHtmlTable) TEST_F(MADDY_TABLEPARSER, ItReplacesMarkdownWithAnHtmlTable)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"|table>" "|table>",
, "Left header|middle header|last header" "Left header|middle header|last header",
, "- | - | -" "- | - | -",
, "cell 1|cell 2|cell 3" "cell 1|cell 2|cell 3",
, "cell 4|cell 5|cell 6" "cell 4|cell 5|cell 6",
, "- | - | -" "- | - | -",
, "foot a|foot b|foot c" "foot a|foot b|foot c",
, "|<table" "|<table"
}; };
std::string expected = "<table><thead><tr><th>Left header</th><th>middle header</th><th>last header</th></tr></thead><tbody><tr><td>cell 1</td><td>cell 2</td><td>cell 3</td></tr><tr><td>cell 4</td><td>cell 5</td><td>cell 6</td></tr></tbody><tfoot><tr><td>foot a</td><td>foot b</td><td>foot c</td></tr></tfoot></table>"; std::string expected =
"<table><thead><tr><th>Left header</th><th>middle header</th><th>last "
"header</th></tr></thead><tbody><tr><td>cell 1</td><td>cell 2</td><td>cell "
"3</td></tr><tr><td>cell 4</td><td>cell 5</td><td>cell "
"6</td></tr></tbody><tfoot><tr><td>foot a</td><td>foot b</td><td>foot "
"c</td></tr></tfoot></table>";
for (std::string md : markdown) for (std::string md : markdown)
{ {

View File

@@ -15,10 +15,10 @@ class MADDY_UNORDEREDLISTPARSER : public ::testing::Test
protected: protected:
std::shared_ptr<maddy::UnorderedListParser> ulParser; std::shared_ptr<maddy::UnorderedListParser> ulParser;
void void SetUp() override
SetUp() override
{ {
std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)> getBlockParserForLineCallback = [](const std::string& line) std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)>
getBlockParserForLineCallback = [](const std::string& line)
{ {
if (maddy::UnorderedListParser::IsStartingLine(line)) if (maddy::UnorderedListParser::IsStartingLine(line))
{ {
@@ -32,15 +32,17 @@ protected:
}; };
this->ulParser = std::make_shared<maddy::UnorderedListParser>( this->ulParser = std::make_shared<maddy::UnorderedListParser>(
nullptr, nullptr, getBlockParserForLineCallback
getBlockParserForLineCallback
); );
} }
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_F(MADDY_UNORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList) TEST_F(
MADDY_UNORDEREDLISTPARSER,
IsStartingLineReturnsTrueWhenFacedWithBeginningOfList
)
{ {
ASSERT_TRUE(maddy::UnorderedListParser::IsStartingLine("* a")); ASSERT_TRUE(maddy::UnorderedListParser::IsStartingLine("* a"));
} }
@@ -53,16 +55,11 @@ TEST_F(MADDY_UNORDEREDLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlUnorderedList) TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlUnorderedList)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"* a" "* a", "* b", "- c", "- d", "+ e", "+ f", "* g", ""
, "* b"
, "- c"
, "- d"
, "+ e"
, "+ f"
, "* g"
, ""
}; };
std::string expected = "<ul><li>a</li><li>b</li><li>c</li><li>d</li><li>e</li><li>f</li><li>g</li></ul>"; std::string expected =
"<ul><li>a</li><li>b</li><li>c</li><li>d</li><li>e</li><li>f</li><li>g</"
"li></ul>";
for (std::string md : markdown) for (std::string md : markdown)
{ {
@@ -80,17 +77,11 @@ TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlUnorderedList)
TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList) TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
{ {
std::vector<std::string> markdown = { std::vector<std::string> markdown = {
"* a" "* a", " * d", " * e", "* b", " * c", " + x", " + y", " - z", ""
, " * d"
, " * e"
, "* b"
, " * c"
, " + x"
, " + y"
, " - z"
, ""
}; };
std::string expected = "<ul><li>a<ul><li>d</li><li>e</li></ul></li><li>b<ul><li>c</li><li>x</li><li>y</li><li>z</li></ul></li></ul>"; std::string expected =
"<ul><li>a<ul><li>d</li><li>e</li></ul></li><li>b<ul><li>c</li><li>x</"
"li><li>y</li><li>z</li></ul></li></ul>";
for (std::string md : markdown) for (std::string md : markdown)
{ {

View File

@@ -7,7 +7,8 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
int main (int argc, char** argv) { int main(int argc, char** argv)
{
::testing::GTEST_FLAG(throw_on_failure) = true; ::testing::GTEST_FLAG(throw_on_failure) = true;
::testing::InitGoogleMock(&argc, argv); ::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

12
tools/Pipfile Normal file
View File

@@ -0,0 +1,12 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
requests = "*"
[dev-packages]
[requires]
python_version = "3.11"

165
tools/Pipfile.lock generated Normal file
View File

@@ -0,0 +1,165 @@
{
"_meta": {
"hash": {
"sha256": "ff88c6939e3090788e917cfdecf1af872168b83c8803457853061495493b5a71"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.11"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"certifi": {
"hashes": [
"sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8",
"sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"
],
"markers": "python_version >= '3.6'",
"version": "==2024.8.30"
},
"charset-normalizer": {
"hashes": [
"sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621",
"sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6",
"sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8",
"sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912",
"sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c",
"sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b",
"sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d",
"sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d",
"sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95",
"sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e",
"sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565",
"sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64",
"sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab",
"sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be",
"sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e",
"sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907",
"sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0",
"sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2",
"sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62",
"sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62",
"sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23",
"sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc",
"sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284",
"sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca",
"sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455",
"sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858",
"sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b",
"sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594",
"sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc",
"sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db",
"sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b",
"sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea",
"sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6",
"sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920",
"sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749",
"sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7",
"sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd",
"sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99",
"sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242",
"sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee",
"sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129",
"sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2",
"sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51",
"sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee",
"sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8",
"sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b",
"sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613",
"sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742",
"sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe",
"sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3",
"sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5",
"sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631",
"sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7",
"sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15",
"sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c",
"sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea",
"sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417",
"sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250",
"sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88",
"sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca",
"sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa",
"sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99",
"sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149",
"sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41",
"sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574",
"sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0",
"sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f",
"sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d",
"sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654",
"sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3",
"sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19",
"sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90",
"sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578",
"sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9",
"sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1",
"sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51",
"sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719",
"sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236",
"sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a",
"sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c",
"sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade",
"sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944",
"sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc",
"sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6",
"sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6",
"sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27",
"sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6",
"sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2",
"sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12",
"sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf",
"sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114",
"sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7",
"sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf",
"sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d",
"sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b",
"sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed",
"sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03",
"sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4",
"sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67",
"sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365",
"sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a",
"sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748",
"sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b",
"sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079",
"sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==3.4.0"
},
"idna": {
"hashes": [
"sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
"sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
],
"markers": "python_version >= '3.6'",
"version": "==3.10"
},
"requests": {
"hashes": [
"sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
"sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.32.3"
},
"urllib3": {
"hashes": [
"sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
"sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"
],
"markers": "python_version >= '3.8'",
"version": "==2.2.3"
}
},
"develop": {}
}

145
tools/format.py Normal file
View File

@@ -0,0 +1,145 @@
import glob
import os
import shlex
import subprocess
import sys
# required clang-format version
REQUIRED_VERSION = "18.1.3"
def check_clang_format_version():
"""
Check if the installed clang-format version matches the required version.
Raises:
SystemExit: If the version does not match the required version or if
there is an error checking the version.
"""
try:
result = subprocess.run(
['clang-format', '--version'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True
)
version_out = result.stdout.strip().split()
version_line = '0.0.0'
is_next = False
for vo in version_out:
if vo == 'version':
is_next = True
continue
if is_next:
version_line = vo
break
if version_line != REQUIRED_VERSION:
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}")
sys.exit(1)
def format_files(dry_run):
"""
Format .h and .cpp files in specified directories using clang-format.
Args:
dry_run (bool): If True, performs a dry run to check for formatting
issues without modifying files. If False, formats
the files in place.
Raises:
subprocess.CalledProcessError: If there is an error running clang-format
during the actual formatting process.
"""
patterns = [
"bench/**/*.h",
"bench/**/*.cpp",
"include/**/*.h",
"tests/**/*.h",
"tests/**/*.cpp",
]
files_to_format = []
for pattern in patterns:
matched_files = glob.glob(pattern, recursive=True)
files_to_format.extend(matched_files)
if not 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()
if dry_run:
# Check for changes without modifying the files
command = f'clang-format --style=file --dry-run --Werror {patterns_arg}'
result = subprocess.run(
shlex.split(command),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
cwd=cwd
)
if result.returncode != 0:
print("Files that need formatting:")
print(result.stdout)
print("Error output:")
print(result.stderr)
sys.exit(1)
else:
print("no changes found")
else:
# Format the files in place
command = f'clang-format --style=file -i {patterns_arg}'
result = subprocess.run(
shlex.split(command),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
cwd=cwd
)
if result.returncode != 0:
print("Error formatting files:")
print(result.stderr)
sys.exit(1)
else:
print('formatting done')
def main():
"""
Main function to handle command-line arguments and invoke formatting.
Checks for the required command-line argument, verifies the clang-format
version, and calls the format_files function to format the code.
"""
if len(sys.argv) != 2:
print(
"Usage: python format.py <dry_run|format>"
)
sys.exit(1)
else:
print(f"Running format with {sys.argv[1]}")
dry_run = False
if sys.argv[1] == "dry_run":
dry_run = True
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__":
main()

View File

@@ -0,0 +1,155 @@
#!/bin/python
#
# maddy update dependencies
# This project is licensed under the MIT license. For more information see the
# LICENSE file.
import os
import re
import requests
import sys
def get_cmake_files(directory, ignored_dirs=None):
"""
Recursively searches for all CMakeLists.txt files in the specified directory,
ignoring specified subdirectories.
Args:
directory (str): The path to the directory to search for CMakeLists.txt files.
ignored_dirs (list): A list of directory names to ignore during the search.
Returns:
list: A list of full paths to all found CMakeLists.txt files.
"""
cmakelists_paths = []
ignored_dirs = ignored_dirs or []
for root, dirs, files in os.walk(directory):
# 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"))
return cmakelists_paths
def get_last_dependency_version(url):
"""
Retrieves the latest release version tag from a specified GitHub repository.
Args:
url (str): The URL of the GitHub repository in the format
'https://github.com/owner/repo.git' or 'https://github.com/owner/repo'.
Returns:
str: The latest release version tag (e.g., 'v1.2.3') if found,
or raises an Exception if the repository is not found or
if there is an error in the API request.
Raises:
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}")
owner = parts[3]
repo = parts[4]
# GitHub API endpoint for releases
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}")
def get_current_version_from_fetch_content(cmake_code):
"""
Extracts the currently used Git tag from a FetchContent call in CMake code.
Args:
cmake_code (str): The CMake code containing the FetchContent call.
Returns:
str: The Git tag used in the FetchContent call, or None if not found.
"""
# Regular expression to match FetchContent_Declare and capture the GIT_TAG argument
pattern = r'FetchContent_Declare\s*\(\s*[^)]+\s*GIT_TAG\s+([^\s)]+)'
match = re.search(pattern, cmake_code)
if match:
return match.group(1) # Return the captured Git tag
return None
def update_fetch_content_versions(cmake_file_path):
"""
Updates the FetchContent blocks in a CMakeLists.txt file to use the latest
version from the corresponding GitHub repositories.
Args:
cmake_file_path (str): The path to the CMakeLists.txt file to be updated.
"""
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)
if repo_match:
repo_url = repo_match.group(1)
current_version = get_current_version_from_fetch_content(block)
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
def main():
"""
Main function to update FetchContent versions in CMakeLists.txt files.
It takes a directory path as an argument and processes all CMakeLists.txt files found,
ignoring specified directories.
"""
if len(sys.argv) < 2:
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.")
sys.exit(1)
cmake_files = get_cmake_files(directory_path, ignored_dirs)
for cmake_file in cmake_files:
print(f"Updating {cmake_file}...")
update_fetch_content_versions(cmake_file)
print(f"Updated {cmake_file} successfully.")
if __name__ == "__main__":
main()