60 Commits

Author SHA1 Message Date
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
Petra Baranski
7c6e32f4b1 Merge pull request #46 from progsource/version-1.2.1
chore: update version to 1.2.1
2023-08-06 13:35:51 +02:00
Petra Baranski
231785ff2d chore: update version to 1.2.1 2023-08-06 13:31:18 +02:00
Petra Baranski
09229aae0d Merge pull request #45 from Ivansstyle/fix_version_define
Refactored version() function in Parser class due to clashes with #define VERSION in various projects
2023-08-01 18:38:12 +02:00
Ivans Saponenko
4656252374 Edit branch due to Contribution Guidelines 2023-08-01 11:42:42 +03:00
Ivans Saponenko
9bcb7ce6dd Refactored version() function in Parser class due to clashes with defines 2023-08-01 11:19:31 +03:00
Petra Baranski
cc7f95f4c1 fix: cmake fails to create zip file 2023-07-27 19:22:23 +02:00
Petra Baranski
d203e8502c docs: fix version in README.md 2023-07-27 19:11:29 +02:00
Petra Baranski
7624810374 fix: markdown-bug-report template 2023-07-27 19:09:50 +02:00
Petra Baranski
5dd974cca1 chore: fix cpp-bug-report template 2023-07-27 19:08:21 +02:00
Petra Baranski
6015b0c9e9 Merge pull request #43 from progsource/version-1.2.0
Version 1.2.0
2023-07-27 19:05:08 +02:00
Petra Baranski
155fb2c7e6 docs: update changelog for 1.2.0 2023-07-27 18:55:20 +02:00
Petra Baranski
123b921f2a style: make regex strings more readable 2023-07-27 18:48:03 +02:00
Petra Baranski
aecb1b30e6 chore: have prettier issue templates 2023-07-27 18:48:03 +02:00
Petra Baranski
baa5c9ccd0 ci: create release workflow 2023-07-27 18:48:03 +02:00
Petra Baranski
02d3ccaf22 docs: update version number 2023-07-27 18:47:50 +02:00
Petra Baranski
bf64f3e3dc Merge pull request #42 from progsource/latex-support
Latex support
2023-07-27 15:34:47 +02:00
Petra Baranski
9090c41709 chore: remove possible vscode files via gitignore 2023-07-27 14:52:08 +02:00
Petra Baranski
01d1e48d11 feat: add optional latex block support 2023-07-27 14:51:56 +02:00
Petra Baranski
f0c282e0c0 docs: update info about code block with class 2023-07-25 22:23:02 +02:00
Petra Baranski
cbcef933e1 Merge pull request #41 from progsource/codeblock-parser-language-class
Codeblock parser language class
2023-07-24 20:40:57 +02:00
Petra Baranski
a1001cb991 feat: add class to block code 2023-07-24 20:35:05 +02:00
Petra Baranski
d23ba23a4c docs: update changelog with last merged PR changes 2023-07-24 20:19:18 +02:00
Petra Baranski
d12186af8a Merge pull request #40 from progsource/advanced_config
feat: add config options to en-/disable each parser
2023-07-23 17:56:27 +02:00
Petra Baranski
41396ab246 feat: add config options to en-/disable each parser
Also fix cmake line, so that ctest can find the test executable;
update readme.
2023-07-23 17:51:03 +02:00
Petra Baranski
51e1813373 Merge pull request #39 from progsource/build_update
Use GitHub workflow instead of external tools.

Update cmake and gtest and add gtest via cmake instead
of github submodule.
2023-07-23 09:02:39 +02:00
Petra Baranski
823645995e ci: use github workflow instead of travis and appveyor 2023-07-23 08:51:10 +02:00
Petra Baranski
87ec259c28 build: add option for running tests
cmake configuration for running tests is now in the
tests folder.

Add option in main cmake file that has to be set to
ON and only build the tests in that case.

Update appveyor and travis ci configurations accordingly.
2023-07-23 06:04:34 +02:00
Petra Baranski
6dd47f5de5 build: move gtest into cmake and up cmake min version
cmake minimum required version is now 3.25.

Instead of loading gtest via git submodule, it is now loaded
in the cmake files.

gtest version upped to v1.13.0.
2023-07-23 05:37:11 +02:00
Petra Baranski
f3d934d6ec Merge pull request #35 from quitesimpleorg/fix/add_static_italic
italicparser: Parse(): Add static keyword to regex
2021-04-18 20:40:11 +02:00
Albert S
a28769be2b italicparser: Parse(): Add static keyword to regex
In line with the other parsers, add the static keyword to the
regex.
2021-04-18 20:24:26 +02:00
Petra Baranski
adb1a910d4 fixed spelling in README 2020-10-10 08:11:48 +02:00
Petra Baranski
f38b3cf4fa cleaned up Changelog colors 2020-10-10 08:08:35 +02:00
Petra Baranski
6b632abd44 Added CHANGELOG and CONTRIBUTING 2020-10-10 08:03:21 +02:00
Petra Baranski
38f802de09 updated version 2020-10-04 19:03:44 +02:00
Petra Baranski
348aa81607 Improved cmake setup 2020-10-04 19:02:39 +02:00
Petra Baranski
ba5cb5d6c5 Merge pull request #34 from solodolo/numeric-list
orderedlistparser: Add parsing support for fully numeric markdown lists
2020-10-04 18:40:57 +02:00
Petra Baranski
fd698d1f5f Merge branch 'master' into numeric-list 2020-10-04 18:31:29 +02:00
Petra Baranski
5b2f20041c Merge pull request #30 from eklitzke/istream
make Parser::Parse accept istreams instead of stringstream
2020-10-04 18:21:25 +02:00
Drew Mettlach
cde0137e90 orderedlistparser: Add parsing support for fully numeric markdown lists 2020-10-03 17:22:21 -05:00
Evan Klitzke
71ee49d1ea make Parser::Parse accept istreams instead of stringstream 2020-07-12 11:30:41 -07:00
Petra Baranski
19338d2b56 Merge pull request #28 from martin357/master
Added another character for bullet point("-", "+")
2020-02-08 07:54:56 +01:00
Martin Kopecky
cb75226b4a *, + and - are equivalent for making unordered bullet lists as per https://spec-md.com/#sec-Lists
Modified tests and documentation to reflect that.
2020-02-03 22:52:57 +01:00
Martin Kopecký
51d61b68fe Added another character for bullet point("-") 2020-01-30 17:38:55 +01:00
73 changed files with 2214 additions and 771 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
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

View File

@@ -0,0 +1,65 @@
name: C++ Bug Report
description: File a bug report regarding C++ problems
title: "[Bug][C++]: "
labels: ["bug", "triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: input
id: os
attributes:
label: Operating System
description: On which OS are you running maddy?
placeholder: ex. Windows/Linux/OSX
validations:
required: true
- type: input
id: compiler
attributes:
label: Compiler
description: Which compiler do you use?
placeholder: ex. mingw/Visual Studio/clang
validations:
required: true
- type: input
id: compiler_flags
attributes:
label: Compiler flags
description: Which compiler flags do you use?
placeholder: ex. -fno-rtti
validations:
required: true
- type: dropdown
id: maddy_version
attributes:
label: maddy version
description: What version of maddy are you using?
options:
- 1.3.0 (latest)
- 1.2.1
- 1.2.0
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
validations:
required: true
- type: textarea
id: example
attributes:
label: Minimal C++ example
description: To be able to reproduce your issue, please give some example C++ code which creates problems.
validations:
required: true
- type: textarea
id: whats-wrong
attributes:
label: What is not working? What did you try?
description: Also, what did you expect to happen?
validations:
required: true

View File

@@ -0,0 +1,15 @@
name: Feature Request
description: Missing some feature?
labels: ["feature"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to create a feature request!
- type: textarea
id: feature-description
attributes:
label: What are you missing in maddy?
description: If you want some extra Markdown supported, please also write a Markdown example and an expected HTML output.
validations:
required: true

View File

@@ -0,0 +1,65 @@
name: Markdown Bug Report
description: File a bug report regarding Markdown problems
title: "[Bug][Markdown]: "
labels: ["bug", "triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: input
id: os
attributes:
label: Operating System
description: On which OS are you running maddy?
placeholder: ex. Windows/Linux/OSX
validations:
required: true
- type: input
id: compiler
attributes:
label: Compiler
description: Which compiler do you use?
placeholder: ex. mingw/Visual Studio/clang
validations:
required: true
- type: input
id: compiler_flags
attributes:
label: Compiler flags
description: Which compiler flags do you use?
placeholder: ex. -fno-rtti
validations:
required: true
- type: dropdown
id: maddy_version
attributes:
label: maddy version
description: What version of maddy are you using?
options:
- 1.3.0 (latest)
- 1.2.1
- 1.2.0
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
validations:
required: true
- type: textarea
id: example
attributes:
label: Minimal Mardown example
description: To be able to reproduce your issue, please give some example Markdown which creates problems. Please indent the Markdown by 4 spaces.
validations:
required: true
- type: textarea
id: whats-wrong
attributes:
label: What is not working? What did you try?
description: Also, what did you expect to happen?
validations:
required: true

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"

View File

@@ -0,0 +1,34 @@
name: release
permissions:
contents: write
on:
push:
tags:
- '*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
ninjaVersion: "^1.11.1" # <--= optional, use most recent 1.x version
- name: create zip
run: |
mkdir build
mkdir tmp
cd tmp
cmake -DMADDY_CREATE_PACKAGE=ON ..
make maddy_package
- name: create release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/maddy-src.zip
tag: ${{ github.ref }}
body: "You can find all changes of this release in the [changelog](https://github.com/progsource/maddy/blob/master/CHANGELOG.md)"

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

@@ -0,0 +1,25 @@
name: run-checks
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

62
.github/workflows/run-tests.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: run-tests
run-name: test ${{ github.ref }}
on:
pull_request:
push:
branches:
- master
- dev
jobs:
test-on-ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
ninjaVersion: "^1.11.1" # <--= optional, use most recent 1.x version
- name: build
run: |
mkdir tmp
cd tmp
cmake -DMADDY_BUILD_WITH_TESTS=ON ..
make -j4
- name: run tests
run: |
./build/MaddyTests
test-on-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
ninjaVersion: "^1.11.1" # <--= optional, use most recent 1.x version
- name: build
run: |
mkdir tmp
cd tmp
cmake -G "Visual Studio 17 2022" -A x64 -DMADDY_BUILD_WITH_TESTS=ON ..
cmake --build . --config Debug
- name: run tests
run: |
./build/Debug/MaddyTests.exe
test-on-osx:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
ninjaVersion: "^1.11.1" # <--= optional, use most recent 1.x version
- name: build
run: |
mkdir tmp
cd tmp
cmake -DMADDY_BUILD_WITH_TESTS=ON ..
make -j4
- name: run tests
run: |
./build/MaddyTests

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 }}

4
.gitignore vendored
View File

@@ -161,10 +161,6 @@ tags
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history
### Xcode ###

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "libs/gtest"]
path = libs/gtest
url = https://github.com/google/googletest.git

View File

@@ -1,32 +0,0 @@
sudo: false
language: cpp
matrix:
include:
- os: linux
dist: xenial
sudo: require
addons:
apt:
sources:
- sourceline: 'ppa:ubuntu-toolchain-r/test'
packages:
- g++-7
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- os: osx
osx_image: xcode10
compiler: clang
env:
- MATRIX_EVAL="CC=clang && CXX=clang++"
before_install:
# This is necessary to solve https://github.com/travis-ci/travis-ci/issues/9649
- eval "${MATRIX_EVAL}"
script:
- mkdir tmp
- cd tmp
- cmake ..
- make
- ../build/MaddyTests

View File

@@ -6,3 +6,8 @@ a license to everyone to use it as detailed in LICENSE.)
M. Petra Baranski (info@progsource.de)
Patrick José Pereira (patrickelectric@gmail.com)
Martin Kopecky (martin.kopecky357@gmail.com)
Andrew Mettlach (dmmettlach@gmail.com)
Evan Klitzke (evan@eklitzke.org)
Albert Schwarzkopf (dev-maddy@quitesimple.org)
Ivans Saponenko (ivans.saponenko+maddy@gmail.com)

91
CHANGELOG.md Normal file
View File

@@ -0,0 +1,91 @@
# Changelog
This file tries to follow roughly [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
maddy uses [semver versioning](https://semver.org/).
## Badges
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) for any bug fixes.
* ![**SECURITY**](https://img.shields.io/badge/-SECURITY-%23c00) in case of vulnerabilities.
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) for new features.
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) for changes in existing functionality.
* ![**DEPRECATED**](https://img.shields.io/badge/-DEPRECATED-%23666) for soon-to-be removed features.
* ![**REMOVED**](https://img.shields.io/badge/-REMOVED-%23900) for now removed features.
## Upcoming
* ![**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
## 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
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Parser.h version() method clashing with VERSION defines at global scope
## version 1.2.0 2023-07-27
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added Changelog
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added contribution guideline
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) updated cmake minimum required version to 3.25
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) gtest is now loaded via cmake and not a git submodule any longer - updated gtest version to 1.13.0
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) tests are only run if the cmake option `MADDY_BUILD_WITH_TESTS` is on, moved test cmake code to the `tests` subfolder
* ![**REMOVED**](https://img.shields.io/badge/-REMOVED-%23900) travis CI and appveyor
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) GitHub workflow for tests
* ![**DEPRECATED**](https://img.shields.io/badge/-DEPRECATED-%23666) config flags `isEmphasizedParserEnabled` and `isHTMLWrappedInParagraph`
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) config flag `enabledParsers` to en-/disable each parser separately
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) class attribute to code blocks if there is text after the three backticks like ` ```cpp`
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) optional support for latex blocks - it's off by default
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) version info to the parser class
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) GitHub workflow for release, so that one can include maddy easier via cmake's `FetchContent`
## version 1.1.2 2020-10-04
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) `*`, `+` and `-` are equivalent for making unordered bullet list
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Parsing support for fully numeric ordered lists
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) make `Parser::Parse` accept istreams instead of stringstream
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) CMake is creating an interface library which you can include in your own `target_link_libraries` and the global include path is untouched from maddy.
## version 1.1.1 2019-12-27
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) BreakLineParser
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) HTMLParser
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added optional config with the following options:
* en-/disable the emphasized parser
* wrap/not wrap HTML in markdown within a paragraph in output
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) Updated gtest to release-1.10.0 to fix build issues
## version 1.1.0 2019-02-19
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Added missing includes to BlockParser
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Added missing dtor to BlockParser and LineParser
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) `__test__` can also be used to get `<strong>text</strong>`
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added AppVeyor CI
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added clang for CI
* ![**CHANGED**](https://img.shields.io/badge/-CHANGED-%23e90) Single underscore `_` results in emphasized tag `<em>`, single `*` in italic tag `<i>`
## version 1.0.3 2018-01-18
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Make sure that all parsers are finished
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) ol documentation
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added Travic-CI with gcc
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added Howto for running the tests on the README
## version 1.0.2 2017-12-26
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Fixed inline code for directly following letters (bold, emphasized and strikethrough)
## version 1.0.1 2017-12-25
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Fixed inline code for bold, emphasized and strikethrough
* ![**FIXED**](https://img.shields.io/badge/-FIXED-%23090) Fixed spelling in README
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Use Gold Linker on Unix if available for faster compile time
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) Added Github ISSUE_TEMPLATE
## version 1.0.0 2017-12-25
initial release

View File

@@ -1,17 +1,10 @@
# This project is licensed under the MIT license. For more information see the
# LICENSE file.
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.25)
project(maddy)
enable_testing()
# ------------------------------------------------------------------------------
set(MADDY_CPP_VERSION 14)
add_definitions(-DCPP_VERSION=${MADDY_CPP_VERSION})
# ------------------------------------------------------------------------------
set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build)
@@ -20,58 +13,49 @@ set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})
# ------------------------------------------------------------------------------
option(MADDY_BUILD_WITH_TESTS "enable building tests - does not work with zip download" OFF)
if(${MADDY_BUILD_WITH_TESTS})
enable_testing()
endif()
option(MADDY_CREATE_PACKAGE "create a package for a version release" OFF)
# ------------------------------------------------------------------------------
set(MADDY_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
file(GLOB_RECURSE MADDY_TESTS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/maddy/*.cpp)
# ------------------------------------------------------------------------------
if (UNIX)
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -g -std=c++${MADDY_CPP_VERSION} -Wall -Wpedantic -Wextra -Wno-ignored-qualifiers -fno-rtti -fno-exceptions -fsanitize=address -fno-omit-frame-pointer"
)
else()
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++${MADDY_CPP_VERSION}"
)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(${CMAKE_CXX_STANDARD} LESS 14)
message(FATAL_ERROR "maddy requires >=C++14")
endif()
# ------------------------------------------------------------------------------
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()
# ------------------------------------------------------------------------------
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/gtest/googlemock)
add_subdirectory(libs)
# ------------------------------------------------------------------------------
include_directories(
${LIBS_INCLUDE_DIRS}
add_library(maddy INTERFACE)
target_include_directories(maddy INTERFACE
${MADDY_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/tests
)
# ------------------------------------------------------------------------------
add_executable(
MaddyTests
${MADDY_TESTS_FILES}
${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp
)
target_link_libraries(MaddyTests gmock_main)
add_test(MaddyTests ${CMAKE_CURRENT_SOURCE_DIR}/build/MaddyTests)
if(${MADDY_BUILD_WITH_TESTS})
add_subdirectory(tests)
endif()
# ------------------------------------------------------------------------------
if(${MADDY_CREATE_PACKAGE})
set(MADDY_PACKAGE_FILES include/ CMakeLists.txt LICENSE)
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}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${MADDY_PACKAGE_FILES})
add_custom_target(${PROJECT_NAME}_package DEPENDS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-src.zip)
endif()

26
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,26 @@
# Contribution Guideline
First of all: I am thankful for any contribution this project gets.
## Creating Issues
You found a bug, you miss some feature in the project or have an idea how to
improve the code? Then [create a GitHub issue](https://github.com/progsource/maddy/issues/new).
## Creating Pull-Requests
* Use a branch other than master.
* Add yourself to the `AUTHORS` file.
* Try to stick with the code style the files are having right now.
* 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:
```
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.
* Update documentation of the Markdown syntax if anything changed there. (`docs/definitions.md`)
* Add a changelog entry at "Upcoming" inside of `CHANGELOG.md`
* Make sure, that the tests are successful.

View File

@@ -1,17 +0,0 @@
## Minimal Code Example
```
```
## Conditions
. | .
--------------------- | ------------------
**Operating System:** | ?
**Compiler:** | ?
**Compiler flags:** | ?
**maddy version:** | ?
## Description
What did you try? What is not working?

View File

@@ -1,4 +1,4 @@
Copyright 2017, 2018, 2019 M. Petra Baranski
Copyright 2017, 2018, 2019, 2020, 2023 M. Petra Baranski
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

View File

@@ -1,9 +1,7 @@
# maddy
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Version: 1.1.1](https://img.shields.io/badge/Version-1.1.1-brightgreen.svg)](https://semver.org/)
[![Travis Build Status](https://travis-ci.org/progsource/maddy.svg?branch=master)](https://travis-ci.org/progsource/maddy)
[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/04m0lg27kigv1pg8/branch/master?svg=true)](https://ci.appveyor.com/project/progsource/maddy/branch/master)
[![Version: 1.3.0](https://img.shields.io/badge/Version-1.3.0-brightgreen.svg)](https://semver.org/)
maddy is a C++ Markdown to HTML **header-only** parser library.
@@ -15,7 +13,7 @@ It is tested to work on:
* Linux (gcc)
* OSX (clang)
* Windows (Visual Studio 2017)
* Windows (Visual Studio 17 2022, mingw)
## Dependencies
@@ -23,13 +21,40 @@ It is tested to work on:
## Why maddy?
When I was needing a Markdown parser in C++ I couldn't find any, that was
When I was looking for a Markdown parser in C++, I couldn't find any, that was
fitting my needs. So I simply wrote my own one.
## Markdown syntax
The supported syntax can be found in the [definitions docs](docs/definitions.md).
## How to add maddy to your cmake project
You can use [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html)
which was introduced in CMake 3.11.
This way you can add
```cmake
include(FetchContent)
FetchContent_Declare(
maddy
URL https://github.com/progsource/maddy/.../maddy-src.zip
)
FetchContent_MakeAvailable(maddy)
add_executable(my_exe)
target_link_libraries(my_exe PUBLIC maddy)
```
to your CMake file to make it work. Check the
[release](https://github.com/progsource/maddy/releases) for the full
zip-file-url.
The zip only contains a `CMakeLists.txt`, the `include` folder and the `LICENSE`
file.
## How to use
To use maddy in your project, simply add the include path of maddy to yours
@@ -45,13 +70,18 @@ std::stringstream markdownInput("");
// config is optional
std::shared_ptr<maddy::ParserConfig> config = std::make_shared<maddy::ParserConfig>();
config->isEmphasizedParserEnabled = true; // default
config->isHTMLWrappedInParagraph = true; // default
// config->isEmphasizedParserEnabled = false; // default true - this flag is deprecated
// config->isHTMLWrappedInParagraph = false; // default true - this flag is deprecated
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::string htmlOutput = parser->Parse(markdownInput);
```
You can find all parser flags in
[`include/maddy/parserconfig.h`](include/maddy/parserconfig.h).
## How to run the tests
*(tested on Linux with
@@ -63,10 +93,9 @@ Open your preferred terminal and type:
```shell
git clone https://github.com/progsource/maddy.git
cd maddy
git submodule update --init --recursive
mkdir tmp
cd tmp
cmake ..
cmake -DMADDY_BUILD_WITH_TESTS=ON ..
make
make test # or run the executable in ../build/MaddyTests
```
@@ -76,5 +105,6 @@ make test # or run the executable in ../build/MaddyTests
There are different possibilities:
* [Create a GitHub issue](https://github.com/progsource/maddy/issues/new)
* Create a pull request with an own branch (don't forget to put yourself in the
AUTHORS file)
* Create a pull request with an own branch
Please also read [CONTRIBUTING.md](CONTRIBUTING.md).

View File

@@ -1,15 +0,0 @@
image: Visual Studio 2017
install:
- cmd: git submodule update --init --recursive
before_build:
- cmd: mkdir tmp
- cmd: cd tmp
- cmd: cmake -G "Visual Studio 15 Win64" ..
build:
project: $(APPVEYOR_BUILD_FOLDER)\tmp\$(APPVEYOR_PROJECT_NAME).sln
test_script:
- cmd: ctest -VV -C "Debug"

View File

@@ -44,11 +44,13 @@ results in
## Lists
### unordered
Characters "*", "+" or "-" to make an unordered "bullet" list are equivalent.
```
* unordered
- unordered
* list
* items
+ items
```
results in
@@ -66,8 +68,8 @@ results in
* list
* items
* in
* an
* hierarchy
+ an
- hierarchy
```
results in
@@ -92,6 +94,26 @@ results in
```
1. ordered
2. list
3. items
```
results in
```html
<ol>
<li>ordered</li>
<li>list</li>
<li>items</li>
</ol>
```
```
1. ordered
* list
* items
@@ -198,6 +220,18 @@ results in
<pre><code>
some code
</code></pre>
```
```cpp
int a = 42;
```
results in
```html
<pre class="cpp"><code>
int a = 42;
</code></pre>
```
## Inline code
@@ -342,3 +376,29 @@ becomes
</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
```

View File

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

View File

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

View File

@@ -31,11 +31,13 @@ public:
*
* @method
* @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(
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)
, isStarted(false)
@@ -51,10 +53,9 @@ public:
* @param {const std::string&} line
* @return {bool}
*/
static bool
IsStartingLine(const std::string& line)
static bool IsStartingLine(const std::string& line)
{
static std::regex re("^- \\[[x| ]\\] .*");
static std::regex re(R"(^- \[[x| ]\] .*)");
return std::regex_match(line, re);
}
@@ -64,27 +65,14 @@ public:
* @method
* @return {bool}
*/
bool
IsFinished() const override
{
return this->isFinished;
}
bool IsFinished() const override { return this->isFinished; }
protected:
bool
isInlineBlockAllowed() const override
{
return true;
}
bool isInlineBlockAllowed() const override { return true; }
bool
isLineParserAllowed() const override
{
return true;
}
bool isLineParserAllowed() const override { return true; }
void
parseBlock(std::string& line) override
void parseBlock(std::string& line) override
{
bool isStartOfNewListItem = IsStartingLine(line);
uint32_t indentation = getIndentationWidth(line);
@@ -92,12 +80,13 @@ protected:
static std::regex lineRegex("^(- )");
line = std::regex_replace(line, lineRegex, "");
static std::regex emptyBoxRegex("^\\[ \\]");
static std::regex emptyBoxRegex(R"(^\[ \])");
static std::string emptyBoxReplacement = "<input type=\"checkbox\"/>";
line = std::regex_replace(line, emptyBoxRegex, emptyBoxReplacement);
static std::regex boxRegex("^\\[x\\]");
static std::string boxReplacement = "<input type=\"checkbox\" checked=\"checked\"/>";
static std::regex boxRegex(R"(^\[x\])");
static std::string boxReplacement =
"<input type=\"checkbox\" checked=\"checked\"/>";
line = std::regex_replace(line, boxRegex, boxReplacement);
if (!this->isStarted)
@@ -113,11 +102,9 @@ protected:
return;
}
if (
line.empty() ||
if (line.empty() ||
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;
this->isFinished = true;

View File

@@ -7,8 +7,8 @@
// -----------------------------------------------------------------------------
#include <functional>
#include <string>
#include <regex>
#include <string>
#include "maddy/blockparser.h"
@@ -47,11 +47,13 @@ public:
*
* @method
* @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(
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)
, isStarted(false)
@@ -71,10 +73,9 @@ public:
* @param {const std::string&} line
* @return {bool}
*/
static bool
IsStartingLine(const std::string& line)
static bool IsStartingLine(const std::string& line)
{
static std::regex re("^(?:`){3}$");
static std::regex re("^(?:`){3}(.*)$");
return std::regex_match(line, re);
}
@@ -84,27 +85,14 @@ public:
* @method
* @return {bool}
*/
bool
IsFinished() const override
{
return this->isFinished;
}
bool IsFinished() const override { return this->isFinished; }
protected:
bool
isInlineBlockAllowed() const override
{
return false;
}
bool isInlineBlockAllowed() const override { return false; }
bool
isLineParserAllowed() const override
{
return false;
}
bool isLineParserAllowed() const override { return false; }
void
parseBlock(std::string& line) override
void parseBlock(std::string& line) override
{
if (line == "```")
{
@@ -123,6 +111,13 @@ protected:
return;
}
}
else if (!this->isStarted && line.substr(0, 3) == "```")
{
line = "<pre class=\"" + line.substr(3) + "\"><code>\n";
this->isStarted = true;
this->isFinished = false;
return;
}
line += "\n";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,124 @@
/*
* This project is licensed under the MIT license. For more information see the
* LICENSE file.
*/
#pragma once
// -----------------------------------------------------------------------------
#include <functional>
#include <regex>
#include <string>
#include "maddy/blockparser.h"
// -----------------------------------------------------------------------------
namespace maddy {
// -----------------------------------------------------------------------------
/**
* LatexBlockParser
*
* Support for https://www.mathjax.org/
* Be aware, that if you want to make MathJax work, you need also their
* JavaScript library added to your HTML code.
* maddy does not itself add that code to be more flexible in how you write your
* head and full body.
*
* From Markdown: `$$` surrounded text
*
* ```
* $$some formula
* $$
* ```
*
* To HTML:
*
* ```
* $$some formula
* $$
* ```
*
* @class
*/
class LatexBlockParser : public BlockParser
{
public:
/**
* ctor
*
* @method
* @param {std::function<void(std::string&)>} parseLineCallback
* @param {std::function<std::shared_ptr<BlockParser>(const std::string&
* line)>} getBlockParserForLineCallback
*/
LatexBlockParser(
std::function<void(std::string&)> parseLineCallback,
std::function<std::shared_ptr<BlockParser>(const std::string& line)>
getBlockParserForLineCallback
)
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false)
, isFinished(false)
{}
/**
* IsStartingLine
*
* If the line starts with two dollars, then it is a latex block.
*
* ```
* $$
* ```
*
* @method
* @param {const std::string&} line
* @return {bool}
*/
static bool IsStartingLine(const std::string& line)
{
static std::regex re(R"(^(?:\$){2}(.*)$)");
return std::regex_match(line, re);
}
/**
* IsFinished
*
* @method
* @return {bool}
*/
bool IsFinished() const override { return this->isFinished; }
protected:
bool isInlineBlockAllowed() const override { return false; }
bool isLineParserAllowed() const override { return false; }
void parseBlock(std::string& line) override
{
if (!this->isStarted && line.substr(0, 2) == "$$")
{
this->isStarted = true;
this->isFinished = false;
}
if (this->isStarted && !this->isFinished && line.size() > 1 &&
line.substr(line.size() - 2, 2) == "$$")
{
this->isFinished = true;
this->isStarted = false;
}
line += "\n";
}
private:
bool isStarted;
bool isFinished;
}; // class LatexBlockParser
// -----------------------------------------------------------------------------
} // namespace maddy

View File

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

View File

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

View File

@@ -30,15 +30,19 @@ public:
*
* @method
* @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(
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
)
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
, isStarted(false)
, isFinished(false)
, isEnabled(isEnabled)
{}
/**
@@ -52,11 +56,7 @@ public:
* @param {const std::string&} line
* @return {bool}
*/
static bool
IsStartingLine(const std::string& line)
{
return !line.empty();
}
static bool IsStartingLine(const std::string& line) { return !line.empty(); }
/**
* IsFinished
@@ -66,41 +66,40 @@ public:
* @method
* @return {bool}
*/
bool
IsFinished() const override
{
return this->isFinished;
}
bool IsFinished() const override { return this->isFinished; }
protected:
bool
isInlineBlockAllowed() const override
{
return false;
}
bool isInlineBlockAllowed() const override { return false; }
bool
isLineParserAllowed() const override
{
return true;
}
bool isLineParserAllowed() const override { return true; }
void
parseBlock(std::string& line) override
void parseBlock(std::string& line) override
{
if (!this->isStarted)
if (this->isEnabled && !this->isStarted)
{
line = "<p>" + line + " ";
this->isStarted = true;
return;
}
else if (!this->isEnabled && !this->isStarted)
{
line += " ";
this->isStarted = true;
return;
}
if (line.empty())
if (this->isEnabled && line.empty())
{
line += "</p>";
this->isFinished = true;
return;
}
else if (!this->isEnabled && line.empty())
{
line += "<br/>";
this->isFinished = true;
return;
}
line += " ";
}
@@ -108,6 +107,7 @@ protected:
private:
bool isStarted;
bool isFinished;
bool isEnabled;
}; // class ParagraphParser
// -----------------------------------------------------------------------------

View File

@@ -6,8 +6,8 @@
// -----------------------------------------------------------------------------
#include <memory>
#include <functional>
#include <memory>
#include <string>
#include "maddy/parserconfig.h"
@@ -18,6 +18,7 @@
#include "maddy/headlineparser.h"
#include "maddy/horizontallineparser.h"
#include "maddy/htmlparser.h"
#include "maddy/latexblockparser.h"
#include "maddy/orderedlistparser.h"
#include "maddy/paragraphparser.h"
#include "maddy/quoteparser.h"
@@ -50,6 +51,18 @@ namespace maddy {
class Parser
{
public:
/**
* Version info
*
* Check https://github.com/progsource/maddy/blob/master/CHANGELOG.md
* for the changelog.
*/
static const std::string& version()
{
static const std::string v = "1.3.0";
return v;
}
/**
* ctor
*
@@ -57,27 +70,76 @@ public:
*
* @method
*/
Parser(std::shared_ptr<ParserConfig> config = nullptr)
: config(config)
, breakLineParser(std::make_shared<BreakLineParser>())
, emphasizedParser(std::make_shared<EmphasizedParser>())
, imageParser(std::make_shared<ImageParser>())
, inlineCodeParser(std::make_shared<InlineCodeParser>())
, italicParser(std::make_shared<ItalicParser>())
, linkParser(std::make_shared<LinkParser>())
, strikeThroughParser(std::make_shared<StrikeThroughParser>())
, strongParser(std::make_shared<StrongParser>())
{}
Parser(std::shared_ptr<ParserConfig> config = nullptr) : config(config)
{
// deprecated backward compatibility
// will be removed in 1.4.0 latest including the booleans
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>();
}
if (!this->config ||
(this->config->enabledParsers & maddy::types::EMPHASIZED_PARSER) != 0)
{
this->emphasizedParser = std::make_shared<EmphasizedParser>();
}
if (!this->config ||
(this->config->enabledParsers & maddy::types::IMAGE_PARSER) != 0)
{
this->imageParser = std::make_shared<ImageParser>();
}
if (!this->config ||
(this->config->enabledParsers & maddy::types::INLINE_CODE_PARSER) != 0)
{
this->inlineCodeParser = std::make_shared<InlineCodeParser>();
}
if (!this->config ||
(this->config->enabledParsers & maddy::types::ITALIC_PARSER) != 0)
{
this->italicParser = std::make_shared<ItalicParser>();
}
if (!this->config ||
(this->config->enabledParsers & maddy::types::LINK_PARSER) != 0)
{
this->linkParser = std::make_shared<LinkParser>();
}
if (!this->config || (this->config->enabledParsers &
maddy::types::STRIKETHROUGH_PARSER) != 0)
{
this->strikeThroughParser = std::make_shared<StrikeThroughParser>();
}
if (!this->config ||
(this->config->enabledParsers & maddy::types::STRONG_PARSER) != 0)
{
this->strongParser = std::make_shared<StrongParser>();
}
}
/**
* Parse
*
* @method
* @param {const std::stringstream&} markdown
* @param {const std::istream&} markdown
* @return {std::string} HTML
*/
std::string
Parse(std::stringstream& markdown) const
std::string Parse(std::istream& markdown) const
{
std::string result = "";
std::shared_ptr<BlockParser> currentBlockParser = nullptr;
@@ -128,111 +190,159 @@ private:
std::shared_ptr<StrongParser> strongParser;
// block parser have to run before
void
runLineParser(std::string& line) const
void runLineParser(std::string& line) const
{
// Attention! ImageParser has to be before LinkParser
if (this->imageParser)
{
this->imageParser->Parse(line);
}
if (this->linkParser)
{
this->linkParser->Parse(line);
}
// Attention! StrongParser has to be before EmphasizedParser
if (this->strongParser)
{
this->strongParser->Parse(line);
}
if (!this->config || this->config->isEmphasizedParserEnabled)
if (this->emphasizedParser)
{
this->emphasizedParser->Parse(line);
}
if (this->strikeThroughParser)
{
this->strikeThroughParser->Parse(line);
this->inlineCodeParser->Parse(line);
this->italicParser->Parse(line);
this->breakLineParser->Parse(line);
}
std::shared_ptr<BlockParser>
getBlockParserForLine(const std::string& line) const
if (this->inlineCodeParser)
{
this->inlineCodeParser->Parse(line);
}
if (this->italicParser)
{
this->italicParser->Parse(line);
}
if (this->breakLineParser)
{
this->breakLineParser->Parse(line);
}
}
std::shared_ptr<BlockParser> getBlockParserForLine(const std::string& line
) const
{
std::shared_ptr<BlockParser> parser;
if (maddy::CodeBlockParser::IsStartingLine(line))
if ((!this->config || (this->config->enabledParsers &
maddy::types::CODE_BLOCK_PARSER) != 0) &&
maddy::CodeBlockParser::IsStartingLine(line))
{
parser = std::make_shared<maddy::CodeBlockParser>(
nullptr,
nullptr
);
parser = std::make_shared<maddy::CodeBlockParser>(nullptr, nullptr);
}
else if (maddy::HeadlineParser::IsStartingLine(line))
else if (this->config &&
(this->config->enabledParsers & maddy::types::LATEX_BLOCK_PARSER
) != 0 &&
maddy::LatexBlockParser::IsStartingLine(line))
{
parser = std::make_shared<LatexBlockParser>(nullptr, nullptr);
}
else if ((!this->config || (this->config->enabledParsers &
maddy::types::HEADLINE_PARSER) != 0) &&
maddy::HeadlineParser::IsStartingLine(line))
{
if (!this->config || this->config->isHeadlineInlineParsingEnabled)
{
parser = std::make_shared<maddy::HeadlineParser>(
[this](std::string& line) { this->runLineParser(line); },
nullptr,
nullptr
true
);
}
else if (maddy::HorizontalLineParser::IsStartingLine(line))
else
{
parser = std::make_shared<maddy::HorizontalLineParser>(
nullptr,
nullptr
);
parser =
std::make_shared<maddy::HeadlineParser>(nullptr, nullptr, false);
}
else if (maddy::QuoteParser::IsStartingLine(line))
}
else if ((!this->config || (this->config->enabledParsers &
maddy::types::HORIZONTAL_LINE_PARSER) != 0) &&
maddy::HorizontalLineParser::IsStartingLine(line))
{
parser = std::make_shared<maddy::HorizontalLineParser>(nullptr, nullptr);
}
else if ((!this->config || (this->config->enabledParsers &
maddy::types::QUOTE_PARSER) != 0) &&
maddy::QuoteParser::IsStartingLine(line))
{
parser = std::make_shared<maddy::QuoteParser>(
[this](std::string& line){ this->runLineParser(line); },
[this](const std::string& line){ return this->getBlockParserForLine(line); }
[this](std::string& line) { this->runLineParser(line); },
[this](const std::string& line)
{ return this->getBlockParserForLine(line); }
);
}
else if (maddy::TableParser::IsStartingLine(line))
else if ((!this->config || (this->config->enabledParsers &
maddy::types::TABLE_PARSER) != 0) &&
maddy::TableParser::IsStartingLine(line))
{
parser = std::make_shared<maddy::TableParser>(
[this](std::string& line){ this->runLineParser(line); },
nullptr
[this](std::string& line) { this->runLineParser(line); }, nullptr
);
}
else if (maddy::ChecklistParser::IsStartingLine(line))
else if ((!this->config || (this->config->enabledParsers &
maddy::types::CHECKLIST_PARSER) != 0) &&
maddy::ChecklistParser::IsStartingLine(line))
{
parser = this->createChecklistParser();
}
else if (maddy::OrderedListParser::IsStartingLine(line))
else if ((!this->config || (this->config->enabledParsers &
maddy::types::ORDERED_LIST_PARSER) != 0) &&
maddy::OrderedListParser::IsStartingLine(line))
{
parser = this->createOrderedListParser();
}
else if (maddy::UnorderedListParser::IsStartingLine(line))
else if ((!this->config || (this->config->enabledParsers &
maddy::types::UNORDERED_LIST_PARSER) != 0) &&
maddy::UnorderedListParser::IsStartingLine(line))
{
parser = this->createUnorderedListParser();
}
else if (
this->config &&
!this->config->isHTMLWrappedInParagraph &&
maddy::HtmlParser::IsStartingLine(line)
)
else if (this->config &&
(this->config->enabledParsers & maddy::types::HTML_PARSER) != 0 &&
maddy::HtmlParser::IsStartingLine(line))
{
parser = std::make_shared<maddy::HtmlParser>(nullptr, nullptr);
}
else if (maddy::ParagraphParser::IsStartingLine(line))
{
parser = std::make_shared<maddy::ParagraphParser>(
[this](std::string& line){ this->runLineParser(line); },
nullptr
[this](std::string& line) { this->runLineParser(line); },
nullptr,
(!this->config ||
(this->config->enabledParsers & maddy::types::PARAGRAPH_PARSER) != 0)
);
}
return parser;
}
std::shared_ptr<BlockParser>
createChecklistParser() const
std::shared_ptr<BlockParser> createChecklistParser() const
{
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)
{
std::shared_ptr<BlockParser> parser;
if (maddy::ChecklistParser::IsStartingLine(line))
if ((!this->config || (this->config->enabledParsers &
maddy::types::CHECKLIST_PARSER) != 0) &&
maddy::ChecklistParser::IsStartingLine(line))
{
parser = this->createChecklistParser();
}
@@ -242,20 +352,24 @@ private:
);
}
std::shared_ptr<BlockParser>
createOrderedListParser() const
std::shared_ptr<BlockParser> createOrderedListParser() const
{
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)
{
std::shared_ptr<BlockParser> parser;
if (maddy::OrderedListParser::IsStartingLine(line))
if ((!this->config || (this->config->enabledParsers &
maddy::types::ORDERED_LIST_PARSER) != 0) &&
maddy::OrderedListParser::IsStartingLine(line))
{
parser = this->createOrderedListParser();
}
else if (maddy::UnorderedListParser::IsStartingLine(line))
else if ((!this->config || (this->config->enabledParsers &
maddy::types::UNORDERED_LIST_PARSER) != 0
) &&
maddy::UnorderedListParser::IsStartingLine(line))
{
parser = this->createUnorderedListParser();
}
@@ -265,20 +379,24 @@ private:
);
}
std::shared_ptr<BlockParser>
createUnorderedListParser() const
std::shared_ptr<BlockParser> createUnorderedListParser() const
{
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)
{
std::shared_ptr<BlockParser> parser;
if (maddy::OrderedListParser::IsStartingLine(line))
if ((!this->config || (this->config->enabledParsers &
maddy::types::ORDERED_LIST_PARSER) != 0) &&
maddy::OrderedListParser::IsStartingLine(line))
{
parser = this->createOrderedListParser();
}
else if (maddy::UnorderedListParser::IsStartingLine(line))
else if ((!this->config || (this->config->enabledParsers &
maddy::types::UNORDERED_LIST_PARSER) != 0
) &&
maddy::UnorderedListParser::IsStartingLine(line))
{
parser = this->createUnorderedListParser();
}

View File

@@ -4,12 +4,53 @@
*/
#pragma once
#include <stdint.h>
// -----------------------------------------------------------------------------
namespace maddy {
// -----------------------------------------------------------------------------
namespace types {
// clang-format off
/**
* PARSER_TYPE
*
* Bitwise flags to turn on/off each parser
*/
enum PARSER_TYPE : uint32_t
{
NONE = 0,
BREAKLINE_PARSER = 0b1,
CHECKLIST_PARSER = 0b10,
CODE_BLOCK_PARSER = 0b100,
EMPHASIZED_PARSER = 0b1000,
HEADLINE_PARSER = 0b10000,
HORIZONTAL_LINE_PARSER = 0b100000,
HTML_PARSER = 0b1000000,
IMAGE_PARSER = 0b10000000,
INLINE_CODE_PARSER = 0b100000000,
ITALIC_PARSER = 0b1000000000,
LINK_PARSER = 0b10000000000,
ORDERED_LIST_PARSER = 0b100000000000,
PARAGRAPH_PARSER = 0b1000000000000,
QUOTE_PARSER = 0b10000000000000,
STRIKETHROUGH_PARSER = 0b100000000000000,
STRONG_PARSER = 0b1000000000000000,
TABLE_PARSER = 0b10000000000000000,
UNORDERED_LIST_PARSER = 0b100000000000000000,
LATEX_BLOCK_PARSER = 0b1000000000000000000,
DEFAULT = 0b0111111111110111111,
ALL = 0b1111111111111111111,
};
// clang-format on
} // namespace types
/**
* ParserConfig
*
@@ -17,12 +58,37 @@ namespace maddy {
*/
struct ParserConfig
{
/**
* @deprecated will be removed in 1.4.0 latest
*
* this flag = false == `enabledParsers &= ~maddy::types::EMPHASIZED_PARSER`
*/
bool isEmphasizedParserEnabled;
/**
* @deprecated will be removed in 1.4.0 latest
*
* this flag = false == `enabledParsers |= maddy::types::HTML_PARSER`
*/
bool isHTMLWrappedInParagraph;
/**
* en-/disable headline inline-parsing
*
* default: enabled
*/
bool isHeadlineInlineParsingEnabled;
/**
* enabled parsers bitfield
*/
uint32_t enabledParsers;
ParserConfig()
: isEmphasizedParserEnabled(true)
, isHTMLWrappedInParagraph(true)
, isHeadlineInlineParsingEnabled(true)
, enabledParsers(maddy::types::DEFAULT)
{}
}; // class ParserConfig

View File

@@ -31,11 +31,13 @@ public:
*
* @method
* @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(
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)
, isStarted(false)
@@ -51,10 +53,9 @@ public:
* @param {const std::string&} line
* @return {bool}
*/
static bool
IsStartingLine(const std::string& line)
static bool IsStartingLine(const std::string& line)
{
static std::regex re("^\\>.*");
static std::regex re(R"(^\>.*)");
return std::regex_match(line, re);
}
@@ -67,8 +68,7 @@ public:
* @param {std::string&} line
* @return {void}
*/
void
AddLine(std::string& line) override
void AddLine(std::string& line) override
{
if (!this->isStarted)
{
@@ -122,31 +122,18 @@ public:
* @method
* @return {bool}
*/
bool
IsFinished() const override
{
return this->isFinished;
}
bool IsFinished() const override { return this->isFinished; }
protected:
bool
isInlineBlockAllowed() const override
{
return true;
}
bool isInlineBlockAllowed() const override { return true; }
bool
isLineParserAllowed() const override
{
return true;
}
bool isLineParserAllowed() const override { return true; }
void
parseBlock(std::string& line) override
void parseBlock(std::string& line) override
{
static std::regex lineRegexWithSpace("^\\> ");
static std::regex lineRegexWithSpace(R"(^\> )");
line = std::regex_replace(line, lineRegexWithSpace, "");
static std::regex lineRegexWithoutSpace("^\\>");
static std::regex lineRegexWithoutSpace(R"(^\>)");
line = std::regex_replace(line, lineRegexWithoutSpace, "");
if (!line.empty())

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +0,0 @@
# This project is licensed under the MIT license. For more information see the
# LICENSE file.
cmake_minimum_required(VERSION 2.8)
set(LIBS_INCLUDE_DIRS
# -- googletest / -mock --------------------------------------------------------
${CMAKE_CURRENT_SOURCE_DIR}/gtest/googletest/include
${CMAKE_CURRENT_SOURCE_DIR}/gtest/googlemock/include
# ------------------------------------------------------------------------------
PARENT_SCOPE)
set(LIBS_SRC_FILES
PARENT_SCOPE)

Submodule libs/gtest deleted from 703bd9caab

47
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,47 @@
# 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(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.16.0
)
FetchContent_MakeAvailable(googletest)
# ------------------------------------------------------------------------------
file(GLOB_RECURSE MADDY_TESTS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/maddy/*.cpp)
# ------------------------------------------------------------------------------
add_executable(
MaddyTests
${MADDY_TESTS_FILES}
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
target_include_directories(MaddyTests PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(MaddyTests maddy gmock_main)
set_target_properties(MaddyTests PROPERTIES
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -g -Wall -Wpedantic -Wextra -Wno-ignored-qualifiers -fno-rtti -fno-exceptions -fsanitize=address -fno-omit-frame-pointer"
)
add_test(NAME MaddyTests COMMAND MaddyTests)

View File

@@ -15,10 +15,10 @@ class MADDY_CHECKLISTPARSER : public ::testing::Test
protected:
std::shared_ptr<maddy::ChecklistParser> clParser;
void
SetUp() override
void 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))
{
@@ -32,15 +32,16 @@ protected:
};
this->clParser = std::make_shared<maddy::ChecklistParser>(
nullptr,
getBlockParserForLineCallback
nullptr, getBlockParserForLineCallback
);
}
};
// -----------------------------------------------------------------------------
TEST_F(MADDY_CHECKLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList)
TEST_F(
MADDY_CHECKLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList
)
{
ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [ ] a"));
ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [x] b"));
@@ -53,12 +54,11 @@ TEST_F(MADDY_CHECKLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHtmlChecklist)
{
std::vector<std::string> markdown = {
"- [ ] a"
, "- [x] b"
, ""
};
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>";
std::vector<std::string> markdown = {"- [ ] a", "- [x] b", ""};
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)
{
@@ -76,14 +76,15 @@ TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHtmlChecklist)
TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
{
std::vector<std::string> markdown = {
"- [ ] a"
, " - [ ] d"
, " - [ ] e"
, "- [ ] b"
, " - [x] c"
, ""
"- [ ] a", " - [ ] 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)
{

View File

@@ -15,13 +15,9 @@ class MADDY_CODEBLOCKPARSER : public ::testing::Test
protected:
std::shared_ptr<maddy::CodeBlockParser> cbParser;
void
SetUp() override
void SetUp() override
{
this->cbParser = std::make_shared<maddy::CodeBlockParser>(
nullptr,
nullptr
);
this->cbParser = std::make_shared<maddy::CodeBlockParser>(nullptr, nullptr);
}
};
@@ -40,13 +36,32 @@ TEST_F(MADDY_CODEBLOCKPARSER, IsFinishedReturnsFalseInTheBeginning)
TEST_F(MADDY_CODEBLOCKPARSER, ItReplacesMarkdownWithAnHtmlCodeBlock)
{
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)
{
cbParser->AddLine(md);
}
ASSERT_TRUE(cbParser->IsFinished());
std::stringstream& output(cbParser->GetResult());
const std::string& outputString = output.str();
ASSERT_EQ(expected, outputString);
}
TEST_F(MADDY_CODEBLOCKPARSER, ItShouldUseAnythingBehindFirstBackticksAsClass)
{
std::vector<std::string> markdown = {
"```cpp", "some code", "some other code", "```"
};
std::string expected =
"<pre class=\"cpp\"><code>\nsome code\nsome other code\n</code></pre>";
for (std::string md : markdown)
{

View File

@@ -24,7 +24,8 @@ TEST(MADDY_EMPHASIZEDPARSER, ItReplacesMarkdownWithEmphasizedHTML)
TEST(MADDY_EMPHASIZEDPARSER, ItDoesNotParseInsideInlineCode)
{
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>();
emphasizedParser->Parse(text);

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,8 @@
TEST(MADDY_IMAGEPARSER, ItReplacesMarkdownWithAnImage)
{
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>();
imageParser->Parse(text);
@@ -23,8 +24,12 @@ TEST(MADDY_IMAGEPARSER, ItReplacesMarkdownWithAnImage)
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 expected = "Some text <img src=\"http://example.com/a.png\" alt=\"Image Title\"/> bla <img src=\"http://example.com/a.png\" alt=\"Image Title\"/>";
std::string text =
"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>();
imageParser->Parse(text);

View File

@@ -13,7 +13,8 @@
TEST(MADDY_INLINECODEPARSER, ItReplacesMarkdownWithCodeHTML)
{
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>();
emphasizedParser->Parse(text);

View File

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

View File

@@ -0,0 +1,95 @@
/*
* This project is licensed under the MIT license. For more information see the
* LICENSE file.
*/
#include <memory>
#include "gmock/gmock.h"
#include "maddy/latexblockparser.h"
// -----------------------------------------------------------------------------
class MADDY_LATEXBLOCKPARSER : public ::testing::Test
{
protected:
std::shared_ptr<maddy::LatexBlockParser> lbParser;
void SetUp() override
{
this->lbParser =
std::make_shared<maddy::LatexBlockParser>(nullptr, nullptr);
}
};
// -----------------------------------------------------------------------------
TEST_F(MADDY_LATEXBLOCKPARSER, IsStartingLineReturnsTrueWhenFacedWithTwoDollars)
{
ASSERT_TRUE(maddy::LatexBlockParser::IsStartingLine("$$"));
}
TEST_F(MADDY_LATEXBLOCKPARSER, IsFinishedReturnsFalseInTheBeginning)
{
ASSERT_FALSE(lbParser->IsFinished());
}
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesOneLineMarkdownWithALatexBlock)
{
std::vector<std::string> markdown = {
"$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$"
};
std::string expected = "$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$\n";
for (std::string md : markdown)
{
lbParser->AddLine(md);
}
ASSERT_TRUE(lbParser->IsFinished());
std::stringstream& output(lbParser->GetResult());
const std::string& outputString = output.str();
ASSERT_EQ(expected, outputString);
}
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesABlockMarkdownWithALatexBlock)
{
std::vector<std::string> markdown = {
"$$", "x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.", "$$"
};
std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.\n$$\n";
for (std::string md : markdown)
{
lbParser->AddLine(md);
}
ASSERT_TRUE(lbParser->IsFinished());
std::stringstream& output(lbParser->GetResult());
const std::string& outputString = output.str();
ASSERT_EQ(expected, outputString);
}
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesAMultilineBlockMarkdownWithALatexBlock)
{
std::vector<std::string> markdown = {
"$$", "x = {-b \\pm \\sqrt{b^2-4ac}", "\\over 2a}.$$"
};
std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac}\n\\over 2a}.$$\n";
for (std::string md : markdown)
{
lbParser->AddLine(md);
}
ASSERT_TRUE(lbParser->IsFinished());
std::stringstream& output(lbParser->GetResult());
const std::string& outputString = output.str();
ASSERT_EQ(expected, outputString);
}

View File

@@ -13,7 +13,8 @@
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithALink)
{
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>();
linkParser->Parse(text);
@@ -23,8 +24,12 @@ TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithALink)
TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithLinks)
{
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>";
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);
@@ -34,7 +39,8 @@ TEST(MADDY_LINKPARSER, ItReplacesMarkdownWithLinks)
// -----------------------------------------------------------------------------
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
// before using the LinkParser

View File

@@ -15,10 +15,10 @@ class MADDY_ORDEREDLISTPARSER : public ::testing::Test
protected:
std::shared_ptr<maddy::OrderedListParser> olParser;
void
SetUp() override
void 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))
{
@@ -32,15 +32,16 @@ protected:
};
this->olParser = std::make_shared<maddy::OrderedListParser>(
nullptr,
getBlockParserForLineCallback
nullptr, getBlockParserForLineCallback
);
}
};
// -----------------------------------------------------------------------------
TEST_F(MADDY_ORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList)
TEST_F(
MADDY_ORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList
)
{
ASSERT_TRUE(maddy::OrderedListParser::IsStartingLine("1. a"));
}
@@ -52,11 +53,7 @@ TEST_F(MADDY_ORDEREDLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlOrderedList)
{
std::vector<std::string> markdown = {
"1. a"
, "* b"
, ""
};
std::vector<std::string> markdown = {"1. a", "* b", ""};
std::string expected = "<ol><li>a</li><li>b</li></ol>";
for (std::string md : markdown)
@@ -75,14 +72,31 @@ TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlOrderedList)
TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
{
std::vector<std::string> markdown = {
"1. a"
, " 1. d"
, " * e"
, "* b"
, " 1. c"
, ""
"1. a", " 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)
{
olParser->AddLine(md);
}
ASSERT_TRUE(olParser->IsFinished());
std::stringstream& output(olParser->GetResult());
const std::string& outputString = output.str();
ASSERT_EQ(expected, outputString);
}
TEST_F(
MADDY_ORDEREDLISTPARSER, ItReplacesNumberedMarkdownListWithAnHtmlOrderedList
)
{
std::vector<std::string> markdown = {"1. a", "94. b", "103. c", ""};
std::string expected = "<ol><li>a</li><li>b</li><li>c</li></ol>";
for (std::string md : markdown)
{

View File

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

View File

@@ -3,10 +3,11 @@
* LICENSE file.
*/
#include "maddy/test_maddy_parser.h"
#include "gmock/gmock.h"
#include "maddy/parser.h"
#include "maddy/test_maddy_parser.h"
// -----------------------------------------------------------------------------
@@ -34,3 +35,65 @@ TEST(MADDY_PARSER, ItShouldParseWithConfig)
ASSERT_EQ(testHtml2, output);
}
TEST(MADDY_PARSER, ItShouldParseWithBitwiseConfig)
{
auto config = std::make_shared<maddy::ParserConfig>();
config->enabledParsers &= ~maddy::types::EMPHASIZED_PARSER;
config->enabledParsers |= maddy::types::HTML_PARSER;
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, ItShouldParseWithSmallConfig)
{
auto config = std::make_shared<maddy::ParserConfig>();
config->enabledParsers =
maddy::types::EMPHASIZED_PARSER | maddy::types::STRONG_PARSER;
auto parser = std::make_shared<maddy::Parser>(config);
std::stringstream markdown(testMarkdown);
const std::string output = parser->Parse(markdown);
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>
const std::string testMarkdown = "# This is a test\n\
const std::string testMarkdown =
"# This is a test\n\
\n\
This should result in a praragraph\n\
it's that simple.\n\
@@ -69,5 +70,71 @@ foot a|foot b|foot c\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 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 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 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:
std::shared_ptr<maddy::QuoteParser> quoteParser;
void
SetUp() override
void SetUp() override
{
this->quoteParser = std::make_shared<maddy::QuoteParser>(
nullptr,
nullptr
);
this->quoteParser = std::make_shared<maddy::QuoteParser>(nullptr, nullptr);
}
};
// -----------------------------------------------------------------------------
TEST_F(MADDY_QUOTEPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfAQuote)
TEST_F(
MADDY_QUOTEPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfAQuote
)
{
ASSERT_TRUE(maddy::QuoteParser::IsStartingLine("> a"));
}
@@ -39,13 +37,7 @@ TEST_F(MADDY_QUOTEPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_QUOTEPARSER, ItReplacesMarkdownWithAnHtmlBlockQuote)
{
std::vector<std::string> markdown = {
"> a"
, "> b"
, ">"
, "> c"
, ""
};
std::vector<std::string> markdown = {"> a", "> b", ">", "> c", ""};
std::string expected = "<blockquote>a b c </blockquote>";
for (std::string md : markdown)

View File

@@ -23,8 +23,10 @@ TEST(MADDY_STRIKETHROUGHPARSER, ItReplacesMarkdownWithStrikeThroughHTML)
TEST(MADDY_STRIKETHROUGHPARSER, ItDoesNotParseInsideInlineCode)
{
std::string text = "some text `~~bla~~` ` ~~text~~ ` testing <code>~~it~~</code> out";
std::string expected = "some text `~~bla~~` ` ~~text~~ ` testing <code>~~it~~</code> out";
std::string text =
"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>();
strikeThroughParser->Parse(text);

View File

@@ -18,16 +18,11 @@ TEST(MADDY_STRONGPARSER, ItReplacesMarkdownWithStrongHTML)
std::string expected;
};
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 <strong>bla</strong> text testing <strong>it</strong> out"
},
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 <strong>bla</strong> text testing <strong>it</strong> out"},
};
auto strongParser = std::make_shared<maddy::StrongParser>();
@@ -47,16 +42,11 @@ TEST(MADDY_STRONGPARSER, ItReplacesEmphasizedMarkdownNotWithStrongHTML)
std::string expected;
};
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 <strong>it</strong> out"
},
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 <strong>it</strong> out"},
};
auto strongParser = std::make_shared<maddy::StrongParser>();
@@ -76,16 +66,13 @@ TEST(MADDY_STRONGPARSER, ItDoesNotParseInsideInlineCode)
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 <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>();

View File

@@ -15,19 +15,17 @@ class MADDY_TABLEPARSER : public ::testing::Test
protected:
std::shared_ptr<maddy::TableParser> tableParser;
void
SetUp() override
void SetUp() override
{
this->tableParser = std::make_shared<maddy::TableParser>(
nullptr,
nullptr
);
this->tableParser = std::make_shared<maddy::TableParser>(nullptr, nullptr);
}
};
// -----------------------------------------------------------------------------
TEST_F(MADDY_TABLEPARSER, IsStartingLineReturnsTrueWhenFacedWithTheBeginningOfATable)
TEST_F(
MADDY_TABLEPARSER, IsStartingLineReturnsTrueWhenFacedWithTheBeginningOfATable
)
{
ASSERT_EQ(true, maddy::TableParser::IsStartingLine("|table>"));
}
@@ -40,16 +38,21 @@ TEST_F(MADDY_TABLEPARSER, IsFinishedReturnsFalseInTheBeginning)
TEST_F(MADDY_TABLEPARSER, ItReplacesMarkdownWithAnHtmlTable)
{
std::vector<std::string> markdown = {
"|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"
"|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"
};
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)
{

View File

@@ -15,10 +15,10 @@ class MADDY_UNORDEREDLISTPARSER : public ::testing::Test
protected:
std::shared_ptr<maddy::UnorderedListParser> ulParser;
void
SetUp() override
void 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))
{
@@ -32,15 +32,17 @@ protected:
};
this->ulParser = std::make_shared<maddy::UnorderedListParser>(
nullptr,
getBlockParserForLineCallback
nullptr, getBlockParserForLineCallback
);
}
};
// -----------------------------------------------------------------------------
TEST_F(MADDY_UNORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList)
TEST_F(
MADDY_UNORDEREDLISTPARSER,
IsStartingLineReturnsTrueWhenFacedWithBeginningOfList
)
{
ASSERT_TRUE(maddy::UnorderedListParser::IsStartingLine("* a"));
}
@@ -53,11 +55,11 @@ TEST_F(MADDY_UNORDEREDLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlUnorderedList)
{
std::vector<std::string> markdown = {
"* a"
, "* b"
, ""
"* a", "* b", "- c", "- d", "+ e", "+ f", "* g", ""
};
std::string expected = "<ul><li>a</li><li>b</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)
{
@@ -75,14 +77,11 @@ TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlUnorderedList)
TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
{
std::vector<std::string> markdown = {
"* a"
, " * d"
, " * e"
, "* b"
, " * c"
, ""
"* a", " * 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></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)
{

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::InitGoogleMock(&argc, argv);
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": {}
}

143
tools/format.py Normal file
View File

@@ -0,0 +1,143 @@
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 = [
"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 check_clang_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()