Skip to content

Move all images referred to by a markdown file to a folder

License

Notifications You must be signed in to change notification settings

wonderbird/malimo

Repository files navigation

malimo - Markdown Linked Images Mover

Gitpod ready-to-code Build Status Badge Test Coverage Code Maintainability Issues in Code Technical Debt

Move all images used by a markdown file into a folder.

Motivation

During online conferences and workshops I take notes in markdown format using Obsidian.md. As a result I have a folder with many screenshots from different talks in the evening.

The Markdown Linked Images Mover "malimo" moves all images addressed by a markdown file into a separate folder.

This way I can separate screenshots by topic at the end of a conference or workshop day.

Development and Support Status

I am developing during my spare time and use this project for learning purposes. Please assume that I will need some days to answer your questions. At some point I might lose interest in the project. Please keep this in mind when using this project in a production environment.

Acknowledgements

The application icon is the folder-document.png from the "Tango harm-on-icons" icon set, which is published in the Open Icon Library using the CC-BY 3.0 license. Thanks to the author(s) for their work ❤️.

Many thanks to JetBrains who provide an Open Source License for this project ❤️.

Installation

macOS

For macOS I am maintaining a Homebrew installer:

brew install wonderbird/tools/malimo

This creates a symlink named malimo in your $(brew --prefix)/bin directory.

The corresponding Homebrew cask is at wonderbird / homebrew-tools / Casks / malimo.rb.

Windows

Use the Chocolatey Package Manager

For Windows, the release process publishes a wrapper package to the Chocolatey Community Repository. The package will download and install the release ZIP file from the malimo GitHub release page.

You can install malimo by:

choco install malimo --pre

At the moment I consider the software a prerelease. This is why the --pre argument is required.

Manual Installation

If you do not manage your Windows software using Chocolatey, then

  • download malimo.win-x64.zip from the latest GitHub release,
  • extract the files into a folder
  • add the folder to your PATH environment variable.

Verification

After successful installation you can run the program and get help by entering

malimo --help

and you can check the version

malimo --version

The displayed version number contains 4 numbers separated by a ".", e.g. 0.1.7.178. The first three numbers reflect the semantic version of the release, here 0.1.7. The last number is the GitHub workflow run number, during which the package was created, in the example case it was run #178.

Usage Examples

The most basic usage is

malimo --file ./my-markdown-file.md --target-dir ./target

malimo will list the images linked in ./my-markdown-file.md. It will ensure that every image exists in the same directory ./. Then it will move all linked images to the directory ./target.

If you want to double check what would be moved before actually moving the files, then add the --dry-run option. This way, no file will be moved.

malimo --dry-run --file ./my-markdown-file.md --target-dir ./will-be-ignored

To get help, specify the --help option:

malimo --help

You can find elaborate usage examples in the FeatureDocumentation HTML file attached to each release starting from 0.1.8-alpha.

Development

Architecture Overview

docs/architecture.adoc gives an overview of the architecture. Section 8 Concepts explains maintenance tasks.

Quick-Start

Click the Gitpod ready-to-code badge (also above) to launch a web IDE.

If that does not work for you or if you'd like to have the project on your local machine, then continue reading.

Prerequisites

To compile, test and run this project the latest .NET SDK is required on your machine. For calculating code metrics I recommend metrix++. This requires python.

If you are interested in test coverage, then you'll need the following tools installed:

dotnet tool install --global coverlet.console --configfile NuGet-OfficialOnly.config
dotnet tool install --global dotnet-reportgenerator-globaltool --configfile NuGet-OfficialOnly.config

Build, Test, Run

Run the following commands from the folder containing the .sln file in order to build and test.

Build and Test the Solution

# Build the project
dotnet build

# Run the tests once
dotnet test
# Continuously watch the tests while changing code
dotnet watch -p ./malimo.Tests test
# Produce a coverage report and open it in the default browser
rm -r malimo.Tests/TestResults && \
  dotnet test --no-restore --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput='./TestResults/coverage.cobertura.xml' && \
  reportgenerator "-reports:malimo.Tests/TestResults/*.xml" "-targetdir:report" "-reporttypes:Html;lcov" "-title:DotnetStarter"
open report/index.html

Run the Application

# Get help
dotnet run --project malimo/malimo.csproj -- --help
# Prepare test data to run the application
cp -Rv malimo.Tests/data/seed malimo.Tests/data/source
mkdir malimo.Tests/data/target
# Run the application
dotnet run --project malimo/malimo.csproj -- --dry-run --file malimo.Tests/data/source/Testfile.md --target-dir malimo.Tests/data/target
# Inspect the result
ls -la malimo.Tests/data/source
ls -la malimo.Tests/data/target
# Cleanup test data
rm -r malimo.Tests/data/source malimo.Tests/data/target

Before Creating a Pull Request ...

Fix Static Code Analysis Warnings

... fix static code analysis warnings reported by SonarLint and by CodeClimate.

Apply Code Formatting Rules

# Install https://csharpier.io globally, once
dotnet tool install -g csharpier

# Format code
dotnet csharpier .

Check Code Metrics

... check code metrics using metrix++

  • Configure the location of the cloned metrix++ scripts

    export METRIXPP=/path/to/metrixplusplus
  • Collect metrics

    python "$METRIXPP/metrix++.py" collect --std.code.complexity.cyclomatic --std.code.lines.code --std.code.todo.comments --std.code.maintindex.simple -- .
  • Get an overview

    python "$METRIXPP/metrix++.py" view --db-file=./metrixpp.db
  • Apply thresholds

    python "$METRIXPP/metrix++.py" limit --db-file=./metrixpp.db --max-limit=std.code.complexity:cyclomatic:5 --max-limit=std.code.lines:code:25:function --max-limit=std.code.todo:comments:0 --max-limit=std.code.mi:simple:1

At the time of writing, I want to stay below the following thresholds:

--max-limit=std.code.complexity:cyclomatic:5
--max-limit=std.code.lines:code:25:function
--max-limit=std.code.todo:comments:0
--max-limit=std.code.mi:simple:1

Finally, remove all code duplication. The next section describes how to detect code duplication.

Remove Code Duplication Where Appropriate

To detect duplicates I use the CPD Copy Paste Detector tool from the PMD Source Code Analyzer Project.

If you have installed PMD by download & unzip, replace pmd by ./run.sh. The homebrew pmd formula makes the pmd command globally available.

# Remove temporary and generated files
# 1. dry run
git clean -ndx
# 2. Remove the files shown by the dry run
git clean -fdx
# Identify duplicated code in files to push to GitHub
pmd cpd --minimum-tokens 50 --language cs --dir .