From abd68c5ffb8d0b0fe22ec71139a9843ef7737752 Mon Sep 17 00:00:00 2001 From: Ti-03 Date: Mon, 13 Jul 2026 13:01:05 +0300 Subject: [PATCH] docs: add Vale prose linting (Microsoft style) + CI gate Add .vale.ini using the Microsoft Writing Style Guide and a prose-lint job in the existing CI workflow so docs style violations fail the build. Fix all flagged issues across the guide, ADR, and README (contractions, quote punctuation, spaced em dashes, adverbs). Styles are synced by CI, not committed. --- .github/workflows/ci.yml | 24 ++++++++++++ .gitignore | 3 ++ .vale.ini | 19 ++++++++++ README.md | 38 +++++++++---------- ...001-compile-time-guard-for-liquid-glass.md | 8 ++-- guide/how-to/read-the-treemap.md | 6 +-- guide/index.md | 4 +- guide/reference/treemap-layout.md | 6 +-- guide/tutorial/first-scan.md | 2 +- 9 files changed, 78 insertions(+), 32 deletions(-) create mode 100644 .vale.ini diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e550a95..1aed936 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,3 +38,27 @@ jobs: - name: Test run: swift test + + # Prose gate: Vale lints the docs against the Microsoft style guide. A style + # violation fails the build, so it never reaches a reviewer. Runs on Linux + # (no Xcode needed) so it starts fast and in parallel with the build matrix. + prose-lint: + name: Docs prose (Vale) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Vale + run: | + VALE_VERSION=3.15.1 + curl -sfL "https://github.com/errata-ai/vale/releases/download/v${VALE_VERSION}/vale_${VALE_VERSION}_Linux_64-bit.tar.gz" -o vale.tar.gz + tar -xzf vale.tar.gz vale + sudo install vale /usr/local/bin/vale + rm -f vale vale.tar.gz + + # Downloads the Microsoft style package declared in .vale.ini. + - name: Sync Vale styles + run: vale sync + + - name: Lint docs prose + run: vale guide docs/adr README.md diff --git a/.gitignore b/.gitignore index 45f6a39..2bd582b 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,9 @@ DerivedData/ # MkDocs build output (built by CI, not committed) /site/ +# Vale prose-lint styles are downloaded by `vale sync` (locally and in CI) +.github/styles/ + # Amore / Sparkle private signing keys — NEVER commit these *.private sparkle_private_key diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000..0228d07 --- /dev/null +++ b/.vale.ini @@ -0,0 +1,19 @@ +# Vale configuration for MacDirStat docs. +# Prose is linted with the Microsoft Writing Style Guide, the same voice the +# guide and ADR were already written in (active voice, present tense, "you"). +StylesPath = .github/styles + +# CI fails on errors (clear-cut style violations). Warnings and suggestions +# still print locally for review but don't block the build. +MinAlertLevel = error + +# Vale downloads the Microsoft package into StylesPath (see the CI workflow and +# the `vale sync` step in the docs). +Packages = Microsoft + +[*.md] +BasedOnStyles = Vale, Microsoft + +# Reference pages quote real API symbols (ByteFormatter, TreemapLayout) and code +# identifiers; don't flag those as spelling errors. +Vale.Spelling = NO diff --git a/README.md b/README.md index 6b4aa8b..98fa50c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

MacDirStat

See where your disk space went.
-A fast, beautiful macOS disk usage visualizer — built entirely in Swift.

+A fast, beautiful macOS disk usage visualizer, built entirely in Swift.

[![CI](https://github.com/Ti-03/MacDirStat/actions/workflows/ci.yml/badge.svg)](https://github.com/Ti-03/MacDirStat/actions/workflows/ci.yml) [![App Store](https://img.shields.io/badge/Mac_App_Store-Download-0D96F6?style=flat-square&logo=apple)](https://apps.apple.com/app/dirstat/id6766033292?mt=12) @@ -23,21 +23,21 @@ A fast, beautiful macOS disk usage visualizer — built entirely in Swift.

## What it does -MacDirStat scans any folder and turns your filesystem into an interactive sunburst chart — every ring is a depth level, every arc is a file or folder, sized by disk usage. Hover to inspect. Click to drill in. Right-click to delete. +MacDirStat scans any folder and turns your filesystem into an interactive sunburst chart: every ring is a depth level, every arc is a file or folder, sized by disk usage. Hover to inspect. Click to drill in. Right-click to delete. ## Features -- **Sunburst visualization** — depth rings, color-coded by file type (video, code, images, archives…) -- **Spotlight hover** — everything else fades when you hover; selected files pulse with a glow -- **Force Touch haptics** — soft tap for small files, triple thud for multi-GB ones -- **Drill navigation** — click any folder to zoom in, click back to go up -- **Duplicate detection** — finds identical files by content hash, shows wasted space per group -- **One-click cleanup** — keep one copy, trash the rest — or delete file by file -- **File list panel** — sortable tree view beside the chart, toggle to give the chart full width -- **File type breakdown** — top file types with a searchable list of all types -- **Move to Trash** — right-click any arc or row to trash it, chart refreshes instantly -- **CSV export** — dump the full scan as a spreadsheet -- **Settings** — toggle haptic feedback on/off +- **Sunburst visualization**: depth rings, color-coded by file type (video, code, images, archives…) +- **Spotlight hover**: everything else fades when you hover; selected files pulse with a glow +- **Force Touch haptics**: soft tap for small files, triple thud for multi-GB ones +- **Drill navigation**: click any folder to zoom in, click back to go up +- **Duplicate detection**: finds identical files by content hash, shows wasted space per group +- **One-click cleanup**: keep one copy, trash the rest, or delete file by file +- **File list panel**: sortable tree view beside the chart, toggle to give the chart full width +- **File type breakdown**: top file types with a searchable list of all types +- **Move to Trash**: right-click any arc or row to trash it, chart refreshes instantly +- **CSV export**: dump the full scan as a spreadsheet +- **Settings**: toggle haptic feedback on/off ## Screenshots @@ -47,9 +47,9 @@ MacDirStat scans any folder and turns your filesystem into an interactive sunbur ## Install -**[Download on the Mac App Store](https://apps.apple.com/app/dirstat/id6766033292?mt=12)** — published as **DirStat**. +**[Download on the Mac App Store](https://apps.apple.com/app/dirstat/id6766033292?mt=12)**, published as **DirStat**. -Or grab the DMG directly from **[Releases](https://github.com/Ti-03/MacDirStat/releases)** — open it and drag the app to your Applications folder. It updates itself automatically via the Help menu once installed. +Or grab the DMG directly from **[Releases](https://github.com/Ti-03/MacDirStat/releases)**. Open it and drag the app to your Applications folder. It updates itself automatically via the Help menu once installed. **Build from source** @@ -63,14 +63,14 @@ Requires macOS 14+ and Xcode 15+. ## Tech -Pure Swift + SwiftUI — no Electron, no web views, no dependencies. +Pure Swift + SwiftUI: no Electron, no web views, no dependencies. | Layer | What | |---|---| -| Scanner | POSIX `opendir`/`fstatat` with async task groups — parallel, cancellable | +| Scanner | POSIX `opendir`/`fstatat` with async task groups: parallel, cancellable | | Layout | Custom sunburst partition algorithm (band-width from view size) | -| Renderer | SwiftUI `Canvas` — draws 1,000+ arcs at 30 fps | -| Haptics | `NSHapticFeedbackManager` — intensity scales with file size | +| Renderer | SwiftUI `Canvas`: draws 1,000+ arcs at 30 fps | +| Haptics | `NSHapticFeedbackManager`: intensity scales with file size | | Duplicates | SHA-256 content hashing on a background actor | ## Documentation diff --git a/docs/adr/0001-compile-time-guard-for-liquid-glass.md b/docs/adr/0001-compile-time-guard-for-liquid-glass.md index 823a89a..4ef6676 100644 --- a/docs/adr/0001-compile-time-guard-for-liquid-glass.md +++ b/docs/adr/0001-compile-time-guard-for-liquid-glass.md @@ -60,8 +60,8 @@ alone type-checked. The runtime `#available` check stays inside the compile-time branch, so a build made with Xcode 26 still back-deploys correctly to macOS 14/15 at runtime. -We also dropped `macos-14` from the CI matrix: its SDK predates both -`glassEffect` and the `ContentUnavailableView` backport check, so it cannot +I also dropped `macos-14` from the CI matrix: its SDK predates both +`glassEffect` and the `ContentUnavailableView` backport check, so it can't build this project at all regardless of guards, and keeping it would only produce a permanently red, unfixable job. @@ -72,9 +72,9 @@ produce a permanently red, unfixable job. `#available` alone. A future contributor who copies an existing `#available`-only pattern from elsewhere in SwiftUI code will reintroduce this bug; there is no compiler warning for it. -- The CI matrix (`macos-15`, `macos-26`) is now load-bearing: it is the +- The CI matrix (`macos-15`, `macos-26`) is now load-bearing: it's the only thing that would have caught this before it shipped, since a - single-SDK local build cannot reproduce the failure. + single-SDK local build can't reproduce the failure. - Slightly more boilerplate per call site (two nested conditionals instead of one), in exchange for the app actually compiling on the SDK most users' Macs currently have. diff --git a/guide/how-to/read-the-treemap.md b/guide/how-to/read-the-treemap.md index 6ae0ff1..3af5e47 100644 --- a/guide/how-to/read-the-treemap.md +++ b/guide/how-to/read-the-treemap.md @@ -31,9 +31,9 @@ extension: | Pink | Fonts | `ttf`, `otf`, `woff` | | Lime | 3D / models | `obj`, `fbx`, `gltf` | -An extension MacDirStat does not recognize gets a stable color derived from +An extension MacDirStat doesn't recognize gets a stable color derived from its name, so the same unknown extension is always the same color across a -scan. Folders are colored separately from files: each folder gets a muted, +scan. Folders and files use different color schemes: each folder gets a muted, low-saturation tint based on its name, so folders never compete visually with the files inside them. Files also darken slightly with depth, so you can tell a top-level file from one buried five folders down at a glance. @@ -55,7 +55,7 @@ can tell a top-level file from one buried five folders down at a glance. ## See also -- [Scan your first folder](../tutorial/first-scan.md) if you have not run a +- [Scan your first folder](../tutorial/first-scan.md) if you haven't run a scan yet. - [TreemapLayout reference](../reference/treemap-layout.md) for exactly how angles and colors are computed. diff --git a/guide/index.md b/guide/index.md index d384af5..91a1b41 100644 --- a/guide/index.md +++ b/guide/index.md @@ -1,11 +1,11 @@ # MacDirStat -MacDirStat is a native macOS app that scans a folder and shows what is taking up +MacDirStat is a native macOS app that scans a folder and shows what's taking up disk space, as an interactive radial treemap. This guide is for **macOS users who have MacDirStat installed** (or built it from source) and want to scan a folder, read the resulting chart, or look up -what a specific API does. You do not need any Swift experience to follow the +what a specific API does. You don't need any Swift experience to follow the tutorial or how-to guide; the reference section assumes you are reading the Swift source. diff --git a/guide/reference/treemap-layout.md b/guide/reference/treemap-layout.md index e3c633f..3aef8e1 100644 --- a/guide/reference/treemap-layout.md +++ b/guide/reference/treemap-layout.md @@ -40,7 +40,7 @@ let arcAngle = fraction * totalAngle An arc smaller than `minArcAngle` (about 1 degree) is skipped entirely rather than drawn as an unreadable sliver. Folders recurse into their own -children at the next radius band; files do not. +children at the next radius band; files don't. ## `TreemapCell` @@ -61,9 +61,9 @@ One cell per arc. `startAngle`/`endAngle` are in radians; `innerRadius`/ ## Color assignment -Colors are not assigned by `TreemapLayout` directly; it delegates to +Colors aren't assigned by `TreemapLayout` directly; it delegates to `ExtensionColorMap.color(for:)` for files and computes a muted per-folder tint by hashing the folder's name for directories. Files also darken by a fixed amount per depth (from 0% at depth 0 up to 38% at depth 5+), so a `.mp4` five folders deep is visibly darker than one at the top level, even -though both are "orange". +though both are "orange." diff --git a/guide/tutorial/first-scan.md b/guide/tutorial/first-scan.md index 2b342f4..e28d020 100644 --- a/guide/tutorial/first-scan.md +++ b/guide/tutorial/first-scan.md @@ -34,6 +34,6 @@ proportional to how much disk space it uses. ## Next step -The colors are not random. Continue to +The colors aren't random. Continue to [How to read the treemap](../how-to/read-the-treemap.md) to learn what each color means and how to change the color scheme.