diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..5e8201ff
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,16 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ - package-ecosystem: "maven" # See documentation for possible values
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "daily"
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 27e606de..681537f7 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,78 +1,44 @@
-name: Build and package
+name: Build and Deploy Snapshots
on:
push:
branches:
- master
- tags:
- - 'v*'
- workflow_dispatch:
- inputs:
- version:
- description: 'Version to create release for if not empty'
- required: false
- default: ''
-
jobs:
build:
runs-on: ubuntu-latest
-
+ permissions:
+ contents: write
+ packages: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
- uses: actions/setup-java@v4
+ uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
cache: maven
-# To handle both tag and manual runs, run a script that will define all required vars
- - name: Define version to build
- run: ./.github/define_release_version.sh ${{ github.event.inputs.version }}
-
-# Building application
- - name: Build with Maven
- run: mvn --batch-mode verify -DversionSuffix=$RELEASE_VERSION_SUFFIX
- - run: mkdir dist && cp cli/target/*.tar.gz dist
- - uses: actions/upload-artifact@v4
- if: env.RELEASE_VERSION == ''
- with:
- name: cli.tar.gz
- path: dist
- retention-days: 20
-
-# Pushing to docker registry
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_HUB_USER }}
- password: ${{ secrets.DOCKER_HUB_TOKEN }}
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Build and push
- uses: docker/build-push-action@v5
- with:
- context: ./cli
- platforms: linux/amd64,linux/arm64
- push: true
- tags: ${{ secrets.DOCKER_HUB_USER }}/text2confl:${{env.RELEASE_DOCKER_TAG}}
- build-args: |
- VERSION=${{env.RELEASE_VERSION_SUFFIX}}
- cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USER }}/text2confl:buildcache
- cache-to: type=registry,ref=${{ secrets.DOCKER_HUB_USER }}/text2confl:buildcache,mode=max
-
-# If there is a tag trigger, creating release
- - name: Compute changelog
- run: ./.github/create_release_changes.sh
- if: startsWith(github.ref, 'refs/tags/')
- - name: Create github release
- uses: softprops/action-gh-release@v1
- if: startsWith(github.ref, 'refs/tags/')
+ - name: Deploy to Github packages
+ run: mvn --batch-mode clean deploy -Pgithub,coverage
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v3
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+ - name: Set up Java for publishing to Maven Central Repository
+ uses: actions/setup-java@v3
with:
- name: ${{env.RELEASE_VERSION}}
- body_path: target/ci/CHANGELOG.md
- token: ${{ secrets.RELEASE_TOKEN }}
- files: |
- dist/*.tar.gz
+ java-version: '11'
+ distribution: 'temurin'
+ cache: maven
+ server-id: ossrh
+ server-username: MAVEN_USERNAME
+ server-password: MAVEN_PASSWORD
+ gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
+ gpg-passphrase: MAVEN_GPG_PASSPHRASE
+ - name: Publish to the Maven Central Repository
+ run: mvn --batch-mode clean deploy -Possrh
env:
- GITHUB_REPOSITORY: zeldigas/text2confl
\ No newline at end of file
+ MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index c79fd0c7..f4d036a9 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -18,21 +18,8 @@ jobs:
distribution: 'adopt'
cache: maven
- name: Build with Maven
- run: mvn --batch-mode verify
- - run: mkdir dist && cp cli/target/*.tar.gz dist
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Build docker image
- uses: docker/build-push-action@v5
- with:
- context: ./cli
- platforms: linux/amd64,linux/arm64
- push: false
- cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USER }}/text2confl:buildcache
- - uses: actions/upload-artifact@v4
- with:
- name: cli.tar.gz
- path: dist
- retention-days: 7
\ No newline at end of file
+ run: mvn --batch-mode verify -Pcoverage
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v3
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..883c2879
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,67 @@
+name: Release New Version
+on:
+ workflow_dispatch:
+ inputs:
+ releaseversion:
+ description: 'Release version'
+ required: true
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ packages: write
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 11
+ uses: actions/setup-java@v3
+ with:
+ java-version: '11'
+ distribution: 'adopt'
+ cache: maven
+ - run: |
+ echo "Release version ${{ github.event.inputs.releaseversion }}!"
+ - name: Set projects Maven version to GitHub Action GUI set version
+ run: mvn versions:set "-DnewVersion=${{ github.event.inputs.releaseversion }}"
+ - name: Deploy to Github packages
+ run: mvn --batch-mode clean deploy -Pgithub
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - name: Deploy to Maven Central Repository
+ uses: actions/setup-java@v3
+ with:
+ java-version: '11'
+ distribution: 'temurin'
+ cache: maven
+ server-id: ossrh
+ server-username: MAVEN_USERNAME
+ server-password: MAVEN_PASSWORD
+ gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
+ gpg-passphrase: MAVEN_GPG_PASSPHRASE
+ - name: Set projects Maven version to GitHub Action GUI set version
+ run: mvn versions:set "-DnewVersion=${{ github.event.inputs.releaseversion }}"
+ - name: Publish to the Maven Central Repository
+ run: mvn --batch-mode clean deploy -Possrh
+ env:
+ MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
+ - name: Generate changelog
+ id: changelog
+ uses: metcalfc/changelog-generator@v4.1.0
+ with:
+ myToken: ${{ secrets.GITHUB_TOKEN }}
+ - name: Create GitHub Release
+ id: create_release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.event.inputs.releaseversion }}
+ release_name: ${{ github.event.inputs.releaseversion }}
+ body: |
+ ### Things that changed in this release
+ ${{ steps.changelog.outputs.changelog }}
+ draft: false
+ prerelease: false
+
diff --git a/README.md b/README.md
index 5616ad55..b577af47 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,14 @@
+## Disclaimer
+
+This is a fork of original [Text2Confl](https://github.com/zeldigas/text2confl)
+
+It's main purposes is to deploy artifacts to maven central.
+
# text2confl
-![](https://img.shields.io/docker/v/zeldigas/text2confl?label=latest%20version&sort=semver) ![](https://img.shields.io/docker/image-size/zeldigas/text2confl?label=docker%20image%20size&sort=semver)
+![](https://img.shields.io/docker/v/zeldigas/text2confl?label=docker%20version&sort=semver) ![](https://img.shields.io/docker/image-size/zeldigas/text2confl?label=docker%20image%20size&sort=semver)
+
+[![maven-central](https://img.shields.io/maven-central/v/io.github.text2confl/text2confl-cli.svg)](https://search.maven.org/artifact/io.github.text2confl/text2confl-cli) ![codecov](https://codecov.io/gh/text2confl/text2confl/branch/master/graph/badge.svg)
Is a tool for publishing documentation written in structured text formats like markdown to Confluence (either server or
cloud edition).
@@ -14,6 +22,8 @@ find something missing - feel free to create an issue and describe your needs.
## User guide
+### CLI
+
To get started and learn how to start using text2confl, consult with [user guide](docs/user-guide.md).
If you want to quickly check how `text2confl` works you can upload documentation of text2confl itself. For this you need
@@ -37,6 +47,18 @@ Will upload docs producing pages similar to this one:
allow making space or pages available to non-members of wiki (wide open to internet) that's why so far you need to
publish to your own server or spend 10-15 minutes and create your own free wiki in Confluence Cloud.
+### Maven
+
+```xml
+
+ io.github.text2confl
+ text2confl-core
+ 0.16.2
+
+```
+
+Then
+
## Design and usability goals
Here are a number of key principles that tool tries to follow:
diff --git a/cli/pom.xml b/cli/pom.xml
index 35f5928a..b47f30ff 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -1,24 +1,31 @@
-
+
- com.github.zeldigas.confluence
- parent
- 1.0.0-SNAPSHOT
+ io.github.text2confl
+ text2confl-parent
+ 0.16.2-SNAPSHOT4.0.0
- cli
-
-
-
-
-
+ text2confl-cli
+ Text2Confl Command Line Interface
- text2confl${versionSuffix}
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.3.0
+
+
+
+ true
+ lib
+ com.github.zeldigas.text2confl.cli.MainKt
+
+
+
+ org.codehaus.mojoflatten-maven-plugin
@@ -50,6 +57,7 @@
maven-assembly-plugin3.6.0
+ falsesrc/assembly/cli-package.xml
@@ -83,8 +91,8 @@
logback-classic
- com.github.zeldigas.confluence
- core
+ io.github.text2confl
+ text2confl-core${project.version}
diff --git a/cli/src/assembly/cli-package.xml b/cli/src/assembly/cli-package.xml
index a18e3a8f..8c70f593 100644
--- a/cli/src/assembly/cli-package.xml
+++ b/cli/src/assembly/cli-package.xml
@@ -7,32 +7,29 @@
tar.gzdir
-
-
-
- com.github.zeldigas.*
-
- lib
-
-
-
- com.github.zeldigas.*
-
- ${artifact.artifactId}.${artifact.extension}
- app
-
-
- src/assembly/bin
+ ${project.basedir}/src/assembly/bin755
-
+ /
+
+
+ /
+
+
+
+ lib
+
+ ${project.groupId}:${project.artifactId}:jar:*
+
+
+
\ No newline at end of file
diff --git a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/CliOptions.kt b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/CliOptions.kt
index 7bc587d9..f710643c 100644
--- a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/CliOptions.kt
+++ b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/CliOptions.kt
@@ -58,8 +58,18 @@ fun ParameterHolder.httpLoggingLevel() = option(
fun ParameterHolder.httpRequestTimeout() = option(
"--http-request-timeout",
- help = "Http request timeout in milliseconds. Default "
-).long()
+ help = "Http request timeout in milliseconds. Default 30 000 "
+).long().default(30000)
+
+fun ParameterHolder.httpSocketTimeout() = option(
+ "--http-socket-timeout",
+ help = "Http socket timeout in milliseconds. Default 30 000 "
+).long().default(30000)
+
+fun ParameterHolder.httpConnectTimeout() = option(
+ "--http-connect-timeout",
+ help = "Http connect timeout in milliseconds. Default 30 000 "
+).long().default(30000)
internal interface WithConfluenceServerOptions {
val confluenceUrl: Url?
@@ -69,6 +79,8 @@ internal interface WithConfluenceServerOptions {
val skipSsl: Boolean?
val httpLogLevel: LogLevel
val httpRequestTimeout: Long?
+ val httpConnectTimeout: Long?
+ val httpSocketTimeout: Long?
val confluenceAuth: ConfluenceAuth
get() = when {
@@ -93,7 +105,9 @@ internal interface WithConfluenceServerOptions {
skipSsl = skipSsl ?: defaultSslSkip,
auth = confluenceAuth,
httpLogLevel = httpLogLevel,
- requestTimeout = httpRequestTimeout
+ requestTimeout = httpRequestTimeout,
+ connectTimeout = httpConnectTimeout,
+ socketTimeout = httpSocketTimeout
)
fun askForSecret(prompt: String, requireConfirmation: Boolean = true): String?
diff --git a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/DumpToMarkdown.kt b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/DumpToMarkdown.kt
index 8923ce3f..bc0234e5 100644
--- a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/DumpToMarkdown.kt
+++ b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/DumpToMarkdown.kt
@@ -22,6 +22,8 @@ class DumpToMarkdown : CliktCommand(name = "export-to-md", help = "Exports confl
override val skipSsl: Boolean? by skipSsl()
override val httpLogLevel: LogLevel by httpLoggingLevel()
override val httpRequestTimeout: Long? by httpRequestTimeout()
+ override val httpSocketTimeout: Long? by httpSocketTimeout()
+ override val httpConnectTimeout: Long? by httpConnectTimeout()
val space: String? by confluenceSpace()
private val pageId: String? by option("--page-id", help = "Id of page that you want to dump")
diff --git a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/PrintingUploadOperationsTracker.kt b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/PrintingUploadOperationsTracker.kt
index c65c030c..8f03f605 100644
--- a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/PrintingUploadOperationsTracker.kt
+++ b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/PrintingUploadOperationsTracker.kt
@@ -45,6 +45,10 @@ class PrintingUploadOperationsTracker(
describeModifiedPage("Updated labels/attachments:", pageResult.serverPage, pageResult.local, labelUpdate, attachmentsUpdated)
}
}
+
+ is PageOperationResult.Failed -> {
+ printWithPrefix("${red("Failed:")} ${failedPage(pageResult)}")
+ }
}
}
@@ -159,4 +163,17 @@ class PrintingUploadOperationsTracker(
private fun printWithPrefix(msg: String) {
printer("$prefix$msg")
}
+
+ private fun failedPage(error: PageOperationResult.Failed): String {
+ return buildString {
+ append("\"")
+ append(red(error.local.title))
+ append("\"")
+ append(" (")
+ append(error.status)
+ append(")")
+ append(" ")
+ append(error.body)
+ }
+ }
}
\ No newline at end of file
diff --git a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/Upload.kt b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/Upload.kt
index 5966f83e..4f2e2e52 100644
--- a/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/Upload.kt
+++ b/cli/src/main/kotlin/com/github/zeldigas/text2confl/cli/Upload.kt
@@ -33,6 +33,8 @@ class Upload : CliktCommand(name = "upload", help = "Converts source files and u
override val skipSsl: Boolean? by skipSsl()
override val httpLogLevel: LogLevel by httpLoggingLevel()
override val httpRequestTimeout: Long? by httpRequestTimeout()
+ override val httpSocketTimeout: Long? by httpSocketTimeout()
+ override val httpConnectTimeout: Long? by httpConnectTimeout()
override val spaceKey: String? by confluenceSpace()
private val parentId: String? by option("--parent-id", help = "Id of parent page where root pages should be added")
@@ -87,6 +89,7 @@ class Upload : CliktCommand(name = "upload", help = "Converts source files and u
} else {
converter.convertDir(docs.toPath())
}
+
serviceProvider.createContentValidator().validate(result)
val confluenceClient = serviceProvider.createConfluenceClient(clientConfig, dryRun)
val publishUnder = resolveParent(confluenceClient, uploadConfig, directoryStoredParams)
diff --git a/cli/src/test/kotlin/com/github/zeldigas/text2confl/cli/UploadTest.kt b/cli/src/test/kotlin/com/github/zeldigas/text2confl/cli/UploadTest.kt
index dc15bedc..00bfcd67 100644
--- a/cli/src/test/kotlin/com/github/zeldigas/text2confl/cli/UploadTest.kt
+++ b/cli/src/test/kotlin/com/github/zeldigas/text2confl/cli/UploadTest.kt
@@ -110,7 +110,7 @@ internal class UploadTest(
internal fun `Data from yaml config file`(@TempDir tempDir: Path) {
val directoryConfig = sampleConfig().copy(tenant = "test1")
directoryConfig.docsDir = tempDir
- writeToFile(tempDir.resolve(".text2confl.yml"), directoryConfig)
+ writeToFile(tempDir.resolve("text2confl.yml"), directoryConfig)
val result = mockk>()
every { converter.convertDir(tempDir) } returns result
diff --git a/confluence-client/pom.xml b/confluence-client/pom.xml
index 437a3cf5..3072d1e6 100644
--- a/confluence-client/pom.xml
+++ b/confluence-client/pom.xml
@@ -1,15 +1,14 @@
-
+
- parent
- com.github.zeldigas.confluence
- 1.0.0-SNAPSHOT
+ io.github.text2confl
+ text2confl-parent
+ 0.16.2-SNAPSHOT4.0.0
-
- confluence-client
+
+ text2confl-confluence-client
+ Text2Confl Confluence ClientImplementation of http client for confluence
diff --git a/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClient.kt b/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClient.kt
index f67f4eae..65ec7874 100644
--- a/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClient.kt
+++ b/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClient.kt
@@ -80,6 +80,9 @@ interface ConfluenceClient {
class PageNotCreatedException(val title: String, val status: Int, val body: String?) :
RuntimeException("Failed to create '$title' page: status=$status, body:\n$body")
+class PageNotUpdatedException(val id: String, val status: Int, val body: String?) :
+ RuntimeException("Failed to update '$id' page: status=$status, body:\n$body")
+
class PageNotFoundException : RuntimeException()
class TooManyPagesFound(val pages: List) : RuntimeException()
diff --git a/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientConfig.kt b/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientConfig.kt
index 66c50d02..c1736bc3 100644
--- a/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientConfig.kt
+++ b/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientConfig.kt
@@ -11,5 +11,7 @@ data class ConfluenceClientConfig(
val skipSsl: Boolean,
val auth: ConfluenceAuth,
val httpLogLevel: LogLevel = LogLevel.NONE,
- val requestTimeout: Long? = null,
+ val requestTimeout: Long? = 30000,
+ val connectTimeout: Long? = 30000,
+ val socketTimeout: Long? = 30000
)
\ No newline at end of file
diff --git a/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientImpl.kt b/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientImpl.kt
index 6cb2944a..d7046b7b 100644
--- a/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientImpl.kt
+++ b/confluence-client/src/main/kotlin/com/github/zeldigas/confclient/ConfluenceClientImpl.kt
@@ -8,6 +8,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.cio.*
+import io.ktor.client.network.sockets.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.auth.*
import io.ktor.client.plugins.contentnegotiation.*
@@ -132,6 +133,10 @@ class ConfluenceClientImpl(
response.body()
} catch (e: ContentConvertException) {
throw PageNotCreatedException(value.title, response.status.value, response.bodyAsText())
+ } catch (e: ConnectTimeoutException) {
+ throw PageNotCreatedException(value.title, response.status.value, response.bodyAsText())
+ } catch (e: HttpRequestTimeoutException) {
+ throw PageNotCreatedException(value.title, response.status.value, response.bodyAsText())
}
}
@@ -179,9 +184,13 @@ class ConfluenceClientImpl(
setBody(body)
}
if (response.status.isSuccess()) {
- return response.readApiResponse()
+ try {
+ return response.readApiResponse()
+ } catch (e: ConnectTimeoutException) {
+ throw PageNotUpdatedException(pageId, response.status.value, response.bodyAsText())
+ }
} else {
- throw RuntimeException("Failed to update $pageId: ${response.bodyAsText()}")
+ throw PageNotUpdatedException(pageId, response.status.value, response.bodyAsText())
}
}
@@ -340,7 +349,7 @@ private suspend inline fun HttpResponse.readApiResponse(expectSucces
parseAndThrowConfluencError()
}
val contentType = contentType()
- if (contentType != null && ContentType.Application.Json.match(contentType)){
+ if (contentType != null && ContentType.Application.Json.match(contentType)) {
try {
return body()
} catch (e: JsonConvertException) {
@@ -357,7 +366,7 @@ private suspend fun HttpResponse.parseAndThrowConfluencError(): Nothing {
}
private data class PageSearchResult(
- val results: List,
+ val results: List = emptyList(),
val start: Int,
val limit: Int,
val size: Int
@@ -367,10 +376,12 @@ fun confluenceClient(
config: ConfluenceClientConfig
): ConfluenceClient {
val client = HttpClient(CIO) {
+ install(HttpTimeout) {
+ requestTimeoutMillis = config.requestTimeout
+ connectTimeoutMillis = config.connectTimeout
+ socketTimeoutMillis = config.socketTimeout
+ }
engine {
- if (config.requestTimeout != null) {
- requestTimeout = config.requestTimeout
- }
if (config.skipSsl) {
https {
trustManager = object : X509TrustManager {
diff --git a/convert/pom.xml b/convert/pom.xml
index 2795eadd..85a501c6 100644
--- a/convert/pom.xml
+++ b/convert/pom.xml
@@ -3,16 +3,18 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- parent
- com.github.zeldigas.confluence
- 1.0.0-SNAPSHOT
+ io.github.text2confl
+ text2confl-parent
+ 0.16.2-SNAPSHOT4.0.0
- convert
+ text2confl-convert
+ Text2Confl Convertor
+ Conversion to Confluence Storage Format
- 0.64.4
+ 0.64.82.5.112.2.17
@@ -99,6 +101,11 @@
${asciidoctorj-diagram.version}runtime
+
+ org.jsoup
+ jsoup
+ 1.17.2
+
@@ -142,4 +149,38 @@
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.6.1
+
+
+ unpack
+ generate-resources
+
+ unpack
+
+
+
+
+ org.sahli.asciidoc.confluence.publisher
+ asciidoc-confluence-publisher-converter
+ 0.22.0
+ jar
+ true
+ ${project.build.directory}/confluence-publisher-templates
+ **/*.slim,**/*.rb
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/AttachmentCollector.kt b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/AttachmentCollector.kt
index ecf8789b..a4e51de1 100644
--- a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/AttachmentCollector.kt
+++ b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/AttachmentCollector.kt
@@ -6,6 +6,7 @@ import java.net.URI
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.exists
+import kotlin.io.path.isRegularFile
class AttachmentCollector(
private val referencesProvider: ReferenceProvider,
@@ -62,7 +63,7 @@ class AttachmentCollector(
private fun lookupInDirAndAdd(dir: Path, pathToFile: String, effectiveName: String): Attachment? {
val file = dir.resolve(pathToFile).normalize()
- return if (file.exists()) {
+ return if (file.exists() && file.isRegularFile()) {
logger.debug { "File exists, adding as attachment: $file with ref $effectiveName" }
val attachment = Attachment.fromLink(effectiveName, file)
attachmentsRegistry.register(effectiveName, attachment)
diff --git a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/Converter.kt b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/Converter.kt
index 89e7757b..b6d92ecb 100644
--- a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/Converter.kt
+++ b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/Converter.kt
@@ -6,6 +6,7 @@ import com.github.zeldigas.text2confl.convert.confluence.LanguageMapper
import com.github.zeldigas.text2confl.convert.confluence.ReferenceProvider
import com.github.zeldigas.text2confl.convert.markdown.MarkdownConfiguration
import com.github.zeldigas.text2confl.convert.markdown.MarkdownFileConverter
+import io.github.oshai.kotlinlogging.KotlinLogging
import java.io.File
import java.nio.file.Path
import kotlin.io.path.exists
@@ -62,6 +63,9 @@ internal class UniversalConverter(
val converters: Map,
val pagesDetector: PagesDetector,
) : Converter {
+ companion object {
+ private val logger = KotlinLogging.logger {}
+ }
override fun convertFile(file: Path): Page {
val converter = converterFor(file)
@@ -79,8 +83,8 @@ internal class UniversalConverter(
override fun convertDir(dir: Path): List {
val documents = scanDocuments(dir)
+ logger.info { "Found " + documents.size + " documents in " + dir }
checkForDuplicates(dir, documents)
-
return convertFilesInDirectory(
dir,
ConvertingContext(ReferenceProvider.fromDocuments(dir, documents), conversionParameters, space)
diff --git a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/PageContent.kt b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/PageContent.kt
index 18f0ea94..939a7238 100644
--- a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/PageContent.kt
+++ b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/PageContent.kt
@@ -1,5 +1,8 @@
package com.github.zeldigas.text2confl.convert
+import io.github.oshai.kotlinlogging.KotlinLogging
+import org.jsoup.Jsoup
+import org.jsoup.parser.Parser
import java.io.ByteArrayInputStream
import java.nio.file.Path
import java.security.DigestInputStream
@@ -89,9 +92,13 @@ data class Attachment(
data class PageContent(
val header: PageHeader,
- val body: String,
+ var body: String,
val attachments: List
) {
+ companion object {
+ private val logger = KotlinLogging.logger { }
+ }
+
val hash by lazy {
val bytes = body.toByteArray()
val md = MessageDigest.getInstance("SHA-256")
@@ -99,9 +106,14 @@ data class PageContent(
toBase64(digest)
}
+ fun fixHtml(): PageContent {
+ val document = Jsoup.parse(body, Parser.xmlParser())
+ body = document.html()
+ return this
+ }
+
fun validate(): Validation {
val stack: Deque = LinkedList()
-
try {
for (event in traverseDocument(body)) {
when {
diff --git a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/asciidoc/AsciidocParser.kt b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/asciidoc/AsciidocParser.kt
index 03e02b76..13388cc4 100644
--- a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/asciidoc/AsciidocParser.kt
+++ b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/asciidoc/AsciidocParser.kt
@@ -6,6 +6,7 @@ import org.asciidoctor.*
import org.asciidoctor.ast.Document
import java.nio.file.Path
import java.nio.file.Paths
+import kotlin.io.path.Path
import kotlin.io.path.div
@@ -14,7 +15,7 @@ class AsciidocParser(
) {
companion object {
- private val TEMPLATES_LOCATION = "/com/github/zeldigas/text2confl/asciidoc"
+ private val TEMPLATES_LOCATION = "com/github/zeldigas/text2confl/asciidoc"
}
private val ADOC: Asciidoctor by lazy {
@@ -27,9 +28,10 @@ class AsciidocParser(
}
private val templatesLocation: Path by lazy {
- val templateResources = AsciidocParser::class.java.getResource(TEMPLATES_LOCATION)!!.toURI()
+ val templateResources = AsciidocParser::class.java.classLoader.getResource(TEMPLATES_LOCATION)!!.toURI()
if (templateResources.scheme == "file") {
- Paths.get(templateResources)
+ val mainPath: String = Paths.get(templateResources).toString()
+ Path(mainPath)
} else {
val dest = config.workdir / "templates"
diff --git a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProvider.kt b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProvider.kt
index 9fbbe5ff..964d88e9 100644
--- a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProvider.kt
+++ b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProvider.kt
@@ -1,9 +1,11 @@
package com.github.zeldigas.text2confl.convert.confluence
import com.github.zeldigas.text2confl.convert.PageHeader
+import java.nio.file.InvalidPathException
import io.github.oshai.kotlinlogging.KotlinLogging
import java.net.URLDecoder
import java.nio.file.Path
+import java.util.regex.Pattern
import kotlin.io.path.relativeTo
interface ReferenceProvider {
@@ -41,18 +43,27 @@ class ReferenceProviderImpl(private val basePath: Path, documents: Map path.relativeTo(basePath).normalize() to header }.toMap()
override fun resolveReference(source: Path, refTo: String): Reference? {
- if (URI_DETECTOR.find(refTo) != null) {
- log.debug { "$refTo detected as link in $source" }
- return null
- }
+
+ if (refTo.startsWith(MAILTO_DETECTOR)) return null
+ if (refTo.startsWith(LOCALHOST_DETECTOR)) return null
+ if (isValid(refTo)) return null
+
val normalizedRef = URLDecoder.decode(refTo, "UTF-8")
if (normalizedRef.startsWith("#")) return Anchor(normalizedRef.substring(1))
@@ -60,10 +71,17 @@ class ReferenceProviderImpl(private val basePath: Path, documents: Map
@@ -61,14 +64,20 @@ class KrokiDiagramsGenerator(
override fun generate(source: String, target: Path, attributes: Map): ImageInfo {
val request = createRequest(source, attributes)
runBlocking {
- val result = client.post(server.toURL()) {
- contentType(ContentType.Application.Json)
- setBody(request)
- }
- if (result.status != HttpStatusCode.OK) {
- throw DiagramGenerationFailedException(result.body())
+ try {
+ val result = client.post(server.toURL()) {
+ contentType(ContentType.Application.Json)
+ setBody(request)
+ }
+ if (result.status != HttpStatusCode.OK) {
+ throw DiagramGenerationFailedException(result.body())
+ }
+ target.writeBytes(result.body())
+ } catch (ex : ConnectException){
+ logger.error { "Trying to connect to $server" }
+ throw DiagramGenerationFailedException(ex.message)
}
- target.writeBytes(result.body())
+
}
return ImageInfo()
}
diff --git a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/MermaidDiagramsGenerator.kt b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/MermaidDiagramsGenerator.kt
index a2a808b7..393becd5 100644
--- a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/MermaidDiagramsGenerator.kt
+++ b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/MermaidDiagramsGenerator.kt
@@ -20,7 +20,7 @@ class MermaidDiagramsGenerator(
private val SUPPORTED_FORMATS = setOf("png", "svg")
private val PUPPETER_CONFIG_ENV = "T2C_PUPPEETER_CONFIG"
- private val log = KotlinLogging.logger {}
+ private val logger = KotlinLogging.logger {}
}
constructor(config: MermaidDiagramsConfiguration, commandExecutor: CommandExecutor = OsCommandExecutor()) : this(
@@ -67,11 +67,11 @@ class MermaidDiagramsGenerator(
val result = try {
commandExecutor.execute(cmd(command) { flag("-V") })
} catch (ex: Exception) {
- log.debug(ex) { "Failed to execute command" }
+ logger.debug(ex) { "Failed to execute command" }
return false
}
return if (result.status == 0) {
- log.info { "Mermaid version: ${result.output}" }
+ logger.info { "Mermaid version: ${result.output}" }
true
} else {
false
diff --git a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/PlantUmlDiagramsGenerator.kt b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/PlantUmlDiagramsGenerator.kt
index 4d9a548c..e73514c9 100644
--- a/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/PlantUmlDiagramsGenerator.kt
+++ b/convert/src/main/kotlin/com/github/zeldigas/text2confl/convert/markdown/diagram/PlantUmlDiagramsGenerator.kt
@@ -16,7 +16,7 @@ class PlantUmlDiagramsGenerator(
val SUPPORTED_LANGS = setOf("plantuml", "puml")
val SUPPORTED_FORMATS = setOf("svg", "png", "eps")
const val DEFAULT_FORMAT = "png"
- private val log = KotlinLogging.logger { }
+ private val logger = KotlinLogging.logger { }
}
constructor(config: PlantUmlDiagramsConfiguration, commandExecutor: CommandExecutor = OsCommandExecutor()) : this(
@@ -59,11 +59,11 @@ class PlantUmlDiagramsGenerator(
val result = try {
commandExecutor.execute(cmd(command) { flag("-version") })
} catch (ex: Exception) {
- log.debug(ex) { "Failed to execute command" }
+ logger.debug(ex) { "Failed to execute command" }
return false
}
return if (result.status == 0) {
- log.info { "PlantUml version: ${result.output.lines().firstOrNull()}" }
+ logger.info { "PlantUml version: ${result.output.lines().firstOrNull()}" }
true
} else {
false
diff --git a/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/PageContentTest.kt b/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/PageContentTest.kt
index 0fa84fcc..7f48e8b5 100644
--- a/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/PageContentTest.kt
+++ b/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/PageContentTest.kt
@@ -11,6 +11,7 @@ import org.junit.jupiter.api.io.TempDir
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import java.nio.file.Path
+import java.util.*
import kotlin.io.path.Path
import kotlin.io.path.writeBytes
@@ -70,6 +71,7 @@ class PageContentTest {
@Test
internal fun `Invalid result for unbalanced xml`() {
+ Locale.setDefault(Locale.ENGLISH);
val sampleXml = """
hello world
@@ -87,4 +89,27 @@ class PageContentTest {
.transform { it.issue }
.contains("[5:3] The element type \"p\" must be terminated by the matching end-tag \"\". Start tag location - [3:4]")
}
+
+ @Test
+ internal fun `Valid result for unbalanced xml`() {
+ Locale.setDefault(Locale.ENGLISH);
+ val sampleXml = """
+
+
hello world
+
hello world </p>
+
hello world
+
""".trimIndent()
+ print(sampleXml)
+ assertThat(
+ PageContent(
+ PageHeader("", emptyMap()),
+ sampleXml,
+ emptyList()
+ )
+ .fixHtml()
+ .validate()
+
+ ).isEqualTo(Validation.Ok)
+ }
+
}
\ No newline at end of file
diff --git a/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProviderImplTest.kt b/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProviderImplTest.kt
index 1a12acd5..926e997b 100644
--- a/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProviderImplTest.kt
+++ b/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/confluence/ReferenceProviderImplTest.kt
@@ -88,4 +88,58 @@ internal class ReferenceProviderImplTest {
assertThat(result).isNull()
}
+
+
+ @Test
+ internal fun `Http resolution`() {
+ val result = providerImpl.resolveReference(Path("docs/one.md"), "http://github.com")
+
+ assertThat(result).isNull()
+ }
+
+ @Test
+ internal fun `Https resolution`() {
+ val result = providerImpl.resolveReference(Path("docs/one.md"), "https://github.com")
+
+ assertThat(result).isNull()
+ }
+
+ @Test
+ internal fun `Mailto resolution`() {
+ val result = providerImpl.resolveReference(Path("docs/one.md"), "mailto:john.doe@github.com")
+
+ assertThat(result).isNull()
+ }
+
+
+ @Test
+ internal fun `French url resolution`() {
+ val result = providerImpl.resolveReference(Path("docs/one.md"), "http://github.com/handle'case")
+
+ assertThat(result).isNull()
+ }
+
+ @Test
+ internal fun `Parenthesis url resolution`() {
+ val result = providerImpl.resolveReference(Path("docs/one.md"), "http://github.com/handle()case")
+
+ assertThat(result).isNull()
+ }
+
+
+ @Test
+ internal fun `Plus url resolution`() {
+ val result = providerImpl.resolveReference(Path("docs/one.md"), "https://github.com/handle/+/case")
+
+ assertThat(result).isNull()
+ }
+
+
+ @Test
+ internal fun `localhost url resolution`() {
+ val result = providerImpl.resolveReference(Path("docs/one.md"), "localhost:9000")
+
+ assertThat(result).isNull()
+ }
+
}
\ No newline at end of file
diff --git a/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/markdown/MarkdownAttachmentCollectorTest.kt b/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/markdown/MarkdownAttachmentCollectorTest.kt
index e53e7844..d38bd5a8 100644
--- a/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/markdown/MarkdownAttachmentCollectorTest.kt
+++ b/convert/src/test/kotlin/com/github/zeldigas/text2confl/convert/markdown/MarkdownAttachmentCollectorTest.kt
@@ -145,4 +145,28 @@ internal class MarkdownAttachmentCollectorTest {
assertThat(registry.collectedAttachments).isEmpty()
}
+
+
+ @Test
+ internal fun `Attachment collection for folder`(
+ @TempDir dir: Path,
+ @MockK referenceProvider: ReferenceProvider
+ ) {
+
+ Files.createDirectory(dir.resolve("folder"))
+ val ast = parser.parse(
+ """
+ ["folder"](folder)
+
+ """.trimIndent()
+ )
+
+ val doc = dir.resolve("doc.md")
+
+ every { referenceProvider.resolveReference(doc, "folder") } returns Xref("test", null)
+
+ MarkdownAttachmentCollector(doc, referenceProvider, registry).collectAttachments(ast)
+
+ assertThat(registry.collectedAttachments).isEmpty()
+ }
}
\ No newline at end of file
diff --git a/core/pom.xml b/core/pom.xml
index 401acf19..3de34e49 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1,25 +1,24 @@
-
+4.0.0
- com.github.zeldigas.confluence
- parent
- 1.0.0-SNAPSHOT
+ io.github.text2confl
+ text2confl-parent
+ 0.16.2-SNAPSHOT
- core
+ text2confl-core
+ Text2confl Core
- com.github.zeldigas.confluence
- convert
+ io.github.text2confl
+ text2confl-convert${project.version}
- com.github.zeldigas.confluence
- confluence-client
+ io.github.text2confl
+ text2confl-confluence-client${project.version}
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/ContentValidator.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/ContentValidator.kt
index 3d24ab7d..362cea40 100644
--- a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/ContentValidator.kt
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/ContentValidator.kt
@@ -2,14 +2,20 @@ package com.github.zeldigas.text2confl.core
import com.github.zeldigas.text2confl.convert.Page
import com.github.zeldigas.text2confl.convert.Validation
+import io.github.oshai.kotlinlogging.KotlinLogging
class ContentValidationFailedException(val errors: List) : RuntimeException()
interface ContentValidator {
fun validate(content: List)
+ fun fixHtml(content: List)
}
class ContentValidatorImpl : ContentValidator {
+
+ companion object {
+ private val logger = KotlinLogging.logger { }
+ }
override fun validate(content: List) {
val foundIssues: MutableList = arrayListOf()
collectErrors(content, foundIssues)
@@ -18,10 +24,20 @@ class ContentValidatorImpl : ContentValidator {
}
}
+ override fun fixHtml(content: List) {
+ logger.info { "Fixing html pages : " + content.size }
+ for (page in content){
+ page.content.fixHtml()
+ fixHtml(page.children)
+ }
+ }
+
private fun collectErrors(pages: List, foundIssues: MutableList) {
for (page in pages) {
+ logger.debug { "Validating : ${page.source}: "}
val validationResult = page.content.validate()
if (validationResult is Validation.Invalid) {
+ logger.debug { validationResult.issue }
foundIssues.add("${page.source}: ${validationResult.issue}")
}
collectErrors(page.children, foundIssues)
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfig.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfig.kt
index 225f0db6..878f9128 100644
--- a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfig.kt
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfig.kt
@@ -10,7 +10,7 @@ import kotlin.io.path.createTempDirectory
import kotlin.io.path.div
/**
- * Holder of data that can be put to `.text2confl.yml` configuration file that is located in root directory of directory structure
+ * Holder of data that can be put to `text2confl.yml` configuration file that is located in root directory of directory structure
*/
data class DirectoryConfig(
val server: String? = null,
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/IO.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/IO.kt
index 01e014b6..ca95bb1c 100644
--- a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/IO.kt
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/config/IO.kt
@@ -13,6 +13,7 @@ import kotlin.io.path.absolute
import kotlin.io.path.exists
import kotlin.io.path.isRegularFile
+private val logger = KotlinLogging.logger { }
private val mapper = JsonMapper.builder(YAMLFactory())
.addModule(kotlinModule())
@@ -21,9 +22,9 @@ private val mapper = JsonMapper.builder(YAMLFactory())
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.build()
-private val CONFIG_FILE_NAMES = listOf(".text2confl", "text2confl")
-private val log = KotlinLogging.logger { }
+private val CONFIG_FILE_NAME = "text2confl.yml"
+private val CONFIG_FILE_NAMES = listOf(CONFIG_FILE_NAME)
fun readDirectoryConfig(dirOfFile: Path): DirectoryConfig {
val resolver: (String) -> Path = if (dirOfFile.isRegularFile()) {
@@ -31,20 +32,28 @@ fun readDirectoryConfig(dirOfFile: Path): DirectoryConfig {
} else {
dirOfFile::resolve
}
- val docsDir = if (dirOfFile.isRegularFile()) dirOfFile.absolute().parent else dirOfFile
- val configFile = CONFIG_FILE_NAMES.asSequence()
- .flatMap { listOf("$it.yml", "$it.yaml") }
+ var directoryConfig = CONFIG_FILE_NAMES.asSequence()
.map(resolver)
.filter { it.exists() }
+ .map { mapper.readValue(it.toFile()) }
.firstOrNull()
- val directoryConfig:DirectoryConfig = if (configFile != null) {
- log.debug { "Found config file $configFile" }
- mapper.readValue(configFile.toFile())
- } else {
- log.debug { "No config file found in $docsDir. Using defaults" }
- DirectoryConfig()
+
+
+ if (directoryConfig == null) {
+ logger.debug { "No Conf File in $dirOfFile" }
+ logger.debug { "Try Loading conf from classpath" }
+
+ val confFile = DirectoryConfig::class.java.classLoader.getResource(CONFIG_FILE_NAME)
+ if (confFile != null) {
+ logger.debug { "Found conf File : " + confFile.file }
+ directoryConfig = mapper.readValue(confFile)
+ } else {
+ logger.debug { "Create default Directory Config" }
+ directoryConfig = DirectoryConfig()
+ }
}
- directoryConfig.docsDir = docsDir
+
+ directoryConfig.docsDir = if (dirOfFile.isRegularFile()) dirOfFile.absolute().parent else dirOfFile
return directoryConfig
}
\ No newline at end of file
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/ContentUploader.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/ContentUploader.kt
index 638650b7..75ebed62 100644
--- a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/ContentUploader.kt
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/ContentUploader.kt
@@ -7,10 +7,8 @@ import com.github.zeldigas.text2confl.convert.Page
import com.github.zeldigas.text2confl.convert.PageHeader
import com.github.zeldigas.text2confl.core.config.Cleanup
import io.github.oshai.kotlinlogging.KotlinLogging
-import kotlinx.coroutines.async
-import kotlinx.coroutines.awaitAll
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
+import io.ktor.client.network.sockets.*
+import kotlinx.coroutines.*
class ContentUploader(
@@ -49,19 +47,67 @@ class ContentUploader(
private val logger = KotlinLogging.logger {}
}
- suspend fun uploadPages(pages: List, space: String, parentPageId: String) {
- val uploadedPages = uploadPagesRecursive(pages, space, parentPageId)
+ fun run(pages: List, space: String, parentPageId: String) = runBlocking {
+ withContext(Dispatchers.Default) {
+ uploadPages(pages, space, parentPageId)
+ }
+ }
+
+ fun runBlocking(pages: List, space: String, parentPageId: String) = runBlocking {
+ withContext(Dispatchers.Default) {
+ uploadPagesBlocking(pages, space, parentPageId)
+ }
+ }
+
+ suspend fun uploadPagesBlocking(pages: List, space: String, parentPageId: String) {
+ val uploadedPages = uploadPagesRecursiveBlocking(pages, space, parentPageId)
+ logger.info { "Uploaded Pages : " + uploadedPages.size }
tracker.uploadsCompleted()
+ handleOrphans(uploadedPages)
+ }
+
+ private suspend fun ContentUploader.handleOrphans(uploadedPages: List) {
val uploadedPagesByParent = buildOrphanedRemovalRegistry(uploadedPages)
deleteOrphans(uploadedPagesByParent)
}
+ suspend fun uploadPages(pages: List, space: String, parentPageId: String) {
+ val uploadedPages = uploadPagesRecursive(pages, space, parentPageId)
+ tracker.uploadsCompleted()
+ handleOrphans(uploadedPages)
+ }
+
+ private suspend fun uploadPagesRecursiveBlocking(
+ pages: List,
+ space: String,
+ parentPageId: String
+ ): List {
+
+ val uploadedPages = ArrayList()
+ pages.forEach {
+ try {
+ val result = uploadPage(it, space, parentPageId)
+ uploadedPages.addAll(
+ buildList {
+ add(result)
+ if (it.children.isNotEmpty()) {
+ addAll(uploadPagesRecursiveBlocking(it.children, space, result.page.id))
+ }
+ })
+ } catch (e: ConnectTimeoutException) {
+ logger.error { e.message }
+ return emptyList()
+ }
+ }
+ return uploadedPages
+ }
+
private suspend fun uploadPagesRecursive(
pages: List,
space: String,
parentPageId: String
): List {
- return coroutineScope {
+ return supervisorScope {
pages.map { page ->
async {
val result = uploadPage(page, space, parentPageId)
@@ -85,7 +131,11 @@ class ContentUploader(
val labelUpdate = pageUploadOperations.updatePageLabels(serverPage, page.content)
val attachmentsUpdated = pageUploadOperations.updatePageAttachments(serverPage, page.content)
tracker.pageUpdated(pageResult, labelUpdate, attachmentsUpdated)
- logger.info { "Page uploaded: title=${page.title}, src=${page.source}: id=${serverPage.id}" }
+ if (pageResult is PageOperationResult.Failed){
+ logger.warn { "Failed to upload Page : title=${page.title}, src=${page.source}" }
+ } else {
+ logger.info { "Page uploaded: title=${page.title}, src=${page.source}: id=${serverPage.id}" }
+ }
PageUploadResult(parentId, serverPage, virtual = false)
} else {
logger.info { "Checking that virtual page exists and properly located: ${page.title}" }
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/DryRunClient.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/DryRunClient.kt
index b54651da..c9a328d4 100644
--- a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/DryRunClient.kt
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/DryRunClient.kt
@@ -8,7 +8,7 @@ import java.time.ZonedDateTime
class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient by realClient {
companion object {
- private val log = KotlinLogging.logger {}
+ private val logger = KotlinLogging.logger{}
private const val UNDEFINED_ID = "(known after apply)"
}
@@ -17,7 +17,7 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
updateParameters: PageUpdateOptions,
expansions: List?
): ConfluencePage {
- log.info { "(dryrun) Creating page under parent ${value.parentPage} with title ${value.title}" }
+ logger.info { "(dryrun) Creating page under parent ${value.parentPage} with title ${value.title}" }
return ConfluencePage(
UNDEFINED_ID,
ContentType.page,
@@ -36,7 +36,7 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
value: PageContentInput,
updateParameters: PageUpdateOptions
): ConfluencePage {
- log.info { "(dryrun) Updating page $pageId with title ${value.title}" }
+ logger.info { "(dryrun) Updating page $pageId with title ${value.title}" }
return ConfluencePage(
pageId,
ContentType.page,
@@ -57,7 +57,7 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
newParentId: String,
updateParameters: PageUpdateOptions
): ConfluencePage {
- log.info { "(dryrun) Changing parent of page $pageId with title ${title} to $newParentId" }
+ logger.info { "(dryrun) Changing parent of page $pageId with title ${title} to $newParentId" }
return ConfluencePage(
pageId,
ContentType.page,
@@ -76,7 +76,7 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
newTitle: String,
updateParameters: PageUpdateOptions
): ConfluencePage {
- log.info { "(dryrun) Changing title of page with ${serverPage.id}: ${serverPage.title} -> $newTitle" }
+ logger.info { "(dryrun) Changing title of page with ${serverPage.id}: ${serverPage.title} -> $newTitle" }
return serverPage.copy(
title = newTitle,
version = PageVersionInfo(serverPage.version!!.number + 1, true, ZonedDateTime.now())
@@ -84,7 +84,7 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
}
override suspend fun deletePage(pageId: String) {
- log.info { "(dryrun) Deleting page $pageId" }
+ logger.info { "(dryrun) Deleting page $pageId" }
}
override suspend fun findChildPages(pageId: String, expansions: List?): List {
@@ -96,15 +96,15 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
}
override suspend fun setPageProperty(pageId: String, name: String, value: PagePropertyInput) {
- log.info { "(dryrun) Setting property on page $pageId: $name=${value.value}, version=${value.version.number}" }
+ logger.info { "(dryrun) Setting property on page $pageId: $name=${value.value}, version=${value.version.number}" }
}
override suspend fun deleteLabel(pageId: String, label: String) {
- log.info { "(dryrun) Deleting label on page $pageId: $label" }
+ logger.info { "(dryrun) Deleting label on page $pageId: $label" }
}
override suspend fun addLabels(pageId: String, labels: List) {
- log.info { "(dryrun) Adding labels on page $pageId: $labels" }
+ logger.info { "(dryrun) Adding labels on page $pageId: $labels" }
}
override suspend fun addAttachments(
@@ -112,7 +112,7 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
pageAttachmentInput: List
): PageAttachments {
pageAttachmentInput.forEach {
- log.info { "(dryrun) Creating attachment on page $pageId: ${contentDetails(it)}" }
+ logger.info { "(dryrun) Creating attachment on page $pageId: ${contentDetails(it)}" }
}
return PageAttachments(results = pageAttachmentInput.map { toServerAttachment(UNDEFINED_ID, it) })
}
@@ -122,7 +122,7 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
attachmentId: String,
pageAttachmentInput: PageAttachmentInput
): Attachment {
- log.info { "(dryrun) Updating attachment $attachmentId on page $pageId: ${contentDetails(pageAttachmentInput)}" }
+ logger.info { "(dryrun) Updating attachment $attachmentId on page $pageId: ${contentDetails(pageAttachmentInput)}" }
return toServerAttachment(attachmentId, pageAttachmentInput)
}
@@ -135,6 +135,6 @@ class DryRunClient(private val realClient: ConfluenceClient) : ConfluenceClient
"uploading ${pageAttachmentInput.content} with contentType=${pageAttachmentInput.contentType}, comment=${pageAttachmentInput.comment}"
override suspend fun deleteAttachment(attachmentId: String) {
- log.info { "(dryrun) Deleting attachment $attachmentId" }
+ logger.info { "(dryrun) Deleting attachment $attachmentId" }
}
}
\ No newline at end of file
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/LoggingUploadOperationsTracker.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/LoggingUploadOperationsTracker.kt
new file mode 100644
index 00000000..2f11884f
--- /dev/null
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/LoggingUploadOperationsTracker.kt
@@ -0,0 +1,202 @@
+package com.github.zeldigas.text2confl.core.upload
+
+import com.github.zeldigas.confclient.model.ConfluencePage
+import com.github.zeldigas.text2confl.convert.Page
+import io.github.oshai.kotlinlogging.KotlinLogging
+import io.ktor.http.*
+import java.util.concurrent.atomic.AtomicLong
+
+class LoggingUploadOperationsTracker(
+ val server: Url
+) : UploadOperationTracker {
+
+ companion object {
+ const val UILINK = "tinyui"
+ private val logger = KotlinLogging.logger { }
+ }
+
+ private val updatedCount = AtomicLong(0L)
+
+ private fun print(msg: String) {
+ logger.info { msg }
+ }
+
+ override fun pageUpdated(
+ pageResult: PageOperationResult,
+ labelUpdate: LabelsUpdateResult,
+ attachmentsUpdated: AttachmentsUpdateResult
+ ) {
+ if (pageResult is PageOperationResult.NotModified
+ && labelUpdate == LabelsUpdateResult.NotChanged
+ && attachmentsUpdated == AttachmentsUpdateResult.NotChanged
+ ) return;
+
+ updatedCount.incrementAndGet()
+
+ when (pageResult) {
+ is PageOperationResult.Created -> {
+ print("Created: ${pageInfo(pageResult.serverPage, pageResult.local)}")
+ }
+
+ is PageOperationResult.ContentModified-> {
+ describeModifiedPage(
+ "Updated:",
+ pageResult.serverPage,
+ pageResult.local,
+ labelUpdate,
+ attachmentsUpdated
+ )
+ }
+ is PageOperationResult.LocationModified -> {
+ describeModifiedPage(
+ "Updated:",
+ pageResult.serverPage,
+ pageResult.local,
+ labelUpdate,
+ attachmentsUpdated
+ )
+ }
+
+ is PageOperationResult.NotModified -> {
+ if (labelUpdate != LabelsUpdateResult.NotChanged || attachmentsUpdated != AttachmentsUpdateResult.NotChanged) {
+ describeModifiedPage(
+ "Updated labels/attachments:",
+ pageResult.serverPage,
+ pageResult.local,
+ labelUpdate,
+ attachmentsUpdated
+ )
+ }
+ }
+ is PageOperationResult.Failed -> {
+ logger.error {
+ "Failed: ${failedPage(pageResult)}"
+ }
+ }
+ }
+ }
+
+ private fun describeModifiedPage(
+ operation: String,
+ serverPage: ServerPage,
+ local: Page,
+ labelUpdate: LabelsUpdateResult,
+ attachmentsUpdated: AttachmentsUpdateResult
+ ) {
+ val labelsAttachmentsInfo = labelsAttachmentsInfo(labelUpdate, attachmentsUpdated)
+ print(
+ "$operation ${
+ pageInfo(
+ serverPage,
+ local
+ )
+ }${if (labelsAttachmentsInfo.isNotBlank()) " $labelsAttachmentsInfo" else "" }"
+ )
+ }
+
+ private fun pageInfo(serverPage: ServerPage, page: Page): String = buildString {
+ append('"')
+ append(serverPage.title)
+ append('"')
+ append(" from - ")
+ append(page.source.normalize())
+ append(".")
+ val uiLink = serverPage.links[UILINK]
+ if (uiLink != null) {
+ append(" URL - ")
+ append(URLBuilder(server).appendPathSegments(uiLink).buildString())
+ append(".")
+ }
+ }
+
+ private fun labelsAttachmentsInfo(
+ labelsUpdateResult: LabelsUpdateResult,
+ attachmentsUpdated: AttachmentsUpdateResult
+ ): String {
+ val labelsInfo = buildString {
+ if (labelsUpdateResult is LabelsUpdateResult.Updated) {
+ append("Labels ")
+ if (labelsUpdateResult.added.isNotEmpty()) {
+ append("+")
+ append("[")
+ append(labelsUpdateResult.added.joinToString(", "))
+ append("]")
+ if (labelsUpdateResult.removed.isNotEmpty()) {
+ append(", ")
+ }
+ }
+ if (labelsUpdateResult.removed.isNotEmpty()) {
+ append("-")
+ append("[")
+ append(labelsUpdateResult.removed.joinToString(", "))
+ append("]")
+ }
+ }
+ }
+ val attachmentsInfo = buildString {
+ if (attachmentsUpdated is AttachmentsUpdateResult.Updated) {
+ append("attachments: ")
+ append("added ${attachmentsUpdated.added.size}, ")
+ append(("modified ${attachmentsUpdated.modified.size}, "))
+ append("removed ${attachmentsUpdated.removed.size}")
+ }
+ }
+ val labelsAttachmentsDetails = listOf(labelsInfo, attachmentsInfo).filter { it.isNotBlank() }
+ return if (labelsAttachmentsDetails.isEmpty()) {
+ return ""
+ } else {
+ labelsAttachmentsDetails.joinToString(", ", postfix = ".")
+ }
+ }
+
+ override fun uploadsCompleted() {
+ val updated = updatedCount.get()
+ if (updated == 0L) {
+ print("All pages are up to date")
+ }
+ }
+
+ override fun pagesDeleted(root: ConfluencePage, allDeletedPages: List) {
+ if (allDeletedPages.isEmpty()) return
+
+ print(buildString {
+ append("Deleted: ")
+ append(deletedPage(allDeletedPages[0]))
+ if (allDeletedPages.size > 1) {
+ append(" with subpages:")
+ }
+ })
+
+ val tail = allDeletedPages.drop(1)
+ if (tail.isNotEmpty()) {
+ tail.forEach { page ->
+ print(" Deleted: ${deletedPage(page)}")
+ }
+ }
+ }
+
+ private fun deletedPage(confluencePage: ConfluencePage): String {
+ return buildString {
+ append("\"")
+ append(confluencePage.title)
+ append("\"")
+ append(" (")
+ append(confluencePage.id)
+ append(")")
+ }
+ }
+
+ private fun failedPage(error: PageOperationResult.Failed): String {
+ return buildString {
+ append("\"")
+ append(error.local.title)
+ append("\"")
+ append(" (")
+ append(error.status)
+ append(")")
+ append(" ")
+ append(error.body)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperations.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperations.kt
index 56e0b343..26d5313e 100644
--- a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperations.kt
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperations.kt
@@ -26,6 +26,7 @@ interface PageUploadOperations {
}
sealed class PageOperationResult {
+
data class NotModified(override val local: Page, override val serverPage: ServerPage) : PageOperationResult()
data class LocationModified(
override val local: Page,
@@ -41,6 +42,13 @@ sealed class PageOperationResult {
val parentChanged: Boolean = false
) : PageOperationResult()
+ data class Failed(
+ override val local: Page,
+ override val serverPage: ServerPage,
+ val status: Int,
+ val body: String?
+ ): PageOperationResult()
+
abstract val local: Page
abstract val serverPage: ServerPage
}
diff --git a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperationsImpl.kt b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperationsImpl.kt
index ae2cda31..f04ae0d5 100644
--- a/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperationsImpl.kt
+++ b/core/src/main/kotlin/com/github/zeldigas/text2confl/core/upload/PageUploadOperationsImpl.kt
@@ -62,29 +62,39 @@ internal class PageUploadOperationsImpl(
page: Page,
parentPageId: String
): PageOperationResult {
+
+
checkTenantBeforeUpdate(confluencePageToUpdate)
val (renamed, confluencePage) = adjustTitleIfRequired(confluencePageToUpdate, page)
val serverPageDetails = createServerPage(confluencePage, parentPageId);
- val result = if (pageContentChangeDetector.strategy(confluencePage, page.content)) {
- updatePageContent(confluencePage, parentPageId, page, serverPageDetails)
- } else if (confluencePage.parent?.id != parentPageId) {
- changePageParent(confluencePage, parentPageId, page, serverPageDetails, confluencePageToUpdate.title)
- } else if (renamed) {
- PageOperationResult.LocationModified(
+ try {
+ val result = if (pageContentChangeDetector.strategy(confluencePage, page.content)) {
+ updatePageContent(confluencePage, parentPageId, page, serverPageDetails)
+ } else if (confluencePage.parent?.id != parentPageId) {
+ changePageParent(confluencePage, parentPageId, page, serverPageDetails, confluencePageToUpdate.title)
+ } else if (renamed) {
+ PageOperationResult.LocationModified(
+ page,
+ serverPageDetails,
+ parentPageId,
+ confluencePageToUpdate.title
+ )
+ } else {
+ logger.info { "Page is up to date, nothing to do: ${confluencePage.id}, ${confluencePage.title}" }
+ PageOperationResult.NotModified(page, serverPageDetails)
+ }
+ setPageProperties(page, confluencePage)
+ return result
+ } catch (ex: PageNotUpdatedException) {
+ return PageOperationResult.Failed(
page,
serverPageDetails,
- parentPageId,
- confluencePageToUpdate.title
+ ex.status,
+ ex.body
)
- } else {
- logger.info { "Page is up to date, nothing to do: ${confluencePage.id}, ${confluencePage.title}" }
- PageOperationResult.NotModified(page, serverPageDetails)
}
- setPageProperties(page, confluencePage)
-
- return result
}
private suspend fun adjustTitleIfRequired(
@@ -200,21 +210,31 @@ internal class PageUploadOperationsImpl(
space: String,
parentPageId: String,
page: Page
- ): PageOperationResult.Created {
+ ): PageOperationResult {
logger.info { "Page does not exist, need to create it: ${page.title}" }
- val serverPage = client.createPage(
- PageContentInput(parentPageId, page.title, page.content.body, space),
- PageUpdateOptions(notifyWatchers, uploadMessage),
- expansions = listOf(
- "metadata.labels",
- "metadata.properties.$HASH_PROPERTY",
- "metadata.properties.$EDITOR_PROPERTY",
- "version",
- "children.attachment"
+ try {
+ val serverPage = client.createPage(
+ PageContentInput(parentPageId, page.title, page.content.body, space),
+ PageUpdateOptions(notifyWatchers, uploadMessage),
+ expansions = listOf(
+ "metadata.labels",
+ "metadata.properties.$HASH_PROPERTY",
+ "metadata.properties.$EDITOR_PROPERTY",
+ "version",
+ "children.attachment"
+ )
)
- )
- setPageProperties(page, serverPage)
- return PageOperationResult.Created(page, createServerPage(serverPage, parentPageId))
+ setPageProperties(page, serverPage)
+ return PageOperationResult.Created(page, createServerPage(serverPage, parentPageId))
+ } catch (ex: PageNotCreatedException) {
+ //TODO fix parent object to something better
+ return PageOperationResult.Failed(
+ page,
+ serverPage = ServerPage("fake","fake","fake", emptyList(), emptyList()),
+ ex.status,
+ ex.body
+ )
+ }
}
private suspend fun setPageProperties(
diff --git a/core/src/test/kotlin/com/github/zeldigas/text2confl/core/ContentValidatorImplTest.kt b/core/src/test/kotlin/com/github/zeldigas/text2confl/core/ContentValidatorImplTest.kt
index b9070dba..2124aa3f 100644
--- a/core/src/test/kotlin/com/github/zeldigas/text2confl/core/ContentValidatorImplTest.kt
+++ b/core/src/test/kotlin/com/github/zeldigas/text2confl/core/ContentValidatorImplTest.kt
@@ -23,7 +23,7 @@ internal class ContentValidatorImplTest {
every { content.validate() } returns Validation.Ok
every { children } returns emptyList()
})
- }))
+ }),)
}
}
@@ -47,7 +47,7 @@ internal class ContentValidatorImplTest {
},
)
- )
+ ,)
}.isInstanceOf(ContentValidationFailedException::class)
.transform { it.errors }.isEqualTo(listOf("${Path.of("a", "b.txt")}: err1", "c.txt: err2"))
}
diff --git a/core/src/test/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfigTest.kt b/core/src/test/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfigTest.kt
index 20951fb9..c7b56ab2 100644
--- a/core/src/test/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfigTest.kt
+++ b/core/src/test/kotlin/com/github/zeldigas/text2confl/core/config/DirectoryConfigTest.kt
@@ -14,8 +14,8 @@ import kotlin.io.path.writeText
class DirectoryConfigTest {
@Test
fun `Properly read from file`(@TempDir dir: Path) {
- dir.resolve(".text2confl.yml").writeText(
- DirectoryConfig::class.java.getResourceAsStream("/data/.text2confl.yml")!!.reader().readText()
+ dir.resolve("text2confl.yml").writeText(
+ DirectoryConfig::class.java.getResourceAsStream("/data/text2confl.yml")!!.reader().readText()
)
val config = readDirectoryConfig(dir)
diff --git a/core/src/test/resources/data/.text2confl.yml b/core/src/test/resources/data/text2confl.yml
similarity index 100%
rename from core/src/test/resources/data/.text2confl.yml
rename to core/src/test/resources/data/text2confl.yml
diff --git a/docs/configuration-reference.md b/docs/configuration-reference.md
index fd3a3925..1ddd8ab8 100644
--- a/docs/configuration-reference.md
+++ b/docs/configuration-reference.md
@@ -1,19 +1,17 @@
# Configuration reference
-On this page you can find information about configuration options available in `.text2confl.yml` file as well as their
+On this page you can find information about configuration options available in `text2confl.yml` file as well as their
alternatives in command line or env variables format.
## Configuration options
!!! warning
- Keep in mind the lookup order of values:
-
- 1. command line argument
- 2. environment variable
- 3. value in `.text2confl.yml`/`.textconfl.yaml`/`text2confl.yml`/`text2confl.yaml` file (whatever is found first)
-
- For brevity, we will use `.text2confl.yml` in examples below.
+ Keep in mind the lookup order of values:
+
+ 1. command line argument
+ 2. environment variable
+ 3. value in `text2confl.yml`
| configuration file | cli option | env variable | description |
|------------------------------|--------------------------------------------|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -38,7 +36,7 @@ alternatives in command line or env variables format.
### Markdown configuration options
-Markdown can be configured in `.text2confl.yml` file, in `markdown` section.
+Markdown can be configured in `text2confl.yml` file, in `markdown` section.
Table contains available parameters. Dot (`.`) means that this is next level, e.g.
@@ -74,7 +72,7 @@ markdown:
### AsciiDoc configuration options
-AsciiDoc can be configured in `.text2confl.yml` file, in `asciidoc` section.
+AsciiDoc can be configured in `text2confl.yml` file, in `asciidoc` section.
Table contains available parameters. Dot (`.`) means that this is next level, e.g.
@@ -117,7 +115,7 @@ Edit source file instead of changing page i
You can specify your own text if you prefer it to be different. Note supports 2 parameters:
1. `__doc-root__` - will be replaced by value of `docs-location` option from config
-2. `__file__` - will be replaced by path to file from document root (directory where `.text2confl.yml` is located)
+2. `__file__` - will be replaced by path to file from document root (directory where `text2confl.yml` is located)
## Additional options for `upload` command
diff --git a/docs/storage-formats/asciidoc/diagrams.adoc b/docs/storage-formats/asciidoc/diagrams.adoc
index 6e87f6c2..67bce86d 100644
--- a/docs/storage-formats/asciidoc/diagrams.adoc
+++ b/docs/storage-formats/asciidoc/diagrams.adoc
@@ -17,7 +17,7 @@ As link:https://docs.asciidoctor.org/diagram-extension/latest/blocks/[official A
With block or macro attributes, you can control name of generated file, file format and diagram-specific features.
-Some attributes such as diagram file format can be convenient to configure not on page, but in `.text2confl.yml` file.
+Some attributes such as diagram file format can be convenient to configure not on page, but in `text2confl.yml` file.
=== Inlined
@@ -46,7 +46,7 @@ include::_assets/example.adoc[tag=diagram]
By default, generated diagrams are saved in `.asciidoc` directory under documents root.
-This is configurable with the following parameters in `.text2confl.yml` file
+This is configurable with the following parameters in `text2confl.yml` file
[source,yaml]
----
diff --git a/docs/storage-formats/asciidoc/toc.adoc b/docs/storage-formats/asciidoc/toc.adoc
index 4204bd64..85a77f71 100644
--- a/docs/storage-formats/asciidoc/toc.adoc
+++ b/docs/storage-formats/asciidoc/toc.adoc
@@ -59,7 +59,7 @@ Example: `+toc::[style=square]+` will generate styled TOC in Confluence
With attributes, you can control only depth of generated TOC.
WARNING: AsciiDoc by default generates TOC with only first 2 levels of sections. Use `:toclevels: N` attribute to control this.
-If you want to customize it for all pages do in xref:../../configuration-reference.md[`.text2confl.yml` file]
+If you want to customize it for all pages do in xref:../../configuration-reference.md[`text2confl.yml` file]
=== AsciiDoc features that are not supported
Specifying a title for the table of contents using the `toc-title` attribute is currently not supported.
\ No newline at end of file
diff --git a/docs/storage-formats/markdown/diagrams.md b/docs/storage-formats/markdown/diagrams.md
index e6d1181d..dc4f1474 100644
--- a/docs/storage-formats/markdown/diagrams.md
+++ b/docs/storage-formats/markdown/diagrams.md
@@ -4,7 +4,7 @@ labels: supported-format,markdown
# Markdown - diagrams
-**text2confl** supports a number of text diagram formats to be embedded in Confluence page as code blocks:
+**text2confl** supports a number of text diagram formats to be embedded in confluence page as code blocks:
* [PlantUML](https://plantuml.com/en/)
* [Mermaid](https://mermaid.js.org/)
@@ -30,7 +30,7 @@ As every diagram is translated to a separate page attachment, you have two optio
By default, generated diagrams are saved in `.diagrams` directory under document's root.
-This is configurable with the following parameters in `.text2confl.yml` file
+This is configurable with the following parameters in `text2confl.yml` file
```yaml
markdown:
@@ -38,10 +38,10 @@ markdown:
# parameters here
```
-| name | description | default value |
-|------------|---------------------------------------------------------------------------------------------------|---------------|
-| `base-dir` | Base directory to store diagrams. Relative path is resolved from directory with `.text2confl.yml` | `.diagrams` |
-| `temp-dir` | Use random temporary directory instead of `base-dir` | `false` |
+| name | description | default value |
+|------------|--------------------------------------------------------------------------------------------------|---------------|
+| `base-dir` | Base directory to store diagrams. Relative path is resolved from directory with `text2confl.yml` | `.diagrams` |
+| `temp-dir` | Use random temporary directory instead of `base-dir` | `false` |
## Formats
@@ -86,20 +86,20 @@ Supported code-block attributes:
#### Generator configuration
-PlantUML parameters can be specified in `.text2confl.yml` file:
+PlantUML parameters can be specified in `text2confl.yml` file:
-```yaml {title=.text2confl.yml}
+```yaml {title=text2confl.yml}
markdown:
diagrams:
plantuml:
# parameters here
```
-| name | description | default value |
-|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
-| `enabled` | Enable PlantUML diagrams support | `true` |
-| `executable` | Command name to invoke for plantuml. There is no support for invoking a jar with `java -jar`, so you need to have a wrapper script that will do it and pass all arguments down. Relative path is resolved from directory with `.text2confl.yml` | `platuml` |
-| `default-format` | Format to use for generated images. Available options: `svg`, `png` | `png` |
+| name | description | default value |
+|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
+| `enabled` | Enable PlantUML diagrams support | `true` |
+| `executable` | Command name to invoke for plantuml. There is no support for invoking a jar with `java -jar`, so you need to have a wrapper script that will do it and pass all arguments down. Relative path is resolved from directory with `text2confl.yml` | `platuml` |
+| `default-format` | Format to use for generated images. Available options: `svg`, `png` | `png` |
### Mermaid
@@ -153,9 +153,9 @@ Supported code-block attributes:
#### Generator configuration
-Mermaid parameters can be specified in `.text2confl.yml` file:
+Mermaid parameters can be specified in `text2confl.yml` file:
-```yaml {title=.text2confl.yml}
+```yaml {title=text2confl.yml}
markdown:
diagrams:
mermaid:
@@ -165,11 +165,11 @@ markdown:
| name | description | default value |
|--------------------|----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| `enabled` | Enable Mermaid diagrams support | `true` |
-| `executable` | Command name to invoke for mermaid. Relative path is resolved from directory with `.text2confl.yml` | `mmdc` |
+| `executable` | Command name to invoke for mermaid. Relative path is resolved from directory with `text2confl.yml` | `mmdc` |
| `default-format` | Format to use for generated images. Available options: `svg`, `png` | `png` |
-| `config-file` | Mermaid configuration file to pass for every diagram invocation. Relative path is resolved from directory with `.text2confl.yml` | |
-| `css-file` | Mermaid css file to pass for every diagram. Relative path is resolved from directory with `.text2confl.yml` | |
-| `puppeeter-config` | Mermaid css file to pass for every diagram. Relative path is resolved from directory with `.text2confl.yml` | Value of `T2C_PUPPEETER_CONFIG` env variable |
+| `config-file` | Mermaid configuration file to pass for every diagram invocation. Relative path is resolved from directory with `text2confl.yml` | |
+| `css-file` | Mermaid css file to pass for every diagram. Relative path is resolved from directory with `text2confl.yml` | |
+| `puppeeter-config` | Mermaid css file to pass for every diagram. Relative path is resolved from directory with `text2confl.yml` | Value of `T2C_PUPPEETER_CONFIG` env variable |
### Kroki
@@ -233,9 +233,9 @@ Supported code-block attributes:
#### Generator configuration
-Kroki parameters can be specified in `.text2confl.yml` file:
+Kroki parameters can be specified in `text2confl.yml` file:
-```yaml {title=.text2confl.yml}
+```yaml {title=text2confl.yml}
markdown:
diagrams:
kroki:
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 0e5ec5ed..0dedc048 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -30,8 +30,7 @@ it and will put *root* pages in it.
#### Configuration file
-Configuration file is `.text2confl.yml` (or `.text2confl.yml` if you prefer this extension more) - create it in
-documentation root dir.
+Configuration file is `text2confl.yml` create it in documentation root dir.
For the start put the following contents:
@@ -85,7 +84,7 @@ because corresponding documents are present:
│ ├── markdown.md
│ └── markdown.png
├── storage-formats.md
-├── .text2confl.yml
+├── text2confl.yml
└── user-guide.md
```
@@ -178,7 +177,7 @@ docker run --rm -it -v ~/.config/text2confl:/root/.config/text2confl:ro -v $PWD:
## Adhoc upload
-If you just need to upload one file, or you are fine with providing all the options via command line it is possible to skip creation of `.text2confl.yml` file:
+If you just need to upload one file, or you are fine with providing all the options via command line it is possible to skip creation of `text2confl.yml` file:
```shell
text2confl upload --docs . \
diff --git a/docs/user-guide/multitenant.md b/docs/user-guide/multitenant.md
index 95164b62..72a16c2a 100644
--- a/docs/user-guide/multitenant.md
+++ b/docs/user-guide/multitenant.md
@@ -17,9 +17,9 @@ To solve this, you have 2 options:
## Configuring multi-tenancy
-In `.text2confl.yml` add `tenant` parameter:
+In `text2confl.yml` add `tenant` parameter:
-```yaml {title=".text2confl.yml}
+```yaml {title="text2confl.yml}
tenant: team-a
```
diff --git a/pom.xml b/pom.xml
index 6ecd114e..1a9c5f9a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,18 +1,19 @@
-
+4.0.0
- com.github.zeldigas.confluence
- parent
- 1.0.0-SNAPSHOT
+ io.github.text2confl
+ text2confl-parent
+ 0.16.2-SNAPSHOTpomText2Confl
- Publisher of pages in lightweight markup formats to Confluence
- https://github.com/zeldigas/text2confl
+
+ Publisher of pages in lightweight markup formats to Confluence.
+ Forked from https://github.com/zeldigas/text2confl to publish to maven
+
+ https://github.com/text2confl/text2confl
@@ -22,11 +23,22 @@
- scm:git:git@github.com:zeldigas/text2confl.git
- scm:git:git@github.com:zeldigas/text2confl.git
- https://github.com/zeldigas/text2confl
+ scm:git:git@github.com:text2confl/text2confl.git
+ scm:git:git@github.com:text2confl/text2confl.git
+ https://github.com/text2confl/text2confl
+ HEAD
+
+
+ zeldigas
+ Dmitry Pavlov
+ zeldigas@gmail.com
+ text2confl
+ https://github.com/text2confl/text2confl
+
+
+
1111
@@ -161,5 +173,133 @@
+
+
+ ossrh
+
+
+ ossrh
+ Central Repository OSSRH
+ https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+ ossrh
+ Central Repository OSSRH
+ https://s01.oss.sonatype.org/content/repositories/snapshots
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 3.1.0
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+ --pinentry-mode
+ loopback
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.3.0
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.6.0
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.jetbrains.dokka
+ dokka-maven-plugin
+ 1.9.10
+
+
+ package
+
+ javadocJar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.0.1
+
+ [ci skip]
+
+
+
+
+
+
+ github
+
+
+ github
+ GitHub Packages
+ https://maven.pkg.github.com/text2confl/text2confl
+
+
+
+
+ coverage
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.11
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+ jacoco-report
+ verify
+
+ report
+
+
+
+
+
+
+
+
+
\ No newline at end of file