Skip to content

Commit

Permalink
docs: adding support for new tools (#650)
Browse files Browse the repository at this point in the history
* docs: how to add new tools

* chore: automatically update CONTRIBUTING.md toc
  • Loading branch information
hougesen authored Jan 28, 2025
1 parent 3c90f1c commit 093e930
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 33 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [Unreleased](https://github.com/hougesen/mdsf/compare/v0.4.1...HEAD)

- docs: adding support for new tools [`#650`](https://github.com/hougesen/mdsf/pull/650)
- refactor(cli): abstract command execution to utility functions [`#647`](https://github.com/hougesen/mdsf/pull/647)
- feat(cli): tool timeout argument [`#646`](https://github.com/hougesen/mdsf/pull/646)
- build(deps-dev): bump eslint from 9.18.0 to 9.19.0 in /mdsf-vscode [`#642`](https://github.com/hougesen/mdsf/pull/642)
- build(deps-dev): bump @eslint/js from 9.18.0 to 9.19.0 in /mdsf-vscode [`#644`](https://github.com/hougesen/mdsf/pull/644)
Expand Down
78 changes: 78 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Contributing to mdsf

Thank you for considering contributing to mdsf. It is greatly appreciated! ❤️

## Table of contents

<!-- START_SECTION:toc -->

- [Contributing to mdsf](#contributing-to-mdsf)
- [Table of contents](#table-of-contents)
- [Adding support for a new tool](#adding-support-for-a-new-tool)
- [Tool metadata](#tool-metadata)

<!-- END_SECTION:toc -->

## Adding support for a new tool

Adding support for new tools is extremely easy, and does not require any knowledge of Rust programming.

To add support for a new tool start by creating a folder in [`tools`](tools/) with the name of the tool.

Inside the folder you create a new file called `plugin.json`.

The file must include _at least_ 2 keys, `binary`, which, as the key suggest, is the name of the binary, and `commands`, which is a nested map of all the commands for the tool.

If we wanted to add support for mdsf (`mdsf format PATH_TO_FILE`) that would look like the following:

```json
// tools/mdsf/plugin.json
{
"$schema": "../tool.schema.json",

"binary": "mdsf",
"commands": {
"format": {
"arguments": ["format", "$PATH"]
}
}
}
```

As seen in the example above we used the argument `$PATH`. That is a special keyword that is automatically replaced with the actual path to the file.

If you wish to test the tool locally you can generate the code for the new tool by running `just codegen`. Otherwise the code will automatically be generated when the `plugin.json` files is committed.

### Tool metadata

`plugin.json` also supports some metadata keys that are used when generating the documentation for the tool.

The metadata fields does **not** affect mdsf when it is ran.

The current metadata keys are:

| Key | Datatype | Description |
| ------------- | ---------- | ---------------------------------------------------------- |
| `description` | `string` | Description of what the tool does. |
| `homepage` | `string` | Link to the repository/homepage/documentation of the tool. |
| `categories` | `string[]` | The purpose of the tool (`formatter` or `linter`). |
| `languages` | `string[]` | The languages/file types the tool supports. |

```json
// tools/mdsf/plugin.json
{
"$schema": "../tool.schema.json",

"binary": "mdsf",
"commands": {
"format": {
"arguments": ["format", "$PATH"]
}
},

"description": "mdsf is a markdown codeblock formatter and linter",
"homepage": "https://github.com/hougesen/mdsf",
"languages": ["markdown"],
"categories": ["linter", "formatter"]
}
```
17 changes: 17 additions & 0 deletions codegen/src/contributing/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::markdown::{table_of_contents, update_markdown_section};

pub fn generate() -> anyhow::Result<()> {
let path = std::path::PathBuf::from("./CONTRIBUTING.md");

let mut contents = std::fs::read_to_string(&path)?;

{
let t = table_of_contents::generate(&path)?;

contents = update_markdown_section(&contents, "toc", &t)?;

std::fs::write(&path, contents)?;
};

Ok(())
}
4 changes: 4 additions & 0 deletions codegen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use tools::Tool;

mod actions;
mod cargo;
mod contributing;
mod language_to_filetype;
pub mod markdown;
mod readme;
mod schema;
mod tools;
Expand Down Expand Up @@ -45,5 +47,7 @@ fn main() -> Result<()> {

actions::generate(&plugins)?;

contributing::generate()?;

Ok(())
}
22 changes: 22 additions & 0 deletions codegen/src/markdown/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pub mod table_of_contents;

pub fn update_markdown_section(
readme: &str,
key: &str,
value: &str,
) -> Result<String, regex::Error> {
let start = format!("<!-- START_SECTION:{key} -->");
let end = format!("<!-- END_SECTION:{key} -->");

let re = regex::RegexBuilder::new(format!(r"({start})[^{{}}]*?{end}").as_str())
.multi_line(true)
.build()?;

let first_value = format!("{start}{end}");

let updated = re.replace(readme, &first_value);

let update = format!("{start}\n\n{value}\n\n{end}");

Ok(updated.replace(&first_value, &update))
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pub fn generate() -> anyhow::Result<String> {
pub fn generate(path: &std::path::Path) -> anyhow::Result<String> {
let output = std::process::Command::new("npx")
.arg("--yes")
.arg("markdown-toc")
.arg("README.md")
.arg(path)
.output()?;

let toc = String::from_utf8(output.stdout)?;
Expand Down
5 changes: 3 additions & 2 deletions codegen/src/readme/command_help.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::readme::update_readme;
use crate::readme::update_markdown_section;

fn execute_command(name: &str) -> std::io::Result<std::process::Output> {
std::process::Command::new("cargo").arg("build").output()?;
Expand All @@ -25,7 +25,8 @@ pub fn generate(mut readme: String) -> anyhow::Result<String> {

let help = String::from_utf8(execute_command(command)?.stdout)?;

readme = update_readme(&readme, section_name, &format!("```\n{}\n```", help.trim()))?;
readme =
update_markdown_section(&readme, section_name, &format!("```\n{}\n```", help.trim()))?;
}

anyhow::Ok(readme)
Expand Down
43 changes: 14 additions & 29 deletions codegen/src/readme/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use regex::RegexBuilder;

use crate::tools::{GeneratedCommand, Tool};
use crate::{
markdown::{table_of_contents, update_markdown_section},
tools::{GeneratedCommand, Tool},
};

mod command_help;
mod command_table;
mod table_of_contents;
mod tool_table;

pub fn pad_right(mut input: String, len: usize, update: char) -> String {
Expand All @@ -15,51 +15,36 @@ pub fn pad_right(mut input: String, len: usize, update: char) -> String {
input
}

pub fn update_readme(readme: &str, key: &str, value: &str) -> Result<String, regex::Error> {
let start = format!("<!-- START_SECTION:{key} -->");
let end = format!("<!-- END_SECTION:{key} -->");

let re = RegexBuilder::new(format!(r"({start})[^{{}}]*?{end}").as_str())
.multi_line(true)
.build()?;

let first_value = format!("{start}{end}");

let updated = re.replace(readme, &first_value);

let update = format!("{start}\n\n{value}\n\n{end}");

Ok(updated.replace(&first_value, &update))
}

pub fn generate(plugins: &[Tool], commands: Vec<GeneratedCommand>) -> anyhow::Result<()> {
let mut readme = std::fs::read_to_string("./README.md")?;
let path = std::path::PathBuf::from("./README.md");

let mut contents = std::fs::read_to_string(&path)?;

{
let content = command_table::generate_command_table(commands);

readme = update_readme(&readme, "supported-commands", &content)?;
contents = update_markdown_section(&contents, "supported-commands", &content)?;
};

{
readme = command_help::generate(readme)?;
contents = command_help::generate(contents)?;
}

{
let tool_table = tool_table::generate(plugins);

readme = update_readme(&readme, "supported-tools", &tool_table)?;
contents = update_markdown_section(&contents, "supported-tools", &tool_table)?;
}

std::fs::write("./README.md", &readme)?;
std::fs::write(&path, &contents)?;

{
let t = table_of_contents::generate()?;
let t = table_of_contents::generate(&path)?;

readme = update_readme(&readme, "toc", &t)?;
contents = update_markdown_section(&contents, "toc", &t)?;
}

std::fs::write("./README.md", readme)?;
std::fs::write(path, contents)?;

Ok(())
}

0 comments on commit 093e930

Please sign in to comment.