Add pandoc wrapper
This commit is contained in:
parent
40664db80d
commit
1ac5768b14
@ -41,5 +41,6 @@ include(
|
||||
":snark-gradle-plugin",
|
||||
":snark-core",
|
||||
":snark-html",
|
||||
":snark-ktor"
|
||||
":snark-ktor",
|
||||
":snark-pandoc"
|
||||
)
|
66
snark-pandoc/README.md
Normal file
66
snark-pandoc/README.md
Normal file
@ -0,0 +1,66 @@
|
||||
## Examples
|
||||
### Simple converting
|
||||
Convert from INPUT_FILE to OUTPUT_FILE:
|
||||
```java
|
||||
PandocWrapper wrapper = new PandocWrapper();
|
||||
wrapper.use(p -> {
|
||||
var command = new PandocCommandBuilder(List.of(INPUT_FILE), OUTPUT_FILE);
|
||||
PandocWrapper.execute(command);
|
||||
});
|
||||
```
|
||||
Equal to:
|
||||
```
|
||||
pandoc --output=OUTPUT_FILE INPUT_FILE
|
||||
```
|
||||
### Convert and set formats
|
||||
Convert from INPUT_FILE to OUTPUT_FILE and set INPUT_FORMAT and OUTPUT_FORMAT:
|
||||
```java
|
||||
PandocWrapper wrapper = new PandocWrapper();
|
||||
wrapper.use(p -> {
|
||||
var command = new PandocCommandBuilder(List.of(INPUT_FILE), OUTPUT_FILE);
|
||||
command.formatForm(INPUT_FORMAT);
|
||||
command.formatTo(OUTPUT_FORMAT);
|
||||
PandocWrapper.execute(command);
|
||||
});
|
||||
```
|
||||
Equal to:
|
||||
```
|
||||
pandoc --output=OUTPUT_FILE --from=INPUT_FORMAT --to=OUTPUT_FORMAT INPUT_FILE
|
||||
```
|
||||
### Converting with options
|
||||
Convert from INPUT_FILE to standalone OUTPUT_FILE and set variable KEY to VALUE :
|
||||
```java
|
||||
PandocWrapper wrapper = new PandocWrapper();
|
||||
wrapper.use(p -> {
|
||||
var command = new PandocCommandBuilder(List.of(INPUT_FILE), OUTPUT_FILE);
|
||||
command.standalone();
|
||||
command.setVariable(KEY, VALUE);
|
||||
PandocWrapper.execute(command);
|
||||
});
|
||||
```
|
||||
Equal to:
|
||||
```
|
||||
pandoc --output=OUTPUT_FILE --standalone --variable=KEY:VALUE INPUT_FILE
|
||||
```
|
||||
|
||||
### Write output from pandoc to file
|
||||
Receive possible input formats in OUTPUT_FILE:
|
||||
```java
|
||||
PandocWrapper wrapper = new PandocWrapper();
|
||||
wrapper.use(p -> {
|
||||
var command = new PandocCommandBuilder();
|
||||
command.getInputFormats();
|
||||
PandocWrapper.execute(command, OUTPUT_FILE);
|
||||
});
|
||||
```
|
||||
Then in OUTPUT_FILE will be a list supported input formats, one per line.
|
||||
|
||||
### Write errors from pandoc to file
|
||||
Receive all from error stream and exit code in ERROR_FILE and output in OUTPUT_FILE:
|
||||
```java
|
||||
PandocWrapper wrapper = new PandocWrapper();
|
||||
wrapper.use(p -> {
|
||||
var command = new PandocCommandBuilder(List.of(INPUT_FILE), OUTPUT_FILE);
|
||||
PandocWrapper.execute(command, OUTPUT_FILE, ERROR_FILE);
|
||||
});
|
||||
```
|
20
snark-pandoc/build.gradle.kts
Normal file
20
snark-pandoc/build.gradle.kts
Normal file
@ -0,0 +1,20 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
}
|
||||
|
||||
|
||||
kscience {
|
||||
useSerialization {
|
||||
json()
|
||||
}
|
||||
jvm()
|
||||
jvmMain {
|
||||
api(spclibs.slf4j)
|
||||
implementation("org.apache.commons:commons-exec:1.3")
|
||||
implementation("org.apache.commons:commons-compress:1.2")
|
||||
}
|
||||
jvmTest{
|
||||
implementation(spclibs.logback.classic)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package space.kscience.snark.pandoc
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardOpenOption
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.io.path.Path
|
||||
|
||||
public object Pandoc {
|
||||
private val logger: Logger = LoggerFactory.getLogger(Pandoc::class.java)
|
||||
|
||||
private fun getOrInstallPandoc(pandocExecutablePath: Path): String = try {
|
||||
ProcessBuilder("pandoc", "--version").start().waitFor()
|
||||
"pandoc"
|
||||
} catch (ex: IOException) {
|
||||
if (Files.exists(pandocExecutablePath)) {
|
||||
pandocExecutablePath.toAbsolutePath().toString()
|
||||
} else {
|
||||
logger.info("Pandoc not found in the system. Installing it from GitHub")
|
||||
PandocInstaller.installPandoc(pandocExecutablePath).toAbsolutePath().toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call pandoc with options described by commandBuilder.
|
||||
* @param commandBuilder
|
||||
* @return true if successfully false otherwise
|
||||
*/
|
||||
public fun execute(
|
||||
redirectOutput: Path? = null,
|
||||
redirectError: Path? = null,
|
||||
pandocExecutablePath: Path = Path("./pandoc").toAbsolutePath(),
|
||||
commandBuilder: PandocCommandBuilder.() -> Unit,
|
||||
): Boolean {
|
||||
|
||||
val path = getOrInstallPandoc(pandocExecutablePath)
|
||||
|
||||
try {
|
||||
val commandLine = PandocCommandBuilder().apply(commandBuilder).build(path)
|
||||
logger.info("Running pandoc: ${commandLine.joinToString(separator = " ")}")
|
||||
val pandoc = ProcessBuilder(commandLine).apply {
|
||||
if(redirectOutput!= null){
|
||||
redirectOutput(redirectOutput.toFile())
|
||||
}
|
||||
if(redirectError !=null){
|
||||
redirectError(redirectError.toFile())
|
||||
}
|
||||
|
||||
}.start()
|
||||
pandoc.waitFor(1, TimeUnit.SECONDS)
|
||||
|
||||
if (pandoc.exitValue() == 0) {
|
||||
logger.info("Successfully execute")
|
||||
return true
|
||||
} else{
|
||||
return false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.error("Got problems with executing: " + e.message)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,264 @@
|
||||
package space.kscience.snark.pandoc
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
|
||||
import org.apache.commons.exec.OS
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.net.*
|
||||
import java.net.http.HttpClient
|
||||
import java.net.http.HttpRequest
|
||||
import java.net.http.HttpResponse
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.attribute.PosixFilePermission
|
||||
import java.time.Duration
|
||||
import java.util.*
|
||||
import java.util.zip.ZipInputStream
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.inputStream
|
||||
|
||||
internal object PandocInstaller {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(PandocInstaller::class.java)
|
||||
|
||||
|
||||
private const val TIMEOUT_SECONDS = 2
|
||||
private const val ATTEMPTS = 3
|
||||
|
||||
private enum class OSType(public val assetSuffix: String, public val propertySuffix: String) {
|
||||
WINDOWS("windows-x86_64.zip", "windows"),
|
||||
MAC_OS_AMD("x86_64-macOS.zip", "mac.os.amd"),
|
||||
MAC_OS_ARM("arm64-macOS.zip", "mac.os.arm"),
|
||||
LINUX_ARM("linux-arm64", "linux.arm"),
|
||||
LINUX_AMD("linux-amd64", "linux.amd")
|
||||
}
|
||||
|
||||
private val properties = Properties().apply {
|
||||
load(PandocInstaller.javaClass.getResourceAsStream("/installer.properties")!!)
|
||||
}
|
||||
|
||||
/**
|
||||
* Install last released pandoc from github
|
||||
* @return path to executable pandoc
|
||||
* @throws IOException in case incorrect github url or path of installation directory
|
||||
*/
|
||||
public fun installPandoc(targetPath: Path): Path {
|
||||
log.info("Start install")
|
||||
return if (OS.isFamilyMac()) {
|
||||
if (OS.isArch("aarch64")) {
|
||||
installPandoc(OSType.MAC_OS_ARM, targetPath)
|
||||
} else {
|
||||
installPandoc(OSType.MAC_OS_AMD, targetPath)
|
||||
}
|
||||
} else if (OS.isFamilyUnix()) {
|
||||
if (OS.isArch("aarch64")) {
|
||||
installPandoc(OSType.LINUX_ARM, targetPath)
|
||||
} else {
|
||||
installPandoc(OSType.LINUX_AMD, targetPath)
|
||||
}
|
||||
} else if (OS.isFamilyWindows()) {
|
||||
installPandoc(OSType.WINDOWS, targetPath)
|
||||
} else {
|
||||
error("Got unexpected os, could not install pandoc")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun installPandoc(os: OSType, targetPath: Path): Path {
|
||||
|
||||
val githubResponse = getGithubUrls()
|
||||
val asset = githubResponse.getAssetByOsSuffix(os.assetSuffix)
|
||||
val currUrl = asset.browserDownloadUrl
|
||||
|
||||
val pandocUrl: URL = URI.create(currUrl).toURL()
|
||||
val fileToInstall: Path = when (os) {
|
||||
OSType.LINUX_AMD, OSType.LINUX_ARM -> Path("$targetPath/pandoc.tar.gz")
|
||||
else -> Path("$targetPath/pandoc.zip")
|
||||
}
|
||||
|
||||
log.info(
|
||||
"Start installing pandoc os: {}, url: {}, file: {}",
|
||||
os,
|
||||
pandocUrl,
|
||||
fileToInstall
|
||||
)
|
||||
|
||||
val archivePath = downloadWithRetry(pandocUrl) ?: error("Could not save file from github")
|
||||
val installPath = unPack(archivePath, targetPath, os) ?: error("Could not unzip file")
|
||||
|
||||
|
||||
val pandocExecutablePath = installPath.resolve(
|
||||
properties.getProperty("path.to.pandoc." + os.propertySuffix).replace(
|
||||
"{version}",
|
||||
githubResponse.tagName
|
||||
)
|
||||
)
|
||||
|
||||
Files.setPosixFilePermissions(pandocExecutablePath, setOf(PosixFilePermission.GROUP_EXECUTE))
|
||||
|
||||
return pandocExecutablePath
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads from a (http/https) URL and saves to a file.
|
||||
* @param target File to write. Parent directory will be created if necessary
|
||||
* @param url http/https url to connect
|
||||
* @param secsConnectTimeout Seconds to wait for connection establishment
|
||||
* @param secsReadTimeout Read timeout in seconds - trasmission will abort if it freezes more than this
|
||||
* @return true if successfully save file and false if:
|
||||
* connection interrupted, timeout (but something was read)
|
||||
* server error (500...)
|
||||
* could not connect: connection timeout java.net.SocketTimeoutException
|
||||
* could not connect: java.net.ConnectException
|
||||
* could not resolve host (bad host, or no internet - no dns)
|
||||
* @throws IOException Only if URL is malformed or if could not create the file
|
||||
* @throws FileNotFoundException if did not find file for save
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
private fun downloadUrl(
|
||||
target: Path,
|
||||
url: URL,
|
||||
secsConnectTimeout: Int,
|
||||
secsReadTimeout: Int,
|
||||
): Path? {
|
||||
Files.createDirectories(target.parent) // make sure parent dir exists , this can throw exception
|
||||
val conn = url.openConnection() // can throw exception if bad url
|
||||
if (secsConnectTimeout > 0) {
|
||||
conn.connectTimeout = secsConnectTimeout * 1000
|
||||
}
|
||||
if (secsReadTimeout > 0) {
|
||||
conn.readTimeout = secsReadTimeout * 1000
|
||||
}
|
||||
var ret = true
|
||||
var somethingRead = false
|
||||
try {
|
||||
conn.getInputStream().use { `is` ->
|
||||
BufferedInputStream(`is`).use { `in` ->
|
||||
Files.newOutputStream(target).use { fout ->
|
||||
val data = ByteArray(8192)
|
||||
var count: Int
|
||||
while ((`in`.read(data).also { count = it }) > 0) {
|
||||
somethingRead = true
|
||||
fout.write(data, 0, count)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target
|
||||
} catch (e: IOException) {
|
||||
var httpcode = 999
|
||||
try {
|
||||
httpcode = (conn as HttpURLConnection).responseCode
|
||||
} catch (ee: Exception) {
|
||||
}
|
||||
|
||||
if (e is FileNotFoundException) {
|
||||
throw FileNotFoundException("Did not found file for install")
|
||||
}
|
||||
|
||||
if (somethingRead && e is SocketTimeoutException) {
|
||||
log.error("Read something, but connection interrupted: {}", e.message, e)
|
||||
} else if (httpcode >= 400 && httpcode < 600) {
|
||||
log.error("Got server error, httpcode: {}", httpcode)
|
||||
} else if (e is SocketTimeoutException) {
|
||||
log.error("Connection timeout: {}", e.message, e)
|
||||
} else if (e is ConnectException) {
|
||||
log.error("Could not connect: {}", e.message, e)
|
||||
} else if (e is UnknownHostException) {
|
||||
log.error("Could not resolve host: {}", e.message, e)
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadWithRetry(url: URL): Path? {
|
||||
val targetPath = Files.createTempFile("pandoc",".tmp")
|
||||
log.info("Downloading pandoc to $targetPath")
|
||||
|
||||
repeat(ATTEMPTS) {
|
||||
return downloadUrl(
|
||||
targetPath,
|
||||
url,
|
||||
TIMEOUT_SECONDS,
|
||||
TIMEOUT_SECONDS
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun unPack(sourcePath: Path, targetPath: Path, os: OSType): Path? {
|
||||
try {
|
||||
when (os) {
|
||||
OSType.LINUX_AMD, OSType.LINUX_ARM -> unTarGz(sourcePath, targetPath)
|
||||
|
||||
else -> unZip(sourcePath, targetPath)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
log.error("Could not perform unpacking: {}", e.message, e)
|
||||
return null
|
||||
}
|
||||
return targetPath
|
||||
}
|
||||
|
||||
private fun unTarGz(sourcePath: Path, targetDir: Path) {
|
||||
TarArchiveInputStream(
|
||||
GzipCompressorInputStream(
|
||||
BufferedInputStream(Files.newInputStream(sourcePath))
|
||||
)
|
||||
).use { tarIn ->
|
||||
var archiveEntry: ArchiveEntry
|
||||
while ((tarIn.nextEntry.also { archiveEntry = it }) != null) {
|
||||
val pathEntryOutput = targetDir.resolve(archiveEntry.name)
|
||||
if (archiveEntry.isDirectory) {
|
||||
Files.createDirectory(pathEntryOutput)
|
||||
} else {
|
||||
Files.copy(tarIn, pathEntryOutput)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun unZip(sourcePath: Path, targetDir: Path) {
|
||||
ZipInputStream(sourcePath.inputStream()).use { zis ->
|
||||
do {
|
||||
val entry = zis.nextEntry
|
||||
if (entry == null) continue
|
||||
val pathEntryOutput = targetDir.resolve(entry.name)
|
||||
if (entry.isDirectory) {
|
||||
Files.createDirectories(pathEntryOutput)
|
||||
} else {
|
||||
Files.createDirectories(pathEntryOutput.parent)
|
||||
Files.copy(zis, pathEntryOutput)
|
||||
}
|
||||
zis.closeEntry()
|
||||
} while (entry != null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGithubUrls(): ResponseDto {
|
||||
val uri = URI.create(properties.getProperty("github.url"))
|
||||
val client = HttpClient.newHttpClient()
|
||||
val request = HttpRequest
|
||||
.newBuilder()
|
||||
.uri(uri)
|
||||
.version(HttpClient.Version.HTTP_2)
|
||||
.timeout(Duration.ofMinutes(1))
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.GET()
|
||||
.build()
|
||||
|
||||
val response = client.send(request, HttpResponse.BodyHandlers.ofString())
|
||||
log.info("Got response from github, status: {}", response.statusCode())
|
||||
|
||||
return Json { ignoreUnknownKeys = true }.decodeFromString(ResponseDto.serializer(), response.body())
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package space.kscience.snark.pandoc
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Response from github/releases/latest
|
||||
*/
|
||||
@Serializable
|
||||
internal class ResponseDto(
|
||||
val assets: Array<AssetDto>,
|
||||
@SerialName("tag_name") val tagName: String,
|
||||
) {
|
||||
/**
|
||||
* @param osSuffix
|
||||
* @return asset appropriate to os
|
||||
*/
|
||||
fun getAssetByOsSuffix(osSuffix: String?): AssetDto {
|
||||
for (asset in assets) {
|
||||
if (asset.name.contains(osSuffix!!)) {
|
||||
return asset
|
||||
}
|
||||
}
|
||||
throw IllegalArgumentException("Unexpected osSuffix")
|
||||
}
|
||||
|
||||
|
||||
@Serializable
|
||||
public class AssetDto(
|
||||
@SerialName("browser_download_url") val browserDownloadUrl: String,
|
||||
val name: String
|
||||
)
|
||||
|
||||
}
|
8
snark-pandoc/src/jvmMain/resources/installer.properties
Normal file
8
snark-pandoc/src/jvmMain/resources/installer.properties
Normal file
@ -0,0 +1,8 @@
|
||||
path.to.pandoc.mac.os.arm=/pandoc-{version}-arm64/bin/pandoc
|
||||
path.to.pandoc.mac.os.amd=/pandoc-{version}-x86_64/bin/pandoc
|
||||
path.to.pandoc.windows=/pandoc-{version}/pandoc.exe
|
||||
path.to.pandoc.linux.amd=/pandoc-{version}/bin/pandoc
|
||||
path.to.pandoc.linux.arm=/pandoc-{version}/bin/pandoc
|
||||
|
||||
github.url=https://api.github.com/repos/jgm/pandoc/releases/latest
|
||||
|
111
snark-pandoc/src/jvmTest/kotlin/PandocTest.kt
Normal file
111
snark-pandoc/src/jvmTest/kotlin/PandocTest.kt
Normal file
@ -0,0 +1,111 @@
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import space.kscience.snark.pandoc.Pandoc
|
||||
import java.io.BufferedReader
|
||||
import java.io.FileReader
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.stream.Collectors
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.div
|
||||
|
||||
class PandocTest {
|
||||
@Test
|
||||
fun when_gotPandocAndCorrectArgs_doConverting() {
|
||||
try {
|
||||
val res = Pandoc.execute {
|
||||
addInputFile(CORRECT_MD)
|
||||
outputFile(TEX_PATH_TO)
|
||||
}
|
||||
assertTrue(res)
|
||||
assertTrue(TEX_PATH_TO.toFile().exists())
|
||||
|
||||
val reader = BufferedReader(FileReader(TEX_PATH_TO.toFile()))
|
||||
val fileString = reader.lines().collect(Collectors.joining())
|
||||
|
||||
assertTrue(fileString.contains("Some simple text"))
|
||||
assertTrue(fileString.contains("\\subsection{Copy elision}"))
|
||||
assertTrue(fileString.contains("return"))
|
||||
|
||||
Files.delete(TEX_PATH_TO)
|
||||
} catch (ex: Exception) {
|
||||
fail<Any>("Unexpected exception during test when_gotPandocAndCorrectArgs_doConverting()", ex)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun when_gotPandocAndNotExistsFromFile_then_error() {
|
||||
val notExistsFile = Path.of("./src/test/testing_directory/non_exists_test.md")
|
||||
assertFalse(notExistsFile.toFile().exists())
|
||||
val res = Pandoc.execute {
|
||||
addInputFile(notExistsFile)
|
||||
outputFile(TEX_PATH_TO)
|
||||
}
|
||||
assertFalse(res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun when_gotPandocAndPassDirectory_then_error() {
|
||||
assertTrue(TESTING_DIRECTORY.toFile().isDirectory)
|
||||
|
||||
val res = Pandoc.execute {
|
||||
addInputFile(TESTING_DIRECTORY)
|
||||
outputFile(TEX_PATH_TO)
|
||||
}
|
||||
|
||||
assertFalse(res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun when_askVersionToFile_then_Ok() {
|
||||
val outputFile = TESTING_DIRECTORY/"output.txt"
|
||||
|
||||
val res = Pandoc.execute(redirectOutput = outputFile) {
|
||||
getVersion()
|
||||
}
|
||||
|
||||
val reader = BufferedReader(FileReader(outputFile.toFile()))
|
||||
val fileString = reader.lines().collect(Collectors.joining())
|
||||
assertTrue(fileString.contains("pandoc"))
|
||||
assertTrue(fileString.contains("This is free software"))
|
||||
assertTrue(res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun when_error_then_writeToErrorStream() {
|
||||
val outputFile = Files.createTempFile(TESTING_DIRECTORY, "output", ".txt")
|
||||
val errorFile = Files.createTempFile(TESTING_DIRECTORY, "error", ".txt")
|
||||
|
||||
val res = Pandoc.execute(outputFile, errorFile) {
|
||||
addInputFile(Path.of("./simple.txt"))
|
||||
outputFile(TEX_PATH_TO)
|
||||
formatFrom("txt")
|
||||
}
|
||||
|
||||
val reader = BufferedReader(FileReader(errorFile.toFile()))
|
||||
val fileString = reader.lines().collect(Collectors.joining())
|
||||
assertFalse(res)
|
||||
assertTrue(fileString.contains("21"))
|
||||
|
||||
Files.delete(outputFile)
|
||||
Files.delete(errorFile)
|
||||
}
|
||||
|
||||
|
||||
// @Test
|
||||
// fun when_installPandoc_thenFindIt() {
|
||||
// PandocInstaller.clearInstallingDirectory()
|
||||
// assertTrue(Pandoc.installPandoc())
|
||||
// assertTrue(Pandoc.isPandocInstalled())
|
||||
// }
|
||||
|
||||
companion object {
|
||||
private val TESTING_DIRECTORY: Path = Path("./testing_directory").apply {
|
||||
createDirectories()
|
||||
}
|
||||
private val CORRECT_MD: Path = TESTING_DIRECTORY.resolve("first_test.md")
|
||||
private val TEX_PATH_TO: Path = TESTING_DIRECTORY.resolve("output1.tex")
|
||||
}
|
||||
}
|
15
snark-pandoc/testing_directory/first_test.md
Normal file
15
snark-pandoc/testing_directory/first_test.md
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
|
||||
## Copy elision
|
||||
### RVO/NRVO
|
||||
Some simple text
|
||||
```c++
|
||||
A f() {
|
||||
return {5};
|
||||
}
|
||||
|
||||
A g() {
|
||||
A a(5);
|
||||
return a;
|
||||
}
|
||||
```
|
1
snark-pandoc/testing_directory/simple.txt
Normal file
1
snark-pandoc/testing_directory/simple.txt
Normal file
@ -0,0 +1 @@
|
||||
hello
|
Loading…
Reference in New Issue
Block a user