mirror of
https://github.com/quitesimpleorg/qsmaddy.git
synced 2024-12-18 09:42:37 +01:00
initial release 1.0.0
This commit is contained in:
commit
569794c4b6
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{h,hh,hpp,c,cc,cpp,cxx}]
|
||||||
|
indent_size = 2
|
497
.gitignore
vendored
Normal file
497
.gitignore
vendored
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
# Created by https://www.gitignore.io/api/vim,c++,xcode,clion,macos,valgrind,visualstudio,visualstudiocode
|
||||||
|
|
||||||
|
### C++ ###
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
### CLion ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.xml
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-debug/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Ruby plugin and RubyMine
|
||||||
|
/.rakeTasks
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
### CLion Patch ###
|
||||||
|
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||||
|
|
||||||
|
# *.iml
|
||||||
|
# modules.xml
|
||||||
|
# .idea/misc.xml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
.idea/sonarlint
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
*.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### Valgrind ###
|
||||||
|
# Callgrind output files
|
||||||
|
callgrind.out
|
||||||
|
callgrind.out.*
|
||||||
|
|
||||||
|
# Cachegrind output files
|
||||||
|
cachegrind.out
|
||||||
|
cachegrind.out.*
|
||||||
|
|
||||||
|
# Massif output files
|
||||||
|
massif.out
|
||||||
|
massif.out.*
|
||||||
|
|
||||||
|
# BBV output files
|
||||||
|
bb.out
|
||||||
|
bb.out.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Vim ###
|
||||||
|
# swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-v][a-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
# session
|
||||||
|
Session.vim
|
||||||
|
# temporary
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
# auto-generated tag files
|
||||||
|
tags
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history
|
||||||
|
|
||||||
|
### Xcode ###
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.moved-aside
|
||||||
|
*.xccheckout
|
||||||
|
*.xcscmblueprint
|
||||||
|
|
||||||
|
### Xcode Patch ###
|
||||||
|
*.xcodeproj/*
|
||||||
|
!*.xcodeproj/project.pbxproj
|
||||||
|
!*.xcodeproj/xcshareddata/
|
||||||
|
!*.xcworkspace/contents.xcworkspacedata
|
||||||
|
/*.gcno
|
||||||
|
|
||||||
|
### VisualStudio ###
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
**/Properties/launchSettings.json
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# TODO: Uncomment the next line to ignore your web deploy settings.
|
||||||
|
# By default, sensitive information, such as encrypted password
|
||||||
|
# should be stored in the .pubxml.user file.
|
||||||
|
#*.pubxml
|
||||||
|
*.pubxml.user
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Typescript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
### VisualStudio Patch ###
|
||||||
|
# By default, sensitive information, such as encrypted password
|
||||||
|
# should be stored in the .pubxml.user file.
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/vim,c++,xcode,clion,macos,valgrind,visualstudio,visualstudiocode
|
||||||
|
|
||||||
|
tmp
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "libs/gtest"]
|
||||||
|
path = libs/gtest
|
||||||
|
url = https://github.com/google/googletest.git
|
7
AUTHORS
Normal file
7
AUTHORS
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
The following authors have all licensed their contributions to maddy under the
|
||||||
|
licensing terms detailed in LICENSE.
|
||||||
|
|
||||||
|
(Authors keep copyright of their contributions, of course; they just grant
|
||||||
|
a license to everyone to use it as detailed in LICENSE.)
|
||||||
|
|
||||||
|
M. Petra Baranski (info@progsource.de)
|
55
CMakeLists.txt
Normal file
55
CMakeLists.txt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# This project is licensed under the MITlicense. For more information see the
|
||||||
|
# LICENSE file.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
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)
|
||||||
|
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
|
||||||
|
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(MADDY_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
file(GLOB_RECURSE MADDY_TESTS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/maddy/*.cpp)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(
|
||||||
|
CMAKE_CXX_FLAGS
|
||||||
|
"${CMAKE_CXX_FLAGS} -g -std=c++${MADDY_CPP_VERSION} -Wall -Wpedantic -Wextra -Wno-ignored-qualifiers -fno-rtti -fno-exceptions" # -O2
|
||||||
|
)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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}
|
||||||
|
${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)
|
18
LICENSE
Normal file
18
LICENSE
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Copyright 2017 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
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
51
README.md
Normal file
51
README.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# maddy
|
||||||
|
|
||||||
|
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
||||||
|
[![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-brightgreen.svg)](https://semver.org/)
|
||||||
|
|
||||||
|
maddy is a C++ Markdown to HTML **header-only** parser library.
|
||||||
|
|
||||||
|
## Supportes OS
|
||||||
|
|
||||||
|
It actually should work on any OS, that supports the C++14 standard library.
|
||||||
|
|
||||||
|
It is tested to work on:
|
||||||
|
|
||||||
|
* Linux (without exceptions and without RTTI)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
* C++14
|
||||||
|
|
||||||
|
## Why maddy?
|
||||||
|
|
||||||
|
When I was needing 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).
|
||||||
|
|
||||||
|
## HowTo use
|
||||||
|
|
||||||
|
To use maddy in your project, simply add the include path of maddy to yours
|
||||||
|
and in the code, you can then do the following:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/parser.h"
|
||||||
|
|
||||||
|
std::stringstream markdownInput("");
|
||||||
|
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>();
|
||||||
|
std::string htmlOutput = parser->Parse(markdownInput);
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to contribute
|
||||||
|
|
||||||
|
There are different possibilities:
|
||||||
|
|
||||||
|
* Create a GitHub issue
|
||||||
|
* Create a pull request with an own branch (don't forget to put yourself in the
|
||||||
|
AUTHORS file)
|
303
docs/definitions.md
Normal file
303
docs/definitions.md
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
# Markdown Definitions
|
||||||
|
|
||||||
|
This specification defines which markdown syntax can be parsed by maddy.
|
||||||
|
There is no HTML allowed in the markdown syntax - or said otherwise - it might
|
||||||
|
destroy the output, if there was HTML in your markdown.
|
||||||
|
|
||||||
|
The Parser expects you to use spaces and not tabs for indentation in the
|
||||||
|
markdown.
|
||||||
|
|
||||||
|
## Headlines
|
||||||
|
|
||||||
|
```
|
||||||
|
# h1 heading
|
||||||
|
## h2 heading
|
||||||
|
### h3 heading
|
||||||
|
#### h4 heading
|
||||||
|
##### h5 heading
|
||||||
|
###### h6 heading
|
||||||
|
```
|
||||||
|
results in:
|
||||||
|
```html
|
||||||
|
<h1>h1 heading</h1>
|
||||||
|
<h2>h2 heading</h2>
|
||||||
|
<h3>h3 heading</h3>
|
||||||
|
<h4>h4 heading</h4>
|
||||||
|
<h5>h5 heading</h5>
|
||||||
|
<h6>h6 heading</h6>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
```
|
||||||
|
[Text of the link](http://example.com)
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<a href="http://example.com">Text of the link</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lists
|
||||||
|
|
||||||
|
### unordered
|
||||||
|
```
|
||||||
|
|
||||||
|
* unordered
|
||||||
|
* list
|
||||||
|
* items
|
||||||
|
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<ul>
|
||||||
|
<li>unordered</li>
|
||||||
|
<li>list</li>
|
||||||
|
<li>items</li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
* unorederd
|
||||||
|
* list
|
||||||
|
* items
|
||||||
|
* in
|
||||||
|
* an
|
||||||
|
* hierarchy
|
||||||
|
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<ul>
|
||||||
|
<li>list</li>
|
||||||
|
<li>items
|
||||||
|
<ul>
|
||||||
|
<li>in</li>
|
||||||
|
<li>an</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>hierarchy</li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
### ordered
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
1. ordered
|
||||||
|
* list
|
||||||
|
* items
|
||||||
|
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<ol>
|
||||||
|
<li>ordered</li>
|
||||||
|
<li>list</li>
|
||||||
|
<li>items</li>
|
||||||
|
</ol>
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
1. ordered
|
||||||
|
* list
|
||||||
|
1. items
|
||||||
|
* in
|
||||||
|
1. an
|
||||||
|
* hierarchy
|
||||||
|
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<ol>
|
||||||
|
<li>ordered</li>
|
||||||
|
<li>list
|
||||||
|
<ol>
|
||||||
|
<li>items</li>
|
||||||
|
<li>in
|
||||||
|
<ol>an</ol>
|
||||||
|
</li>
|
||||||
|
<li>hierarchy</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
```
|
||||||
|
|
||||||
|
### combination
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
* combination
|
||||||
|
* of
|
||||||
|
1. unordered and
|
||||||
|
* ordered
|
||||||
|
* list
|
||||||
|
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<ul>
|
||||||
|
<li>combination</li>
|
||||||
|
<li>of
|
||||||
|
<ol>
|
||||||
|
<li>unordered and</li>
|
||||||
|
<li>ordered</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li>list</li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
### checklist
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] some item
|
||||||
|
- [ ] another item
|
||||||
|
- [x] some checked item
|
||||||
|
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<ul class="checklist">
|
||||||
|
<li><label><input type="checkbox"/>some item
|
||||||
|
<ul class="checklist">
|
||||||
|
<li><label><input type="checkbox"/><span>another item</label></li>
|
||||||
|
</ul>
|
||||||
|
</label></li>
|
||||||
|
<li><label><input type="checkbox" checked="checked"/>some checked item</label></li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
might not work in combination with other lists
|
||||||
|
|
||||||
|
## Code Blocks
|
||||||
|
|
||||||
|
```
|
||||||
|
some code
|
||||||
|
```
|
||||||
|
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<pre><code>
|
||||||
|
some code
|
||||||
|
</code></pre>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inline code
|
||||||
|
|
||||||
|
some text `some inline code` some other text
|
||||||
|
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
some text <code>some inline code</code> some other text
|
||||||
|
```
|
||||||
|
|
||||||
|
## quotes
|
||||||
|
|
||||||
|
```
|
||||||
|
> Some quote
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<blockqoute>
|
||||||
|
<p>Some quote</p>
|
||||||
|
</blockquote>
|
||||||
|
```
|
||||||
|
|
||||||
|
## bold
|
||||||
|
|
||||||
|
```
|
||||||
|
**bold text**
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<strong>bold text</strong>
|
||||||
|
```
|
||||||
|
|
||||||
|
## emphasized
|
||||||
|
|
||||||
|
```
|
||||||
|
*emphasized text*
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<em>emphasized text</em>
|
||||||
|
```
|
||||||
|
|
||||||
|
## strikethrough
|
||||||
|
|
||||||
|
```
|
||||||
|
~~striked through text~~
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<s>striked through text</s>
|
||||||
|
```
|
||||||
|
|
||||||
|
## horizontal line
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<hr/>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Images
|
||||||
|
|
||||||
|
```
|
||||||
|
![Image alt text](http://example.com/example.png)
|
||||||
|
```
|
||||||
|
results in
|
||||||
|
```html
|
||||||
|
<img src="http://example.com/example.png" alt="Image alt text"/>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|table>
|
||||||
|
Left header | middle header | last header
|
||||||
|
- | - | -
|
||||||
|
cell 1 | cell 2 | cell 3
|
||||||
|
cell 4 | cell 5 | cell 6
|
||||||
|
- | - | -
|
||||||
|
foot a | foot b | foot c
|
||||||
|
|<table
|
||||||
|
|
||||||
|
```
|
||||||
|
becomes
|
||||||
|
```html
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Left header</th>
|
||||||
|
<th>middle header</th>
|
||||||
|
<th>last header</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>cell 1</td>
|
||||||
|
<td>cell 2</td>
|
||||||
|
<td>cell 3</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>cell 4</td>
|
||||||
|
<td>cell 5</td>
|
||||||
|
<td>cell 6</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td>foot a</td>
|
||||||
|
<td>foot b</td>
|
||||||
|
<td>foot c</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
```
|
||||||
|
table header and footer are optional
|
190
include/maddy/blockparser.h
Normal file
190
include/maddy/blockparser.h
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BlockParser
|
||||||
|
*
|
||||||
|
* The code expects every child to have the following static function to be
|
||||||
|
* implemented:
|
||||||
|
* `static bool IsStartingLine(const std::string& line)`
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: result("", std::ios_base::ate | std::ios_base::in | std::ios_base::out)
|
||||||
|
, childParser(nullptr)
|
||||||
|
, parseLineCallback(parseLineCallback)
|
||||||
|
, getBlockParserForLineCallback(getBlockParserForLineCallback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddLine
|
||||||
|
*
|
||||||
|
* Adding a line which has to be parsed.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
virtual void
|
||||||
|
AddLine(std::string& line)
|
||||||
|
{
|
||||||
|
this->parseBlock(line);
|
||||||
|
|
||||||
|
if (this->isInlineBlockAllowed() && !this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser = this->getBlockParserForLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser->AddLine(line);
|
||||||
|
|
||||||
|
if (this->childParser->IsFinished())
|
||||||
|
{
|
||||||
|
this->result << this->childParser->GetResult().str();
|
||||||
|
this->childParser = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->isLineParserAllowed())
|
||||||
|
{
|
||||||
|
this->parseLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->result << line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* Check if the BlockParser is done
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
virtual bool IsFinished() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetResult
|
||||||
|
*
|
||||||
|
* Get the parsed HTML output.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {std::stringstream}
|
||||||
|
*/
|
||||||
|
std::stringstream&
|
||||||
|
GetResult()
|
||||||
|
{
|
||||||
|
return this->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear
|
||||||
|
*
|
||||||
|
* Clear the result to reuse the parser object.
|
||||||
|
*
|
||||||
|
* It is only used by one test for now.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Clear()
|
||||||
|
{
|
||||||
|
this->result.str("");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::stringstream result;
|
||||||
|
std::shared_ptr<BlockParser> childParser;
|
||||||
|
|
||||||
|
virtual bool isInlineBlockAllowed() const = 0;
|
||||||
|
virtual bool isLineParserAllowed() const = 0;
|
||||||
|
virtual void parseBlock(std::string& line) = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
parseLine(std::string& line)
|
||||||
|
{
|
||||||
|
if (parseLineCallback)
|
||||||
|
{
|
||||||
|
parseLineCallback(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
getIndentationWidth(const std::string& line) const
|
||||||
|
{
|
||||||
|
bool hasMetNonSpace = false;
|
||||||
|
|
||||||
|
uint32_t indentation = std::count_if(
|
||||||
|
line.begin(),
|
||||||
|
line.end(),
|
||||||
|
[&hasMetNonSpace](unsigned char c)
|
||||||
|
{
|
||||||
|
if (hasMetNonSpace)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::isspace(c))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMetNonSpace = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return indentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
getBlockParserForLine(const std::string& line)
|
||||||
|
{
|
||||||
|
if (getBlockParserForLineCallback)
|
||||||
|
{
|
||||||
|
return getBlockParserForLineCallback(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::function<void(std::string&)> parseLineCallback;
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback;
|
||||||
|
}; // class BlockParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
140
include/maddy/checklistparser.h
Normal file
140
include/maddy/checklistparser.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChecklistParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class ChecklistParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* An unordered list starts with `* `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^- \\[[x| ]\\] .*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
bool isStartOfNewListItem = IsStartingLine(line);
|
||||||
|
uint32_t indentation = getIndentationWidth(line);
|
||||||
|
|
||||||
|
static std::regex lineRegex("^(- )");
|
||||||
|
line = std::regex_replace(line, lineRegex, "");
|
||||||
|
|
||||||
|
static std::regex emptyBoxRegex("^\\[ \\]");
|
||||||
|
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\"/>";
|
||||||
|
line = std::regex_replace(line, boxRegex, boxReplacement);
|
||||||
|
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<ul class=\"checklist\"><li><label>" + line;
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indentation >= 2)
|
||||||
|
{
|
||||||
|
line = line.substr(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
line.empty() ||
|
||||||
|
line.find("</label></li><li><label>") != std::string::npos ||
|
||||||
|
line.find("</label></li></ul>") != std::string::npos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
line = "</label></li></ul>" + line;
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStartOfNewListItem)
|
||||||
|
{
|
||||||
|
line = "</label></li><li><label>" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class ChecklistParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
137
include/maddy/codeblockparser.h
Normal file
137
include/maddy/codeblockparser.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CodeBlockParser
|
||||||
|
*
|
||||||
|
* From Markdown: 3 times surrounded code (without space in the beginning)
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
* some code
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* To HTML:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <pre><code>
|
||||||
|
* some code
|
||||||
|
* </code></pre>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class CodeBlockParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line starts with three code signs, then it is a code block.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^(?:`){3}$");
|
||||||
|
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 (line == "```")
|
||||||
|
{
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<pre><code>\n";
|
||||||
|
this->isStarted = true;
|
||||||
|
this->isFinished = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line = "</code></pre>";
|
||||||
|
this->isFinished = true;
|
||||||
|
this->isStarted = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class CodeBlockParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
53
include/maddy/emphasizedparser.h
Normal file
53
include/maddy/emphasizedparser.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EmphasizedParser
|
||||||
|
*
|
||||||
|
* Has to be used after the `StrongParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class EmphasizedParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text *text*`
|
||||||
|
*
|
||||||
|
* To HTML: `text <em>text</em>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("\\*([^\\*]*)\\*");
|
||||||
|
static std::string replacement = "<em>$1</em>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class EmphasizedParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
138
include/maddy/headlineparser.h
Normal file
138
include/maddy/headlineparser.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HeadlineParser
|
||||||
|
*
|
||||||
|
* From Markdown:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* # Headline 1
|
||||||
|
* ## Headline 2
|
||||||
|
* ### Headline 3
|
||||||
|
* #### Headline 4
|
||||||
|
* ##### Headline 5
|
||||||
|
* ###### Headline 6
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* To HTML:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <h1>Headline 1</h1>
|
||||||
|
* <h2>Headline 2</h2>
|
||||||
|
* <h3>Headline 3</h3>
|
||||||
|
* <h4>Headline 4</h4>
|
||||||
|
* <h5>Headline 5</h5>
|
||||||
|
* <h6>Headline 6</h6>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class HeadlineParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line starts with 1 - 6 `#`, then it is a headline.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^(?:#){1,6} (.*)");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* The headline is always only one line long, so this method always returns
|
||||||
|
* true.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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} (.*)")
|
||||||
|
};
|
||||||
|
static std::vector<std::string> hlReplacement = {
|
||||||
|
"<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)
|
||||||
|
{
|
||||||
|
line = std::regex_replace(line, hlRegex[i], hlReplacement[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; // class HeadlineParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
106
include/maddy/horizontallineparser.h
Normal file
106
include/maddy/horizontallineparser.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HorizontalLineParser
|
||||||
|
*
|
||||||
|
* From Markdown: `---`
|
||||||
|
*
|
||||||
|
* To HTML: `<hr/>`
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class HorizontalLineParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, lineRegex("^---$")
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line has exact three dashes `---`, then it is a horizontal line.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^---$");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* The horizontal line is always only one line long, so this method always
|
||||||
|
* returns true.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::string replacement = "<hr/>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, lineRegex, replacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::regex lineRegex;
|
||||||
|
}; // class HorizontalLineParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
53
include/maddy/imageparser.h
Normal file
53
include/maddy/imageparser.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImageParser
|
||||||
|
*
|
||||||
|
* Has to be used before the `LinkParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class ImageParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `![text](http://example.com/a.png)`
|
||||||
|
*
|
||||||
|
* To HTML: `<img src="http://example.com/a.png" alt="text"/>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("\\!\\[([^\\]]*)\\]\\(([^\\]]*)\\)");
|
||||||
|
static std::string replacement = "<img src=\"$2\" alt=\"$1\"/>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class ImageParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
51
include/maddy/inlinecodeparser.h
Normal file
51
include/maddy/inlinecodeparser.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InlineCodeParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class InlineCodeParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text `some code``
|
||||||
|
*
|
||||||
|
* To HTML: `text <code>some code</code>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("`([^`]*)`");
|
||||||
|
static std::string replacement = "<code>$1</code>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class InlineCodeParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
39
include/maddy/lineparser.h
Normal file
39
include/maddy/lineparser.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LineParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown to HTML
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
virtual void Parse(std::string& line) = 0;
|
||||||
|
}; // class LineParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
53
include/maddy/linkparser.h
Normal file
53
include/maddy/linkparser.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LinkParser
|
||||||
|
*
|
||||||
|
* Has to be used after the `ImageParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class LinkParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `[text](http://example.com)`
|
||||||
|
*
|
||||||
|
* To HTML: `<a href="http://example.com">text</a>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("\\[([^\\]]*)\\]\\(([^\\]]*)\\)");
|
||||||
|
static std::string replacement = "<a href=\"$2\">$1</a>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class LinkParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
142
include/maddy/orderedlistparser.h
Normal file
142
include/maddy/orderedlistparser.h
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OrderedListParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class OrderedListParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* An ordered list starts with `1. `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^1\\. .*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
bool isStartOfNewListItem = this->isStartOfNewListItem(line);
|
||||||
|
uint32_t indentation = getIndentationWidth(line);
|
||||||
|
|
||||||
|
static std::regex orderedlineRegex("^1\\. ");
|
||||||
|
line = std::regex_replace(line, orderedlineRegex, "");
|
||||||
|
static std::regex unorderedlineRegex("^(\\* )");
|
||||||
|
line = std::regex_replace(line, unorderedlineRegex, "");
|
||||||
|
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<ol><li>" + line;
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indentation >= 2)
|
||||||
|
{
|
||||||
|
line = line.substr(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = "</li></ol>" + line;
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStartOfNewListItem)
|
||||||
|
{
|
||||||
|
line = "</li><li>" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
|
||||||
|
bool
|
||||||
|
isStartOfNewListItem(const std::string& line) const
|
||||||
|
{
|
||||||
|
static std::regex re("^(?:1\\. |\\* ).*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
}; // class OrderedListParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
114
include/maddy/paragraphparser.h
Normal file
114
include/maddy/paragraphparser.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParagraphParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class ParagraphParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line is not empty, it will be a paragraph. So this block parser has
|
||||||
|
* to always run as the last one!
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
return !line.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* An empty line will end the paragraph.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<p>" + line + " ";
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.empty())
|
||||||
|
{
|
||||||
|
line += "</p>";
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class ParagraphParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
255
include/maddy/parser.h
Normal file
255
include/maddy/parser.h
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// BlockParser
|
||||||
|
#include "maddy/checklistparser.h"
|
||||||
|
#include "maddy/codeblockparser.h"
|
||||||
|
#include "maddy/headlineparser.h"
|
||||||
|
#include "maddy/horizontallineparser.h"
|
||||||
|
#include "maddy/orderedlistparser.h"
|
||||||
|
#include "maddy/paragraphparser.h"
|
||||||
|
#include "maddy/quoteparser.h"
|
||||||
|
#include "maddy/tableparser.h"
|
||||||
|
#include "maddy/unorderedlistparser.h"
|
||||||
|
|
||||||
|
// LineParser
|
||||||
|
#include "maddy/emphasizedparser.h"
|
||||||
|
#include "maddy/imageparser.h"
|
||||||
|
#include "maddy/inlinecodeparser.h"
|
||||||
|
#include "maddy/linkparser.h"
|
||||||
|
#include "maddy/strikethroughparser.h"
|
||||||
|
#include "maddy/strongparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser
|
||||||
|
*
|
||||||
|
* Transforms Markdown to HTML
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class Parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* Initializes all `LineParser`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
|
Parser()
|
||||||
|
: emphasizedParser(std::make_shared<EmphasizedParser>())
|
||||||
|
, imageParser(std::make_shared<ImageParser>())
|
||||||
|
, inlineCodeParser(std::make_shared<InlineCodeParser>())
|
||||||
|
, linkParser(std::make_shared<LinkParser>())
|
||||||
|
, strikeThroughParser(std::make_shared<StrikeThroughParser>())
|
||||||
|
, strongParser(std::make_shared<StrongParser>())
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::stringstream&} markdown
|
||||||
|
* @return {std::string} HTML
|
||||||
|
*/
|
||||||
|
std::string
|
||||||
|
Parse(std::stringstream& markdown) const
|
||||||
|
{
|
||||||
|
std::string result = "";
|
||||||
|
std::shared_ptr<BlockParser> currentBlockParser = nullptr;
|
||||||
|
|
||||||
|
for (std::string line; std::getline(markdown, line);)
|
||||||
|
{
|
||||||
|
if (!currentBlockParser)
|
||||||
|
{
|
||||||
|
currentBlockParser = getBlockParserForLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentBlockParser)
|
||||||
|
{
|
||||||
|
currentBlockParser->AddLine(line);
|
||||||
|
|
||||||
|
if (currentBlockParser->IsFinished())
|
||||||
|
{
|
||||||
|
result += currentBlockParser->GetResult().str();
|
||||||
|
currentBlockParser = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<EmphasizedParser> emphasizedParser;
|
||||||
|
std::shared_ptr<ImageParser> imageParser;
|
||||||
|
std::shared_ptr<InlineCodeParser> inlineCodeParser;
|
||||||
|
std::shared_ptr<LinkParser> linkParser;
|
||||||
|
std::shared_ptr<StrikeThroughParser> strikeThroughParser;
|
||||||
|
std::shared_ptr<StrongParser> strongParser;
|
||||||
|
|
||||||
|
// block parser have to run before
|
||||||
|
void
|
||||||
|
runLineParser(std::string& line) const
|
||||||
|
{
|
||||||
|
// Attention! ImageParser has to be before LinkParser
|
||||||
|
this->imageParser->Parse(line);
|
||||||
|
this->linkParser->Parse(line);
|
||||||
|
|
||||||
|
// Attention! StrongParser has to be before EmphasizedParser
|
||||||
|
this->strongParser->Parse(line);
|
||||||
|
this->emphasizedParser->Parse(line);
|
||||||
|
|
||||||
|
this->strikeThroughParser->Parse(line);
|
||||||
|
|
||||||
|
this->inlineCodeParser->Parse(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
getBlockParserForLine(const std::string& line) const
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::CodeBlockParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::CodeBlockParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::HeadlineParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::HeadlineParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::HorizontalLineParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::HorizontalLineParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (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); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::TableParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::TableParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::ChecklistParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createChecklistParser();
|
||||||
|
}
|
||||||
|
else if (maddy::OrderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createOrderedListParser();
|
||||||
|
}
|
||||||
|
else if (maddy::UnorderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createUnorderedListParser();
|
||||||
|
}
|
||||||
|
else if (maddy::ParagraphParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::ParagraphParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
createChecklistParser() const
|
||||||
|
{
|
||||||
|
return std::make_shared<maddy::ChecklistParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
[this](const std::string& line)
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::ChecklistParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createChecklistParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
createOrderedListParser() const
|
||||||
|
{
|
||||||
|
return std::make_shared<maddy::OrderedListParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
[this](const std::string& line)
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::OrderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createOrderedListParser();
|
||||||
|
}
|
||||||
|
else if (maddy::UnorderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createUnorderedListParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
createUnorderedListParser() const
|
||||||
|
{
|
||||||
|
return std::make_shared<maddy::UnorderedListParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
[this](const std::string& line)
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::OrderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createOrderedListParser();
|
||||||
|
}
|
||||||
|
else if (maddy::UnorderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createUnorderedListParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}; // class Parser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
165
include/maddy/quoteparser.h
Normal file
165
include/maddy/quoteparser.h
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuoteParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class QuoteParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* A quote starts with `> `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^\\>.*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddLine
|
||||||
|
*
|
||||||
|
* Adding a line which has to be parsed.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
AddLine(std::string& line) override
|
||||||
|
{
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
this->result << "<blockquote>";
|
||||||
|
this->isStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool finish = false;
|
||||||
|
if (line.empty())
|
||||||
|
{
|
||||||
|
finish = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->parseBlock(line);
|
||||||
|
|
||||||
|
if (this->isInlineBlockAllowed() && !this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser = this->getBlockParserForLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser->AddLine(line);
|
||||||
|
|
||||||
|
if (this->childParser->IsFinished())
|
||||||
|
{
|
||||||
|
this->result << this->childParser->GetResult().str();
|
||||||
|
this->childParser = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->isLineParserAllowed())
|
||||||
|
{
|
||||||
|
this->parseLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finish)
|
||||||
|
{
|
||||||
|
this->result << "</blockquote>";
|
||||||
|
this->isFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->result << line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex lineRegexWithSpace("^\\> ");
|
||||||
|
line = std::regex_replace(line, lineRegexWithSpace, "");
|
||||||
|
static std::regex lineRegexWithoutSpace("^\\>");
|
||||||
|
line = std::regex_replace(line, lineRegexWithoutSpace, "");
|
||||||
|
|
||||||
|
if (!line.empty())
|
||||||
|
{
|
||||||
|
line += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class QuoteParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
51
include/maddy/strikethroughparser.h
Normal file
51
include/maddy/strikethroughparser.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StrikeThroughParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class StrikeThroughParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text ~~text~~`
|
||||||
|
*
|
||||||
|
* To HTML: `text <s>text</s>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("\\~\\~([^\\~]*)\\~\\~");
|
||||||
|
static std::string replacement = "<s>$1</s>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class StrikeThroughParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
53
include/maddy/strongparser.h
Normal file
53
include/maddy/strongparser.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StrongParser
|
||||||
|
*
|
||||||
|
* Has to be used before the `EmphasizedParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class StrongParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text **text**`
|
||||||
|
*
|
||||||
|
* To HTML: `text <strong>text</strong>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("\\*\\*([^\\*\\*]*)\\*\\*");
|
||||||
|
static std::string replacement = "<strong>$1</strong>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class StrongParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
246
include/maddy/tableparser.h
Normal file
246
include/maddy/tableparser.h
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TableParser
|
||||||
|
*
|
||||||
|
* For more information, see the docs folder.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class TableParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
, currentBlock(0)
|
||||||
|
, currentRow(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line has exact `|table>`, then it is starting the table.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::string matchString("|table>");
|
||||||
|
return line == matchString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddLine
|
||||||
|
*
|
||||||
|
* Adding a line which has to be parsed.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
AddLine(std::string& line) override
|
||||||
|
{
|
||||||
|
if (!this->isStarted && line == "|table>")
|
||||||
|
{
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->isStarted)
|
||||||
|
{
|
||||||
|
if (line == "- | - | -")
|
||||||
|
{
|
||||||
|
++this->currentBlock;
|
||||||
|
this->currentRow = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line == "|<table")
|
||||||
|
{
|
||||||
|
static std::string emptyLine = "";
|
||||||
|
this->parseBlock(emptyLine);
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->table.size() < this->currentBlock + 1)
|
||||||
|
{
|
||||||
|
this->table.push_back(std::vector<std::vector<std::string>>());
|
||||||
|
}
|
||||||
|
this->table[this->currentBlock].push_back(std::vector<std::string>());
|
||||||
|
|
||||||
|
std::string segment;
|
||||||
|
std::stringstream streamToSplit(line);
|
||||||
|
|
||||||
|
while (std::getline(streamToSplit, segment, '|'))
|
||||||
|
{
|
||||||
|
this->parseLine(segment);
|
||||||
|
this->table[this->currentBlock][this->currentRow].push_back(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
++this->currentRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* A table ends with `|<table`.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string&) override
|
||||||
|
{
|
||||||
|
result << "<table>";
|
||||||
|
|
||||||
|
bool hasHeader = false;
|
||||||
|
bool hasFooter = false;
|
||||||
|
bool isFirstBlock = true;
|
||||||
|
uint32_t currentBlockNumber = 0;
|
||||||
|
|
||||||
|
if (this->table.size() > 1)
|
||||||
|
{
|
||||||
|
hasHeader = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->table.size() >= 3)
|
||||||
|
{
|
||||||
|
hasFooter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const std::vector<std::vector<std::string>>& block : this->table)
|
||||||
|
{
|
||||||
|
bool isInHeader = false;
|
||||||
|
bool isInFooter = false;
|
||||||
|
++currentBlockNumber;
|
||||||
|
|
||||||
|
if (hasHeader && isFirstBlock)
|
||||||
|
{
|
||||||
|
result << "<thead>";
|
||||||
|
isInHeader = true;
|
||||||
|
}
|
||||||
|
else if (hasFooter && currentBlockNumber == this->table.size())
|
||||||
|
{
|
||||||
|
result << "<tfoot>";
|
||||||
|
isInFooter = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "<tbody>";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const std::vector<std::string>& row : block)
|
||||||
|
{
|
||||||
|
result << "<tr>";
|
||||||
|
|
||||||
|
for (const std::string& column : row)
|
||||||
|
{
|
||||||
|
if (isInHeader)
|
||||||
|
{
|
||||||
|
result << "<th>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "<td>";
|
||||||
|
}
|
||||||
|
|
||||||
|
result << column;
|
||||||
|
|
||||||
|
if (isInHeader)
|
||||||
|
{
|
||||||
|
result << "</th>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "</td>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result << "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInHeader)
|
||||||
|
{
|
||||||
|
result << "</thead>";
|
||||||
|
}
|
||||||
|
else if (isInFooter)
|
||||||
|
{
|
||||||
|
result << "</tfoot>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "</tbody>";
|
||||||
|
}
|
||||||
|
|
||||||
|
isFirstBlock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result << "</table>";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
uint32_t currentBlock;
|
||||||
|
uint32_t currentRow;
|
||||||
|
std::vector<std::vector<std::vector<std::string>>> table;
|
||||||
|
}; // class TableParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
133
include/maddy/unorderedlistparser.h
Normal file
133
include/maddy/unorderedlistparser.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnorderedListParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class UnorderedListParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @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
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* An unordered list starts with `* `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^\\* .*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
bool isStartOfNewListItem = IsStartingLine(line);
|
||||||
|
uint32_t indentation = getIndentationWidth(line);
|
||||||
|
|
||||||
|
static std::regex lineRegex("^(\\* )");
|
||||||
|
line = std::regex_replace(line, lineRegex, "");
|
||||||
|
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<ul><li>" + line;
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indentation >= 2)
|
||||||
|
{
|
||||||
|
line = line.substr(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = "</li></ul>" + line;
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStartOfNewListItem)
|
||||||
|
{
|
||||||
|
line = "</li><li>" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class UnorderedListParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
14
libs/CMakeLists.txt
Normal file
14
libs/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# 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)
|
1
libs/gtest
Submodule
1
libs/gtest
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 5490beb0602eab560fa3969a4410e11d94bf12af
|
99
tests/maddy/test_maddy_checklistparser.cpp
Normal file
99
tests/maddy/test_maddy_checklistparser.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/checklistparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_CHECKLISTPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::ChecklistParser> clParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)> getBlockParserForLineCallback = [](const std::string& line)
|
||||||
|
{
|
||||||
|
if (maddy::ChecklistParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<maddy::BlockParser>(
|
||||||
|
std::make_shared<maddy::ChecklistParser>(nullptr, nullptr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<maddy::BlockParser> empty;
|
||||||
|
return empty;
|
||||||
|
};
|
||||||
|
|
||||||
|
this->clParser = std::make_shared<maddy::ChecklistParser>(
|
||||||
|
nullptr,
|
||||||
|
getBlockParserForLineCallback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_CHECKLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [ ] a"));
|
||||||
|
ASSERT_TRUE(maddy::ChecklistParser::IsStartingLine("- [x] b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_CHECKLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
|
||||||
|
{
|
||||||
|
ASSERT_FALSE(clParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
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>";
|
||||||
|
|
||||||
|
for (std::string md : markdown)
|
||||||
|
{
|
||||||
|
clParser->AddLine(md);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_TRUE(clParser->IsFinished());
|
||||||
|
|
||||||
|
std::stringstream& output(clParser->GetResult());
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_CHECKLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"- [ ] 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>";
|
||||||
|
|
||||||
|
for (std::string md : markdown)
|
||||||
|
{
|
||||||
|
clParser->AddLine(md);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_TRUE(clParser->IsFinished());
|
||||||
|
|
||||||
|
std::stringstream& output(clParser->GetResult());
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
61
tests/maddy/test_maddy_codeblockparser.cpp
Normal file
61
tests/maddy/test_maddy_codeblockparser.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/codeblockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_CODEBLOCKPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::CodeBlockParser> cbParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
this->cbParser = std::make_shared<maddy::CodeBlockParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_CODEBLOCKPARSER, IsStartingLineReturnsTrueWhenFacedWithThreeSigns)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::CodeBlockParser::IsStartingLine("```"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_CODEBLOCKPARSER, IsFinishedReturnsFalseInTheBeginning)
|
||||||
|
{
|
||||||
|
ASSERT_FALSE(cbParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_CODEBLOCKPARSER, ItReplacesMarkdownWithAnHtmlCodeBlock)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"```"
|
||||||
|
, "some code"
|
||||||
|
, "some other code"
|
||||||
|
, "```"
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
22
tests/maddy/test_maddy_emphasizedparser.cpp
Normal file
22
tests/maddy/test_maddy_emphasizedparser.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/emphasizedparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST(MADDY_EMPHASIZEDPARSER, ItReplacesMarkdownWithEmphasizedHTML)
|
||||||
|
{
|
||||||
|
std::string text = "some text *bla* text testing *it* out";
|
||||||
|
std::string expected = "some text <em>bla</em> text testing <em>it</em> out";
|
||||||
|
auto emphasizedParser = std::make_shared<maddy::EmphasizedParser>();
|
||||||
|
|
||||||
|
emphasizedParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
88
tests/maddy/test_maddy_headlineparser.cpp
Normal file
88
tests/maddy/test_maddy_headlineparser.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/headlineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_HEADLINEPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::HeadlineParser> hlParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
this->hlParser = std::make_shared<maddy::HeadlineParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_HEADLINEPARSER, IsStartingLineReturnsTrueWhenFacedWithOneToSixHashes)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("# a"));
|
||||||
|
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("## a"));
|
||||||
|
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("### a"));
|
||||||
|
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("#### a"));
|
||||||
|
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("##### a"));
|
||||||
|
ASSERT_TRUE(maddy::HeadlineParser::IsStartingLine("###### a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_HEADLINEPARSER, IsFinishedAlwaysReturnsTrue)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(hlParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_HEADLINEPARSER, ItReplacesMarkdownWithAnHtmlHeadline)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"# 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>"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
hlParser->AddLine(markdown[i]);
|
||||||
|
std::stringstream& output(hlParser->GetResult());
|
||||||
|
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected[i], outputString);
|
||||||
|
hlParser->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_HEADLINEPARSER, ItReplacesInvalidMarkdownNotWithAnHtmlHeadline)
|
||||||
|
{
|
||||||
|
std::string markdown = "####### a";
|
||||||
|
std::string expected(markdown);
|
||||||
|
|
||||||
|
hlParser->AddLine(markdown);
|
||||||
|
std::stringstream& output(hlParser->GetResult());
|
||||||
|
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
64
tests/maddy/test_maddy_horizontallineparser.cpp
Normal file
64
tests/maddy/test_maddy_horizontallineparser.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/horizontallineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_HORIZONTALLINEPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::HorizontalLineParser> hlParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
this->hlParser = std::make_shared<maddy::HorizontalLineParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_HORIZONTALLINEPARSER, IsStartingLineReturnsTrueWhenFacedWithThreeDashes)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::HorizontalLineParser::IsStartingLine("---"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_HORIZONTALLINEPARSER, IsFinishedAlwaysReturnsTrue)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(hlParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_HORIZONTALLINEPARSER, ItReplacesMarkdownWithAnHtmlLine)
|
||||||
|
{
|
||||||
|
std::string markdown = "---";
|
||||||
|
std::string expected = "<hr/>";
|
||||||
|
|
||||||
|
hlParser->AddLine(markdown);
|
||||||
|
std::stringstream& output(hlParser->GetResult());
|
||||||
|
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_HORIZONTALLINEPARSER, ItReplacesInvalidMarkdownNotWithAnHtmlLine)
|
||||||
|
{
|
||||||
|
std::string markdown = "--- ";
|
||||||
|
std::string expected(markdown);
|
||||||
|
|
||||||
|
hlParser->AddLine(markdown);
|
||||||
|
std::stringstream& output(hlParser->GetResult());
|
||||||
|
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
44
tests/maddy/test_maddy_imageparser.cpp
Normal file
44
tests/maddy/test_maddy_imageparser.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/imageparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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\"/>";
|
||||||
|
auto imageParser = std::make_shared<maddy::ImageParser>();
|
||||||
|
|
||||||
|
imageParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
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\"/>";
|
||||||
|
auto imageParser = std::make_shared<maddy::ImageParser>();
|
||||||
|
|
||||||
|
imageParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MADDY_IMAGEPARSER, ItReplacesNoLinkMarkdownWithImages)
|
||||||
|
{
|
||||||
|
std::string text = "Some text [Image Title](http://example.com)";
|
||||||
|
std::string expected(text);
|
||||||
|
auto imageParser = std::make_shared<maddy::ImageParser>();
|
||||||
|
|
||||||
|
imageParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
22
tests/maddy/test_maddy_inlinecodeparser.cpp
Normal file
22
tests/maddy/test_maddy_inlinecodeparser.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/inlinecodeparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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";
|
||||||
|
auto emphasizedParser = std::make_shared<maddy::InlineCodeParser>();
|
||||||
|
|
||||||
|
emphasizedParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
50
tests/maddy/test_maddy_linkparser.cpp
Normal file
50
tests/maddy/test_maddy_linkparser.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/linkparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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>";
|
||||||
|
auto linkParser = std::make_shared<maddy::LinkParser>();
|
||||||
|
|
||||||
|
linkParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
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>";
|
||||||
|
auto linkParser = std::make_shared<maddy::LinkParser>();
|
||||||
|
|
||||||
|
linkParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
TEST_F(DISABLED_MADDY_LINKPARSER, ItReplacesNoImageMarkdownWithLinks)
|
||||||
|
{
|
||||||
|
std::string text = "Some text ![Image Title](http://example.com/example.png)";
|
||||||
|
std::string expected(text);
|
||||||
|
auto linkParser = std::make_shared<maddy::LinkParser>();
|
||||||
|
|
||||||
|
linkParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
98
tests/maddy/test_maddy_orderedlistparser.cpp
Normal file
98
tests/maddy/test_maddy_orderedlistparser.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/orderedlistparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_ORDEREDLISTPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::OrderedListParser> olParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)> getBlockParserForLineCallback = [](const std::string& line)
|
||||||
|
{
|
||||||
|
if (maddy::OrderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<maddy::BlockParser>(
|
||||||
|
std::make_shared<maddy::OrderedListParser>(nullptr, nullptr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<maddy::BlockParser> empty;
|
||||||
|
return empty;
|
||||||
|
};
|
||||||
|
|
||||||
|
this->olParser = std::make_shared<maddy::OrderedListParser>(
|
||||||
|
nullptr,
|
||||||
|
getBlockParserForLineCallback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_ORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::OrderedListParser::IsStartingLine("1. a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_ORDEREDLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
|
||||||
|
{
|
||||||
|
ASSERT_FALSE(olParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_ORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlOrderedList)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"1. a"
|
||||||
|
, "* b"
|
||||||
|
, ""
|
||||||
|
};
|
||||||
|
std::string expected = "<ol><li>a</li><li>b</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, ItReplacesMarkdownWithAnHierachicalHtmlList)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"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>";
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
59
tests/maddy/test_maddy_paragraphparser.cpp
Normal file
59
tests/maddy/test_maddy_paragraphparser.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/paragraphparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_PARAGRAPHPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::ParagraphParser> pParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
this->pParser = std::make_shared<maddy::ParagraphParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_PARAGRAPHPARSER, IsStartingLineReturnsTrueWhenFacedWithThreeDashes)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::ParagraphParser::IsStartingLine("---"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_PARAGRAPHPARSER, IsFinishedReturnsFalseInTheBeginning)
|
||||||
|
{
|
||||||
|
ASSERT_FALSE(pParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_PARAGRAPHPARSER, ItReplacesMarkdownWithAnHtmlLine)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
pParser->AddLine(md);
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(pParser->IsFinished());
|
||||||
|
|
||||||
|
std::stringstream& output(pParser->GetResult());
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
21
tests/maddy/test_maddy_parser.cpp
Normal file
21
tests/maddy/test_maddy_parser.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/parser.h"
|
||||||
|
#include "maddy/test_maddy_parser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST(MADDY_PARSER, ItShouldParse)
|
||||||
|
{
|
||||||
|
auto parser = std::make_shared<maddy::Parser>();
|
||||||
|
std::stringstream markdown(testMarkdown);
|
||||||
|
|
||||||
|
const std::string output = parser->Parse(markdown);
|
||||||
|
|
||||||
|
ASSERT_EQ(testHtml, output);
|
||||||
|
}
|
70
tests/maddy/test_maddy_parser.h
Normal file
70
tests/maddy/test_maddy_parser.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
const std::string testMarkdown = "# This is a test\n\
|
||||||
|
\n\
|
||||||
|
This should result in a praragraph\n\
|
||||||
|
it's that simple.\n\
|
||||||
|
\n\
|
||||||
|
* an unordered list\n\
|
||||||
|
* with some **hierarchy**\n\
|
||||||
|
1. and an *ordered*\n\
|
||||||
|
* list\n\
|
||||||
|
* directly\n\
|
||||||
|
* inside\n\
|
||||||
|
\n\
|
||||||
|
```\n\
|
||||||
|
var c = 'blub';\n\
|
||||||
|
```\n\
|
||||||
|
\n\
|
||||||
|
> A Quote\n\
|
||||||
|
>\n\
|
||||||
|
> With some ~~text~~ blocks inside\n\
|
||||||
|
>\n\
|
||||||
|
> * even a list\n\
|
||||||
|
> * should be\n\
|
||||||
|
> * possible\n\
|
||||||
|
>\n\
|
||||||
|
\n\
|
||||||
|
And well `inline code` should also work.\n\
|
||||||
|
\n\
|
||||||
|
## Another Headline\n\
|
||||||
|
\n\
|
||||||
|
And not to forget [link to progsource](http://progsource.de) should work.\n\
|
||||||
|
And well - let's see how an image would be shown:\n\
|
||||||
|
\n\
|
||||||
|
![an image](http://progsource.de/img/progsource.png)\n\
|
||||||
|
\n\
|
||||||
|
---\n\
|
||||||
|
\n\
|
||||||
|
### and more headlines\n\
|
||||||
|
\n\
|
||||||
|
- [ ] how\n\
|
||||||
|
- [ ] about\n\
|
||||||
|
- [ ] a\n\
|
||||||
|
- [x] nice\n\
|
||||||
|
- [x] check\n\
|
||||||
|
- [ ] list\n\
|
||||||
|
\n\
|
||||||
|
#### even a table\n\
|
||||||
|
\n\
|
||||||
|
|table>\n\
|
||||||
|
Left header|middle header|last header\n\
|
||||||
|
- | - | -\n\
|
||||||
|
cell 1|cell **2**|cell 3\n\
|
||||||
|
cell 4|cell 5|cell 6\n\
|
||||||
|
- | - | -\n\
|
||||||
|
foot a|foot b|foot c\n\
|
||||||
|
|<table\n\
|
||||||
|
\n\
|
||||||
|
##### h5\n\
|
||||||
|
###### h6\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 unordered 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/><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>";
|
62
tests/maddy/test_maddy_quoteparser.cpp
Normal file
62
tests/maddy/test_maddy_quoteparser.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/quoteparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_QUOTEPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::QuoteParser> quoteParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
this->quoteParser = std::make_shared<maddy::QuoteParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_QUOTEPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfAQuote)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::QuoteParser::IsStartingLine("> a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_QUOTEPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
|
||||||
|
{
|
||||||
|
ASSERT_FALSE(quoteParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_QUOTEPARSER, ItReplacesMarkdownWithAnHtmlBlockQuote)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"> a"
|
||||||
|
, "> b"
|
||||||
|
, ">"
|
||||||
|
, "> c"
|
||||||
|
, ""
|
||||||
|
};
|
||||||
|
std::string expected = "<blockquote>a b c </blockquote>";
|
||||||
|
|
||||||
|
for (std::string md : markdown)
|
||||||
|
{
|
||||||
|
quoteParser->AddLine(md);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_TRUE(quoteParser->IsFinished());
|
||||||
|
|
||||||
|
std::stringstream& output(quoteParser->GetResult());
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
22
tests/maddy/test_maddy_strikethroughparser.cpp
Normal file
22
tests/maddy/test_maddy_strikethroughparser.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/strikethroughparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST(MADDY_STRIKETHROUGHPARSER, ItReplacesMarkdownWithStrikeThroughHTML)
|
||||||
|
{
|
||||||
|
std::string text = "some text ~~bla~~ text testing ~~it~~ out";
|
||||||
|
std::string expected = "some text <s>bla</s> text testing <s>it</s> out";
|
||||||
|
auto strikeThroughParser = std::make_shared<maddy::StrikeThroughParser>();
|
||||||
|
|
||||||
|
strikeThroughParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
33
tests/maddy/test_maddy_strongparser.cpp
Normal file
33
tests/maddy/test_maddy_strongparser.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/strongparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST(MADDY_STRONGPARSER, ItReplacesMarkdownWithStrongHTML)
|
||||||
|
{
|
||||||
|
std::string text = "some text **bla** text testing **it** out";
|
||||||
|
std::string expected = "some text <strong>bla</strong> text testing <strong>it</strong> out";
|
||||||
|
auto strongParser = std::make_shared<maddy::StrongParser>();
|
||||||
|
|
||||||
|
strongParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MADDY_STRONGPARSER, ItReplacesEmphasizedMarkdownNotWithStrongHTML)
|
||||||
|
{
|
||||||
|
std::string text = "some text *bla* text testing **it** out";
|
||||||
|
std::string expected = "some text *bla* text testing <strong>it</strong> out";
|
||||||
|
auto strongParser = std::make_shared<maddy::StrongParser>();
|
||||||
|
|
||||||
|
strongParser->Parse(text);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, text);
|
||||||
|
}
|
66
tests/maddy/test_maddy_tableparser.cpp
Normal file
66
tests/maddy/test_maddy_tableparser.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/tableparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_TABLEPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::TableParser> tableParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
this->tableParser = std::make_shared<maddy::TableParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_TABLEPARSER, IsStartingLineReturnsTrueWhenFacedWithTheBeginningOfATable)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(true, maddy::TableParser::IsStartingLine("|table>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_TABLEPARSER, IsFinishedReturnsFalseInTheBeginning)
|
||||||
|
{
|
||||||
|
ASSERT_FALSE(tableParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
};
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
tableParser->AddLine(md);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_TRUE(tableParser->IsFinished());
|
||||||
|
|
||||||
|
std::stringstream& output(tableParser->GetResult());
|
||||||
|
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
98
tests/maddy/test_maddy_unorderedlistparser.cpp
Normal file
98
tests/maddy/test_maddy_unorderedlistparser.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "maddy/unorderedlistparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MADDY_UNORDEREDLISTPARSER : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<maddy::UnorderedListParser> ulParser;
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp() override
|
||||||
|
{
|
||||||
|
std::function<std::shared_ptr<maddy::BlockParser>(const std::string& line)> getBlockParserForLineCallback = [](const std::string& line)
|
||||||
|
{
|
||||||
|
if (maddy::UnorderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<maddy::BlockParser>(
|
||||||
|
std::make_shared<maddy::UnorderedListParser>(nullptr, nullptr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<maddy::BlockParser> empty;
|
||||||
|
return empty;
|
||||||
|
};
|
||||||
|
|
||||||
|
this->ulParser = std::make_shared<maddy::UnorderedListParser>(
|
||||||
|
nullptr,
|
||||||
|
getBlockParserForLineCallback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(MADDY_UNORDEREDLISTPARSER, IsStartingLineReturnsTrueWhenFacedWithBeginningOfList)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(maddy::UnorderedListParser::IsStartingLine("* a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_UNORDEREDLISTPARSER, IsFinishedAlwaysReturnsFalseInTheBeginning)
|
||||||
|
{
|
||||||
|
ASSERT_FALSE(ulParser->IsFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHtmlUnorderedList)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"* a"
|
||||||
|
, "* b"
|
||||||
|
, ""
|
||||||
|
};
|
||||||
|
std::string expected = "<ul><li>a</li><li>b</li></ul>";
|
||||||
|
|
||||||
|
for (std::string md : markdown)
|
||||||
|
{
|
||||||
|
ulParser->AddLine(md);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_TRUE(ulParser->IsFinished());
|
||||||
|
|
||||||
|
std::stringstream& output(ulParser->GetResult());
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MADDY_UNORDEREDLISTPARSER, ItReplacesMarkdownWithAnHierachicalHtmlList)
|
||||||
|
{
|
||||||
|
std::vector<std::string> markdown = {
|
||||||
|
"* a"
|
||||||
|
, " * d"
|
||||||
|
, " * e"
|
||||||
|
, "* b"
|
||||||
|
, " * c"
|
||||||
|
, ""
|
||||||
|
};
|
||||||
|
std::string expected = "<ul><li>a<ul><li>d</li><li>e</li></ul></li><li>b<ul><li>c</li></ul></li></ul>";
|
||||||
|
|
||||||
|
for (std::string md : markdown)
|
||||||
|
{
|
||||||
|
ulParser->AddLine(md);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_TRUE(ulParser->IsFinished());
|
||||||
|
|
||||||
|
std::stringstream& output(ulParser->GetResult());
|
||||||
|
const std::string& outputString = output.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, outputString);
|
||||||
|
}
|
14
tests/main.cpp
Normal file
14
tests/main.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int main (int argc, char** argv) {
|
||||||
|
::testing::GTEST_FLAG(throw_on_failure) = false;
|
||||||
|
::testing::InitGoogleMock(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user