Compare commits
6 Commits
main
...
feature/do
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d22c99c84 | |||
| ad980feee1 | |||
| 1b8b8269c6 | |||
| afe400036a | |||
| 4d545ff7c5 | |||
| 98e11b9da1 |
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
||||
**
|
||||
!src
|
||||
!Cargo.toml
|
||||
!Cargo.lock
|
||||
!flake.nix
|
||||
!flake.lock
|
||||
BIN
.github/assets/directory_structure.png
vendored
BIN
.github/assets/directory_structure.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 181 KiB |
23
.github/workflows/docker.yml
vendored
Normal file
23
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main", "feature/docker"]
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hustcer/setup-nu@v3
|
||||
|
||||
- name: Get Cargo version
|
||||
run: version=$(nu -c "cargo metadata --format-version=1 --no-deps | from json | get packages | first | get version")
|
||||
- name: Build docker image
|
||||
run: docker build -t docki:$version .
|
||||
40
.github/workflows/docker_deploy.yml
vendored
40
.github/workflows/docker_deploy.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: Deploy Docker Image to Github Container Registry
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths:
|
||||
- "Cargo.toml"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hustcer/setup-nu@v3
|
||||
- uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- run: nix build .#docker
|
||||
|
||||
- run: |
|
||||
export CARGO_VERSION=$(nu -c "cargo metadata --format-version=1 --no-deps | from json | get packages | first | get version")
|
||||
echo "CARGO_VERSION=$CARGO_VERSION" >> $GITHUB_ENV
|
||||
|
||||
- run: docker load -i result
|
||||
- name: Log in to registry
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
- run: docker tag docki:latest "ghcr.io/quirinecker/docki:$CARGO_VERSION"
|
||||
- run: docker tag docki:latest "ghcr.io/quirinecker/docki:latest"
|
||||
- run: docker push ghcr.io/quirinecker/docki:$CARGO_VERSION
|
||||
- run: docker push ghcr.io/quirinecker/docki:latest
|
||||
29
.github/workflows/rust.yml
vendored
Normal file
29
.github/workflows/rust.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- 'Cargo.toml'
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
- name: Publish to crates.io
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
|
||||
run: |
|
||||
cargo publish --verbose
|
||||
26
.github/workflows/rust_deploy.yml
vendored
26
.github/workflows/rust_deploy.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Deploy Rust to Crates.io
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths:
|
||||
- "./Cargo.toml"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: cargo build --release --bin docki
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
- name: Publish to crates.io
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
|
||||
run: |
|
||||
cargo publish --verbose
|
||||
24
.github/workflows/rust_test.yml
vendored
24
.github/workflows/rust_test.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Test Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main", "develop"]
|
||||
paths:
|
||||
- "./src/**"
|
||||
- "./Cargo.toml"
|
||||
pull_request:
|
||||
branches: ["main", "develop"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
/target
|
||||
dist
|
||||
/docs
|
||||
res/test/docs/slides/revealjs
|
||||
res/test/asciidocs/slides/revealjs
|
||||
res/test/result
|
||||
result
|
||||
|
||||
20
.gitlab-ci.yml
Normal file
20
.gitlab-ci.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
workflow:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'
|
||||
|
||||
default:
|
||||
image: 'quirinecker/rust-openssl'
|
||||
|
||||
build:
|
||||
script:
|
||||
- cargo build
|
||||
|
||||
test:
|
||||
script:
|
||||
- cargo test
|
||||
|
||||
# publish:
|
||||
# script:
|
||||
# - export CARGO_REGISTRY_TOKEN=$CARGO_TOKEN
|
||||
# - cargo publish
|
||||
|
||||
|
Before Width: | Height: | Size: 18 MiB After Width: | Height: | Size: 18 MiB |
2933
Cargo.lock
generated
2933
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
20
Cargo.toml
20
Cargo.toml
@@ -1,26 +1,20 @@
|
||||
[package]
|
||||
name = "docki"
|
||||
version = "1.3.0"
|
||||
version = "1.2.1"
|
||||
edition = "2021"
|
||||
description = "cli for building and publishing documentation using asciidoctor"
|
||||
license-file = "LICENSE.txt"
|
||||
authors = ["Quirin Ecker"]
|
||||
exclude = [".gitlab", ".github"]
|
||||
default-run = "docki"
|
||||
|
||||
[[bin]]
|
||||
name = "docki"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "util"
|
||||
path = "src/util.rs"
|
||||
exclude = [
|
||||
".gitlab"
|
||||
]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.4.0"
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
colored = "2.0.0"
|
||||
futures = "0.3.26"
|
||||
home = "0.5.4"
|
||||
live-server = "0.6.0"
|
||||
@@ -31,7 +25,3 @@ text_io = "0.1.12"
|
||||
tokio = { version = "1.26.0", features = ["full"] }
|
||||
zip-extract = "0.1.1"
|
||||
clap_complete = "4.1.4"
|
||||
nu-ansi-term = "0.50.3"
|
||||
config = { version = "0.15.18", features = ["toml"] }
|
||||
serde = "1.0.228"
|
||||
toml = "0.9.6"
|
||||
|
||||
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
||||
FROM nixos/nix AS build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . /app
|
||||
|
||||
RUN nix --extra-experimental-features nix-command --extra-experimental-features flakes build \
|
||||
&& nix --extra-experimental-features nix-command --extra-experimental-features flakes store gc
|
||||
|
||||
RUN mkdir /out && cp result/bin/docki .
|
||||
|
||||
61
README.md
61
README.md
@@ -1,22 +1,19 @@
|
||||
# Docki
|
||||
|
||||
> [!NOTE]
|
||||
> This project is under renovations. It can be used, but it might not be completely stable yet.
|
||||
|
||||
|
||||
## Preview
|
||||
|
||||

|
||||

|
||||
|
||||
Docki is cli for converting asciidoctor files into html files.
|
||||
|
||||
## Usage
|
||||
|
||||
Docki must be run in a directory with the following structure
|
||||
|
||||

|
||||
|
||||
1. Will be converted into asciidoc format
|
||||
2. Will be converted into asciidocs slides
|
||||
|
||||
> [!NOTE]
|
||||
> The input directory can be defined either with a cli argument or the config file. Default is `./docs`
|
||||
> This works in a directory with a directory called `docs`, which contains the asciidoctor documentation.
|
||||
|
||||
### Building the documentation
|
||||
|
||||
@@ -24,7 +21,7 @@ Docki must be run in a directory with the following structure
|
||||
docki build
|
||||
```
|
||||
|
||||
### Serving the documentation with a live server
|
||||
### Serving the documentation on a live server
|
||||
|
||||
```shell
|
||||
docki serve
|
||||
@@ -32,26 +29,29 @@ docki serve
|
||||
|
||||
## Installation
|
||||
|
||||
### Homebrew
|
||||
### Nix
|
||||
|
||||
This installation method is recommended, because it will include both asciidoctor and asciidoctor_revealjs.
|
||||
|
||||
Note: This is the most basic installation. If you are already more experienced, you might want to add it to your shell or home manager configuration.
|
||||
|
||||
```shell
|
||||
brew tap quirinecker/homebrew-docki https://github.com/quirinecker/homebrew-docki
|
||||
nix profile install github:quirinecker/docki
|
||||
```
|
||||
|
||||
### Homebrew
|
||||
|
||||
> [!NOTE]
|
||||
> Installing it via homebrew will not include asciidoctor_revealjs. It can be installed afterwards with `docki install-reveal`
|
||||
|
||||
```shell
|
||||
brew tap quirinecker/docki-homebrew https://github.com/quirinecker/docki-homebrew
|
||||
```
|
||||
|
||||
```
|
||||
brew install docki
|
||||
```
|
||||
|
||||
### Nix
|
||||
|
||||
If you just want to try it out real quick and the nix package manager is available on your system you can use the following command.
|
||||
|
||||
```shell
|
||||
nix develop github:quirinecker/docki#preview
|
||||
```
|
||||
|
||||
This will open a shell evnironment with docki installed. If you want to install it permanently with nix, i would recommend following the instructions in the [Nix (Advanced, Flake)](#nix-advanced-flake) section.
|
||||
|
||||
### Cargo
|
||||
|
||||
> [!NOTE]
|
||||
@@ -61,19 +61,6 @@ This will open a shell evnironment with docki installed. If you want to install
|
||||
cargo install docki
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
There is also a docker image available to use. It is primarily used for the gh actions.
|
||||
|
||||
```shell
|
||||
docker pull ghcr.io/quirinecker/docki:latest
|
||||
```
|
||||
|
||||
You can also build it yourself with nix.
|
||||
|
||||
```
|
||||
nix build .#docker && docker load -i result
|
||||
```
|
||||
|
||||
### Nix (Advanced, Flake)
|
||||
|
||||
@@ -115,10 +102,6 @@ home.packages = with pkgs; [
|
||||
]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
You can configure some of the cli arguments with a config file. It is always located relatively to the current directory under `./docki.config.toml`. Available options and their defaults can be found in the [docki.config.toml](config/docki.config.toml) file. CLI arguments with the same names as in the config usually have also the same default values. As a fallback you can also use the [config.rs](src/app/config/config.rs) file for reference.
|
||||
|
||||
## Development
|
||||
|
||||
### Running it
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
port = 8080
|
||||
input_dir = "./docs"
|
||||
offline_reveal = false
|
||||
output_dir = "./dist"
|
||||
25
flake.nix
25
flake.nix
@@ -64,11 +64,6 @@
|
||||
libiconv
|
||||
makeWrapper
|
||||
];
|
||||
binaries = [ "docki" ];
|
||||
# only including the main binary in build
|
||||
# There is no better option at the time of writing this
|
||||
# https://github.com/nix-community/naersk/issues/127
|
||||
copyBinsFilter = ''select(.reason == "compiler-artifact" and .executable != null and .profile.test == false and .target.name == "docki")'';
|
||||
postInstall = ''
|
||||
mkdir -p $out/share/bash-completion/completions
|
||||
mkdir -p $out/share/zsh/site-functions
|
||||
@@ -125,26 +120,6 @@
|
||||
naerskLib = naerskLib;
|
||||
pkgs = pkgs;
|
||||
};
|
||||
|
||||
docker = pkgs.dockerTools.buildImage {
|
||||
name = "docki";
|
||||
tag = "latest";
|
||||
config = {
|
||||
WorkingDir = "/app";
|
||||
};
|
||||
copyToRoot = pkgs.buildEnv {
|
||||
name = "docki-docker";
|
||||
paths = [
|
||||
pkgs.coreutils
|
||||
pkgs.bash
|
||||
pkgs.cacert
|
||||
(build_docki {
|
||||
naerskLib = naerskLib;
|
||||
pkgs = pkgs;
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
= My Project
|
||||
:toc:
|
||||
:toc-title:
|
||||
:toclevels: 2
|
||||
|
||||
== Introduction
|
||||
|
||||
This is my project.
|
||||
|
||||
== Slides
|
||||
|
||||
* link:slides/index.html[Presentation]
|
||||
|
||||
== License
|
||||
|
||||
This project is licensed under the MIT License - see the link:LICENSE[LICENSE] file for details.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Slides
|
||||
|
||||
## Slide 1
|
||||
|
||||
* First
|
||||
* Second
|
||||
* Third
|
||||
|
||||
## Slide 2
|
||||
|
||||
* First
|
||||
* Second
|
||||
* Third
|
||||
|
||||
### Slide 3
|
||||
|
||||
* First
|
||||
* Second
|
||||
* Third
|
||||
@@ -1,3 +0,0 @@
|
||||
docs_dir = "./asciidocs"
|
||||
port = 6969
|
||||
offline_reveal = false
|
||||
0
res/test/docs/core/functions.adoc
Normal file
0
res/test/docs/core/functions.adoc
Normal file
0
res/test/docs/core/index.adoc
Normal file
0
res/test/docs/core/index.adoc
Normal file
0
res/test/docs/fail.txt
Normal file
0
res/test/docs/fail.txt
Normal file
0
res/test/docs/functions.adoc
Normal file
0
res/test/docs/functions.adoc
Normal file
@@ -1,16 +0,0 @@
|
||||
= My Project
|
||||
:toc:
|
||||
:toc-title:
|
||||
:toclevels: 2
|
||||
|
||||
== Introduction
|
||||
|
||||
This is my project.
|
||||
|
||||
== Slides
|
||||
|
||||
* link:slides/index.html[Presentation]
|
||||
|
||||
== License
|
||||
|
||||
This project is licensed under the MIT License - see the link:LICENSE[LICENSE] file for details.
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Slides
|
||||
|
||||
## Slide 1
|
||||
|
||||
* First
|
||||
* Second
|
||||
* Third
|
||||
|
||||
## Slide 2
|
||||
|
||||
* First
|
||||
* Second
|
||||
* Third
|
||||
|
||||
### Slide 3
|
||||
|
||||
* First
|
||||
* Second
|
||||
* Third
|
||||
@@ -1,10 +1,10 @@
|
||||
use clap::Parser;
|
||||
|
||||
use self::arguments::Args;
|
||||
use self::structure::Args;
|
||||
|
||||
pub mod arguments;
|
||||
pub mod config;
|
||||
pub mod structure;
|
||||
|
||||
pub fn args() -> Args {
|
||||
return Args::parse();
|
||||
|
||||
}
|
||||
35
src/app/args/structure.rs
Normal file
35
src/app/args/structure.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser)]
|
||||
pub struct Args {
|
||||
#[command(subcommand)]
|
||||
pub command: CommandArg,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum ShellArg {
|
||||
Bash,
|
||||
Fish,
|
||||
Zsh,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum CommandArg {
|
||||
/// Builds the documentation into a dist folder
|
||||
Build,
|
||||
/// Checks if everything required for docki is installed
|
||||
Health,
|
||||
/// Helper command for installing asciidoctor-reveal-js
|
||||
InstallReveal,
|
||||
/// Starts a Webserver with the live preview of the Documentation
|
||||
Serve {
|
||||
/// Port for the Live Server
|
||||
#[arg(short, long)]
|
||||
port: Option<u16>,
|
||||
},
|
||||
/// Generates completions for the desired shell
|
||||
Completions {
|
||||
#[command(subcommand)]
|
||||
shell: ShellArg,
|
||||
},
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
use regex::Regex;
|
||||
use std::process;
|
||||
|
||||
use crate::app::config::config::Config;
|
||||
|
||||
fn exec_command(command: &mut process::Command) -> Result<(), String> {
|
||||
let result = command.output();
|
||||
|
||||
@@ -14,13 +11,9 @@ fn exec_command(command: &mut process::Command) -> Result<(), String> {
|
||||
}
|
||||
} else {
|
||||
println!("{}", result.unwrap_err());
|
||||
|
||||
let binary_name = command.get_program().to_str().unwrap_or("Something is");
|
||||
|
||||
return Err(format!(
|
||||
"{} not installed. For more information run docki health!",
|
||||
binary_name
|
||||
));
|
||||
return Err(
|
||||
"asciidoctor not installed. For more information run docki health!".to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,17 +27,9 @@ fn asciidoctor_docs(in_path: &str, out_path: &str) -> process::Command {
|
||||
return command;
|
||||
}
|
||||
|
||||
fn asciidoctor_slides(in_path: &str, out_path: &str, config: &Config) -> process::Command {
|
||||
fn asciidoctor_slides(in_path: &str, out_path: &str) -> process::Command {
|
||||
let mut command = process::Command::new(format!("asciidoctor-revealjs"));
|
||||
let out_dir = parent_path(out_path);
|
||||
let revealjs_path = if config.offline_reveal {
|
||||
path_between(
|
||||
out_dir.to_string(),
|
||||
format!("{}/slides/revealjs", config.output_dir),
|
||||
)
|
||||
} else {
|
||||
"https://cdn.jsdelivr.net/npm/reveal.js@5.2.1".to_string()
|
||||
};
|
||||
let revealjs_path = "/slides/revealjs";
|
||||
|
||||
command
|
||||
.arg(format!("{in_path}"))
|
||||
@@ -55,67 +40,13 @@ fn asciidoctor_slides(in_path: &str, out_path: &str, config: &Config) -> process
|
||||
return command;
|
||||
}
|
||||
|
||||
fn parent_path(child_path: &str) -> String {
|
||||
let split: Vec<&str> = child_path.split("/").collect();
|
||||
let slice = &split[..split.len() - 1];
|
||||
return slice.join("/");
|
||||
}
|
||||
|
||||
pub fn path_between(from: String, to: String) -> String {
|
||||
let from_segments = transform_input_to_clone_split(&from);
|
||||
let to_segments = transform_input_to_clone_split(&to);
|
||||
let last_matching_index = matching_from_start(&from_segments, &to_segments);
|
||||
let number_of_backs = from_segments.len() - last_matching_index;
|
||||
let mut path_between = path_back(number_of_backs);
|
||||
let path_to_to_path = &to_segments[last_matching_index..];
|
||||
path_between.push_str(&path_to_to_path.join("/"));
|
||||
return path_between;
|
||||
}
|
||||
|
||||
fn transform_input_to_clone_split(input: &String) -> Vec<String> {
|
||||
let regex = Regex::new(r"/$").unwrap();
|
||||
let first_transformation = input.clone().replace("./", "");
|
||||
return regex
|
||||
.replace_all(&first_transformation, "")
|
||||
.to_string()
|
||||
.split("/")
|
||||
.collect::<Vec<&str>>()
|
||||
.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
}
|
||||
|
||||
fn path_back(count: usize) -> String {
|
||||
let mut path = "".to_string();
|
||||
|
||||
for _ in 0..count {
|
||||
path.push_str("../");
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
pub fn matching_from_start(from_segments: &Vec<String>, to_segments: &Vec<String>) -> usize {
|
||||
for (index, from_segment) in from_segments.iter().enumerate() {
|
||||
if let Some(to_segment) = to_segments.get(index) {
|
||||
if from_segment != to_segment {
|
||||
return index;
|
||||
}
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return from_segments.len();
|
||||
}
|
||||
|
||||
pub fn build_doc(in_path: &str, out_path: &str, _: &Config) -> Result<(), String> {
|
||||
pub fn build_doc(in_path: &str, out_path: &str) -> Result<(), String> {
|
||||
let mut command = asciidoctor_docs(in_path, out_path);
|
||||
return exec_command(&mut command);
|
||||
}
|
||||
|
||||
pub fn build_slide(in_path: &str, out_path: &str, config: &Config) -> Result<(), String> {
|
||||
let mut command = asciidoctor_slides(in_path, out_path, config);
|
||||
pub fn build_slide(in_path: &str, out_path: &str) -> Result<(), String> {
|
||||
let mut command = asciidoctor_slides(in_path, out_path);
|
||||
return exec_command(&mut command);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,121 +1,29 @@
|
||||
use std::fs;
|
||||
|
||||
use self::asciidoctor::{build_doc, build_slide};
|
||||
|
||||
use super::fs_util;
|
||||
|
||||
pub mod asciidoctor;
|
||||
|
||||
use std::{
|
||||
fs, io::Cursor, path::PathBuf
|
||||
};
|
||||
|
||||
use crate::app::{
|
||||
build::{asciidoctor::build_slide, asciidoctor::build_doc}, config::config::Config, fs_util::{self, create_dir_recursive}, log::display_status
|
||||
};
|
||||
|
||||
pub struct DockiBuilder<'a> {
|
||||
progress: usize,
|
||||
goal: usize,
|
||||
config: &'a Config
|
||||
}
|
||||
|
||||
impl <'a> DockiBuilder <'a> {
|
||||
pub fn new(config: &'a Config) -> Self {
|
||||
return Self {
|
||||
progress: 0,
|
||||
goal: 0,
|
||||
config: config
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Prepares everything for building the documentation
|
||||
///
|
||||
/// 1. Checks if the input directory exists and if not, returns an error
|
||||
/// 2. When offline_reveal is set to true, it downloads revealjs. When it fails, it returns an error
|
||||
pub async fn prepare(&self) -> Result<(), String> {
|
||||
if !fs_util::directory_exists(&self.config.input_dir) {
|
||||
return Err(
|
||||
"docs directory does not exist it. Create it or use the template".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
if !self.config.offline_reveal {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let reveal_version = "5.2.1";
|
||||
let target = format!("https://github.com/hakimel/reveal.js/archive/{reveal_version}.zip");
|
||||
|
||||
create_dir_recursive(format!("{}/slides", self.config.input_dir).as_str());
|
||||
|
||||
reqwest::get(target.clone()).await.unwrap();
|
||||
let Ok(response) = reqwest::get(target).await else {
|
||||
return Err("could not downlaod revealjs".to_string())
|
||||
};
|
||||
|
||||
let Ok(bytes) = response.bytes().await else {
|
||||
return Err("could not extract bytes".to_string())
|
||||
};
|
||||
|
||||
let out = PathBuf::from(format!("{}/slides/revealjs", self.config.input_dir));
|
||||
|
||||
if zip_extract::extract(Cursor::new(bytes), &out, true).is_err() {
|
||||
return Err("could not write extracted archive to disk".to_string());
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
/// Builds all files in the input directory with a pretty output
|
||||
pub fn build_docs(&mut self) -> Result<(), String> {
|
||||
let result = fs_util::fetch_paths_recursive(&self.config.input_dir);
|
||||
let Ok(paths) = result else {
|
||||
return Err(result.unwrap_err())
|
||||
};
|
||||
|
||||
let reveal_dir = format!("{}/slides/revealjs", self.config.input_dir);
|
||||
let paths = paths.into_iter()
|
||||
.filter(|path| self.config.offline_reveal || !path.starts_with(reveal_dir.as_str()))
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
self.goal = paths.len();
|
||||
|
||||
for (index, in_path) in paths.iter().enumerate() {
|
||||
self.progress = index + 1;
|
||||
let result = self.build_file(&in_path);
|
||||
|
||||
match result {
|
||||
DockiBuildResult::Err(err) => {
|
||||
self.display_building_status("Error", &in_path, "");
|
||||
println!("{}", err)
|
||||
},
|
||||
DockiBuildResult::Copy(out_path) => self.display_building_status("Copy", &in_path, &out_path),
|
||||
DockiBuildResult::Slide(out_path) => self.display_building_status("Slide", &in_path, &out_path),
|
||||
DockiBuildResult::Doc(out_path) => self.display_building_status("Doc", &in_path, &out_path),
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
/// Builds a single file without a pretty output
|
||||
pub fn build_file(&self, path: &str) -> DockiBuildResult {
|
||||
let out_path = path.replace(&self.config.input_dir, &self.config.output_dir);
|
||||
pub fn docki_build(in_path: &str) -> DockiBuildResult {
|
||||
let out_path = in_path.replace("/docs/", "/dist/");
|
||||
let convert_out_path = out_path.replace(".adoc", ".html");
|
||||
|
||||
if path.starts_with(format!("{}/slides/", &self.config.input_dir).as_str()) && path.ends_with(".adoc") {
|
||||
if let Err(err) = build_slide(&path, &convert_out_path, self.config) {
|
||||
if in_path.starts_with("./docs/slides/") && in_path.ends_with(".adoc") {
|
||||
if let Err(err) = build_slide(&in_path, &convert_out_path) {
|
||||
return DockiBuildResult::Err(err);
|
||||
}
|
||||
|
||||
DockiBuildResult::Slide(convert_out_path)
|
||||
} else if path.ends_with(".adoc") {
|
||||
if let Err(err) = build_doc(&path, &convert_out_path, self.config) {
|
||||
} else if in_path.ends_with(".adoc") {
|
||||
if let Err(err) = build_doc(&in_path, &convert_out_path) {
|
||||
return DockiBuildResult::Err(err);
|
||||
}
|
||||
|
||||
DockiBuildResult::Doc(convert_out_path)
|
||||
} else {
|
||||
if let Err(err) = Self::copy(&path, &out_path) {
|
||||
if let Err(err) = copy(&in_path, &out_path) {
|
||||
return DockiBuildResult::Err(err);
|
||||
}
|
||||
|
||||
@@ -133,15 +41,6 @@ impl <'a> DockiBuilder <'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_building_status(&self, status_type: &str, in_path: &str, out_path: &str) -> () {
|
||||
let progress_str = format!("{} / {}", self.progress, self.goal);
|
||||
display_status(&progress_str, status_type, in_path, out_path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Used for the Result of build_file. This way it is known what the builder did
|
||||
pub enum DockiBuildResult {
|
||||
Slide(String),
|
||||
Doc(String),
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
use crate::app::config::config::Config;
|
||||
use super::executions::build_execution::BuildExecution;
|
||||
|
||||
use crate::app::build::DockiBuilder;
|
||||
|
||||
pub async fn build(config: &Config) -> () {
|
||||
let mut builder = DockiBuilder::new(config);
|
||||
|
||||
builder.prepare().await.expect("could not prepare for build");
|
||||
builder.build_docs().expect("build failed")
|
||||
pub async fn build() -> () {
|
||||
let mut build_execution = BuildExecution::new();
|
||||
build_execution.execute().await.expect("build failed")
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::io;
|
||||
use clap::CommandFactory;
|
||||
use clap_complete::{generate, shells::{Bash, Fish, Zsh}};
|
||||
|
||||
use crate::app::config::arguments::{Args, ShellArg};
|
||||
use crate::app::args::structure::{Args, ShellArg};
|
||||
|
||||
pub fn completions(shell: ShellArg) {
|
||||
let mut command = Args::command();
|
||||
|
||||
95
src/app/commands/executions/build_execution.rs
Normal file
95
src/app/commands/executions/build_execution.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
use std::{
|
||||
io::Cursor,
|
||||
path::PathBuf
|
||||
};
|
||||
|
||||
use crate::app::{
|
||||
build::{docki_build, DockiBuildResult},
|
||||
fs_util::{self, create_dir_recursive}, log::display_status,
|
||||
};
|
||||
|
||||
pub struct BuildExecution {
|
||||
progress: usize,
|
||||
goal: usize,
|
||||
}
|
||||
|
||||
impl BuildExecution {
|
||||
pub fn new() -> Self {
|
||||
return BuildExecution {
|
||||
progress: 0,
|
||||
goal: 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub async fn execute(&mut self) -> Result<(), String> {
|
||||
let path = "./docs/".to_string();
|
||||
|
||||
if !fs_util::directory_exists(&path) {
|
||||
return Err(
|
||||
"docs directory does not exist it. Create it or use the template".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
if let Err(error) = Self::prepare().await {
|
||||
return Err(error);
|
||||
}
|
||||
|
||||
return self.build_dir(&path);
|
||||
}
|
||||
|
||||
|
||||
async fn prepare() -> Result<(), String> {
|
||||
let reveal_version = "3.9.2";
|
||||
let target = format!("https://github.com/hakimel/reveal.js/archive/{reveal_version}.zip");
|
||||
|
||||
create_dir_recursive("./docs/slides");
|
||||
|
||||
let Ok(response) = reqwest::get(target).await else {
|
||||
return Err("could not downlaod revealjs".to_string())
|
||||
};
|
||||
|
||||
let Ok(bytes) = response.bytes().await else {
|
||||
return Err("could not extract bytes".to_string())
|
||||
};
|
||||
|
||||
let out = PathBuf::from("./docs/slides/revealjs");
|
||||
|
||||
if zip_extract::extract(Cursor::new(bytes), &out, true).is_err() {
|
||||
return Err("could not write extracted archive to disk".to_string());
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn build_dir(&mut self, path: &str) -> Result<(), String> {
|
||||
let result = fs_util::fetch_paths_recursive(&path);
|
||||
|
||||
let Ok(paths) = result else {
|
||||
return Err(result.unwrap_err())
|
||||
};
|
||||
|
||||
for (index, in_path) in paths.iter().enumerate() {
|
||||
self.progress = index + 1;
|
||||
self.goal = paths.len();
|
||||
let result = docki_build(&in_path);
|
||||
|
||||
match result {
|
||||
DockiBuildResult::Err(err) => {
|
||||
self.display_building_status("Error", in_path, "");
|
||||
println!("{}", err)
|
||||
},
|
||||
DockiBuildResult::Copy(out_path) => self.display_building_status("Copy", &in_path, &out_path),
|
||||
DockiBuildResult::Slide(out_path) => self.display_building_status("Slide", &in_path, &out_path),
|
||||
DockiBuildResult::Doc(out_path) => self.display_building_status("Doc", &in_path, &out_path)
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn display_building_status(&self, status_type: &str, in_path: &str, out_path: &str) -> () {
|
||||
let progress_str = format!("{} / {}", self.progress, self.goal);
|
||||
display_status(&progress_str, status_type, in_path, out_path);
|
||||
}
|
||||
|
||||
}
|
||||
1
src/app/commands/executions/mod.rs
Normal file
1
src/app/commands/executions/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod build_execution;
|
||||
@@ -1,5 +1,5 @@
|
||||
use nu_ansi_term::Color::{LightGray, LightGreen, LightRed};
|
||||
use std::{io::ErrorKind, process::Command};
|
||||
use std::{process::Command, io::ErrorKind};
|
||||
use colored::Colorize;
|
||||
|
||||
const INFO_ASCIIDOC: &str = "
|
||||
Install the binary with your package manager!
|
||||
@@ -37,7 +37,7 @@ fn check_reveal() -> () {
|
||||
}
|
||||
|
||||
fn reveal_is_installed() -> bool {
|
||||
return check_command("asciidoctor-revealjs");
|
||||
return check_command("asciidoctor-revealjs")
|
||||
}
|
||||
|
||||
fn check_asciidoc() -> () {
|
||||
@@ -49,21 +49,23 @@ fn check_asciidoc() -> () {
|
||||
}
|
||||
|
||||
fn asciidoc_is_installed() -> bool {
|
||||
return check_command("asciidoctor");
|
||||
return check_command("asciidoctor")
|
||||
}
|
||||
|
||||
fn check_command(command: &str) -> bool {
|
||||
return match Command::new(command).output() {
|
||||
return match Command::new(command)
|
||||
.output() {
|
||||
Ok(_) => true,
|
||||
Err(e) => ErrorKind::NotFound != e.kind(),
|
||||
};
|
||||
Err(e) => ErrorKind::NotFound != e.kind()
|
||||
}
|
||||
}
|
||||
|
||||
fn print_health_ok(name: &str) {
|
||||
println!("- ✔️ {}", LightGreen.paint(name));
|
||||
println!("- ✔️ {}", name.bright_green());
|
||||
}
|
||||
|
||||
fn print_health_not_ok(name: &str, info: &str) {
|
||||
println!("- ❗{}", LightRed.paint(name));
|
||||
println!("{}", LightGray.paint(info))
|
||||
println!("- ❗{}", name.bright_red());
|
||||
println!("{}", info.bright_black())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod build;
|
||||
pub mod completions;
|
||||
pub mod executions;
|
||||
pub mod health;
|
||||
pub mod install_reveal;
|
||||
pub mod serve;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use nu_ansi_term::Color::Green;
|
||||
use colored::Colorize;
|
||||
use futures::StreamExt;
|
||||
use live_server::listen;
|
||||
use notify::{
|
||||
@@ -7,97 +7,72 @@ use notify::{
|
||||
};
|
||||
use std::{env, path::Path};
|
||||
|
||||
use crate::app::watcher::watcher;
|
||||
use crate::app::log::display_status;
|
||||
use crate::app::config::config::Config;
|
||||
use crate::app::build::{DockiBuildResult, DockiBuilder};
|
||||
use crate::app::{ watcher::watcher, build::{docki_build, DockiBuildResult}, commands::build::build, log::display_status};
|
||||
|
||||
pub async fn serve(config: &Config) {
|
||||
let builder = DockiBuilder::new(config);
|
||||
let mut server = Server::new(builder, config);
|
||||
server.serve().await;
|
||||
|
||||
pub async fn serve(port: Option<u16>) {
|
||||
build().await;
|
||||
tokio::join!(watch_and_build(), start_server(port));
|
||||
}
|
||||
|
||||
struct Server<'a> {
|
||||
builder: DockiBuilder<'a>,
|
||||
config: &'a Config,
|
||||
}
|
||||
|
||||
impl <'a> Server <'a> {
|
||||
fn new(builder: DockiBuilder<'a>, config: &'a Config) -> Self {
|
||||
return Self {
|
||||
builder,
|
||||
config: config
|
||||
}
|
||||
}
|
||||
|
||||
async fn serve(&mut self) {
|
||||
self.builder.prepare().await.expect("could not prepare for build");
|
||||
self.builder.build_docs().expect("build failed");
|
||||
tokio::join!(self.start_server(), self.watch_and_build());
|
||||
}
|
||||
|
||||
async fn start_server(&self) {
|
||||
let link = &format!("http://localhost:{}", self.config.port);
|
||||
let hyperlink = Green.paint(link).hyperlink(link);
|
||||
|
||||
println!(
|
||||
"\nServing at {}",
|
||||
hyperlink
|
||||
);
|
||||
|
||||
let Ok(()) = listen("localhost", self.config.port, self.config.output_dir.clone()).await else {
|
||||
panic!("could not start server")
|
||||
};
|
||||
}
|
||||
|
||||
async fn watch_and_build(&self) {
|
||||
self.watch()
|
||||
async fn watch_and_build() {
|
||||
watch(Path::new("./docs"))
|
||||
.await
|
||||
.expect("something went wrong")
|
||||
}
|
||||
|
||||
async fn watch(&self) -> notify::Result<()> {
|
||||
let path = Path::new(&self.config.input_dir);
|
||||
async fn start_server(port: Option<u16>) {
|
||||
let unwrapped_port = port.unwrap_or(8080);
|
||||
println!(
|
||||
"\nServing at {}{} ",
|
||||
"http://localhost:".bold(),
|
||||
unwrapped_port.to_string().bold()
|
||||
);
|
||||
|
||||
let Ok(()) = listen("localhost", port.unwrap_or(8080), "./dist").await else {
|
||||
panic!("could not start server")
|
||||
};
|
||||
}
|
||||
|
||||
async fn watch(path: &Path) -> notify::Result<()> {
|
||||
let (mut watcher, mut rx) = watcher()?;
|
||||
|
||||
watcher.watch(path.as_ref(), RecursiveMode::Recursive)?;
|
||||
|
||||
while let Some(res) = rx.next().await {
|
||||
let event = res.expect("watching failed");
|
||||
self.file_change(event)
|
||||
file_change(event)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
fn file_change(&self, event: Event) {
|
||||
fn file_change(event: Event) {
|
||||
match event.kind {
|
||||
EventKind::Modify(ModifyKind::Data(_)) => self.build_valid_files(event.paths),
|
||||
EventKind::Modify(ModifyKind::Data(_)) => build_file(event.paths),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_valid_files(&self, paths: Vec<std::path::PathBuf>) {
|
||||
fn build_file(paths: Vec<std::path::PathBuf>) {
|
||||
let invalid_path_message = "changed path is invalid";
|
||||
let in_path = paths
|
||||
.first()
|
||||
.expect(invalid_path_message)
|
||||
.strip_prefix(&Self::current_dir())
|
||||
.expect(invalid_path_message)
|
||||
.to_str()
|
||||
.expect(invalid_path_message);
|
||||
.expect(invalid_path_message)
|
||||
.replace(¤t_dir(), "")
|
||||
.replace("/./", "./");
|
||||
|
||||
let in_path = format!("./{}", in_path);
|
||||
let result = self.builder.build_file(&in_path);
|
||||
|
||||
let result = docki_build(&in_path);
|
||||
|
||||
match result {
|
||||
DockiBuildResult::Slide(out_path) => Self::display_rebuilding_status("Slide", &in_path, &out_path),
|
||||
DockiBuildResult::Doc(out_path) => Self::display_rebuilding_status("Doc", &in_path, &out_path),
|
||||
DockiBuildResult::Copy(out_path) => Self::display_rebuilding_status("Copy", &in_path, &out_path),
|
||||
DockiBuildResult::Slide(out_path) => display_rebuilding_status("Slide", &in_path, &out_path),
|
||||
DockiBuildResult::Doc(out_path) => display_rebuilding_status("Doc", &in_path, &out_path),
|
||||
DockiBuildResult::Copy(out_path) => display_rebuilding_status("Copy", &in_path, &out_path),
|
||||
DockiBuildResult::Err(err) => {
|
||||
Self::display_rebuilding_status("Error", &in_path, "");
|
||||
display_rebuilding_status("Error", &in_path, "");
|
||||
println!("{}", err);
|
||||
},
|
||||
}
|
||||
@@ -116,6 +91,4 @@ impl <'a> Server <'a> {
|
||||
.expect(err_message),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use nu_ansi_term::{AnsiGenericString, Style};
|
||||
|
||||
fn github_hyperlink() -> AnsiGenericString<'static, str> {
|
||||
return Style::new()
|
||||
.bold()
|
||||
.underline()
|
||||
.paint("https://github.com/quirinecker/docki")
|
||||
.hyperlink("https://github.com/quirinecker/docki");
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(after_help = format!("More information like defaults can be found at {}", github_hyperlink()))]
|
||||
pub struct Args {
|
||||
#[command(subcommand)]
|
||||
pub command: CommandArg,
|
||||
|
||||
/// The directory where the documentation is located
|
||||
#[arg(short, long, global = true)]
|
||||
pub input_dir: Option<String>,
|
||||
|
||||
/// The directory where the documentation will be built
|
||||
#[arg(short, long, global = true)]
|
||||
pub output_dir: Option<String>,
|
||||
|
||||
/// When set to true, docki will download revealjs before building the documentation.
|
||||
/// Otherwise it will use the cdn for revealjs
|
||||
#[arg(long, global = true)]
|
||||
pub offline_reveal: bool,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum ShellArg {
|
||||
Bash,
|
||||
Fish,
|
||||
Zsh,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum CommandArg {
|
||||
/// Builds the documentation into the specified output_dir
|
||||
Build,
|
||||
/// Checks if everything required for docki is installed
|
||||
Health,
|
||||
/// Deprecated: Helper command for installing asciidoctor-reveal-js
|
||||
InstallReveal,
|
||||
/// Starts a Webserver with the live preview of the Documentation
|
||||
Serve {
|
||||
/// Port for the Live Server
|
||||
#[arg(short, long)]
|
||||
port: Option<u16>,
|
||||
},
|
||||
/// Generates completions for the desired shell
|
||||
Completions {
|
||||
#[command(subcommand)]
|
||||
shell: ShellArg,
|
||||
},
|
||||
}
|
||||
|
||||
impl Args {}
|
||||
@@ -1,44 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::app::config::arguments::CommandArg;
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct Config {
|
||||
pub port: u16,
|
||||
pub input_dir: String,
|
||||
pub offline_reveal: bool,
|
||||
pub output_dir: String,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn load() -> Result<Self, config::ConfigError> {
|
||||
let s = config::Config::builder()
|
||||
.add_source(config::File::with_name("./docki.config.toml"))
|
||||
.build()?;
|
||||
s.try_deserialize()
|
||||
}
|
||||
|
||||
pub fn merge_with_args(self, args: &super::arguments::Args) -> Self {
|
||||
Self {
|
||||
port: match args.command {
|
||||
CommandArg::Serve { port } => port.unwrap_or(self.port),
|
||||
_ => self.port,
|
||||
},
|
||||
input_dir: args.input_dir.clone().unwrap_or(self.input_dir),
|
||||
output_dir: args.output_dir.clone().unwrap_or(self.output_dir),
|
||||
offline_reveal: args.offline_reveal || self.offline_reveal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
port: 8080,
|
||||
input_dir: "./docs".to_string(),
|
||||
output_dir: "./dist".to_string(),
|
||||
offline_reveal: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
use nu_ansi_term::Color::LightGreen;
|
||||
use nu_ansi_term::Color::LightRed;
|
||||
use nu_ansi_term::Style;
|
||||
use colored::Colorize;
|
||||
|
||||
pub fn display_status(context1: &str, context2: &str, in_path: &str, out_path: &str) {
|
||||
let colored_context = if context2 == "Error" {
|
||||
LightRed.paint(context2)
|
||||
} else {
|
||||
LightGreen.paint(context2)
|
||||
};
|
||||
|
||||
let colored_context = color_context(context2);
|
||||
println!(
|
||||
"({}) [{}] {} -> {}",
|
||||
Style::new().paint(context1),
|
||||
context1.bold(),
|
||||
colored_context,
|
||||
in_path,
|
||||
out_path
|
||||
);
|
||||
}
|
||||
|
||||
fn color_context(context: &str) -> colored::ColoredString {
|
||||
if context == "Error" {
|
||||
return context.bright_red()
|
||||
} else {
|
||||
return context.bright_green()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,11 @@ pub mod build;
|
||||
pub mod fs_util;
|
||||
pub mod watcher;
|
||||
pub mod log;
|
||||
pub mod config;
|
||||
mod args;
|
||||
|
||||
use std::env;
|
||||
|
||||
use crate::app::config::config::Config;
|
||||
|
||||
use self::config::{args, arguments::CommandArg};
|
||||
use self::args::{args, structure::CommandArg};
|
||||
use self::commands::build::build;
|
||||
use self::commands::completions::completions;
|
||||
use self::commands::health::health;
|
||||
@@ -22,14 +20,13 @@ impl App {
|
||||
|
||||
pub async fn start(&self) {
|
||||
let args = args();
|
||||
let config = Config::load().unwrap_or(Config::default()).merge_with_args(&args);
|
||||
Self::setup_environment_variables();
|
||||
|
||||
match args.command {
|
||||
CommandArg::Build { .. } => build(&config).await,
|
||||
CommandArg::Build => build().await,
|
||||
CommandArg::Health => health(),
|
||||
CommandArg::InstallReveal => install_reveal().await,
|
||||
CommandArg::Serve { .. } => serve(&config).await,
|
||||
CommandArg::Serve { port } => serve(port).await,
|
||||
CommandArg::Completions { shell } => completions(shell)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ fn test_fetch_asciidoctor_paths_recursive() {
|
||||
let paths = fs_util::fetch_paths_recursive("res/test/docs").unwrap();
|
||||
let len = paths.len();
|
||||
dbg!(paths);
|
||||
assert_eq!(len, 2);
|
||||
assert_eq!(len, 5);
|
||||
}
|
||||
|
||||
34
src/util.rs
34
src/util.rs
@@ -1,34 +0,0 @@
|
||||
mod app;
|
||||
|
||||
use std::{fs::File, io::Write};
|
||||
|
||||
use app::config::config::Config;
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser)]
|
||||
pub struct Args {
|
||||
#[command(subcommand)]
|
||||
pub command: CommandArg,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum CommandArg {
|
||||
/// Generates a default docki.config.toml
|
||||
GenerateDefaultConfig,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
match args.command {
|
||||
CommandArg::GenerateDefaultConfig => generate_default_config(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_default_config() {
|
||||
let default_config = Config::default();
|
||||
let target_file = "config/docki.config.toml";
|
||||
let mut file = File::create(target_file).unwrap();
|
||||
let output = toml::to_string_pretty(&default_config).unwrap();
|
||||
|
||||
file.write_all(output.as_bytes()).unwrap();
|
||||
}
|
||||
Reference in New Issue
Block a user