Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Available via the [`json-sort` package][json-sort package], the binary is called

### Via the source code

Clone the repository and run in the sourcecode folder:
Clone the repository and run in the source code folder:

```sh
cargo build --release
Expand Down Expand Up @@ -72,7 +72,7 @@ just serve
Open <http://localhost:8080> and use the page to sort JSON object keys locally
in the browser.

Try the online demo on Github pages, find the link in the badge on top of this
Try the online demo on GitHub Pages; the link is available in the badge at the top of this
file.

### Via Nix
Expand All @@ -83,6 +83,33 @@ You can use the package from this repository with Nix. If you have Nix installed
nix run github:drupol/json-sort
```

### Treefmt module

This repository also exposes a reusable `treefmtModule` as `treefmtModules.default`, so you can add the
`json-sort` formatter to any `treefmt` configuration without duplicating the setup.

```nix
treefmt = {
imports = [
inputs.json-sort.treefmtModules.default
];
projectRootFile = "flake.nix";
programs = {
json-sort.enable = true;
};
};
```

Make sure to add the `json-sort` flake input:

```nix
inputs = {
# ... 8< ...
json-sort.url = "github:drupol/json-sort";
# ... >8 ...
};
```

## Usage

### Command Line
Expand Down
8 changes: 7 additions & 1 deletion nix/modules/fmt.nix
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
{ inputs, ... }:
{
imports = [ inputs.treefmt-nix.flakeModule ];
imports = [
inputs.treefmt-nix.flakeModule
];

perSystem = {
treefmt = {
imports = [
inputs.self.treefmtModules.default
];
projectRootFile = "flake.nix";
programs = {
jsonfmt.enable = true;
json-sort.enable = true;
nixfmt.enable = true;
prettier.enable = true;
statix.enable = true;
Expand Down
74 changes: 74 additions & 0 deletions nix/modules/treefmt-module.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
inputs,
...
}:
let
treefmtModule =
{
lib,
config,
pkgs,
...
}:
let
cfg = config.programs.json-sort;
in
{
config = lib.mkIf cfg.enable {
settings.formatter.json-sort = {
inherit (cfg) includes;
command = lib.getExe cfg.package;
options = [ "--fix" ];
}
// lib.optionalAttrs (cfg.excludes != [ ]) { inherit (cfg) excludes; }
// lib.optionalAttrs (cfg.priority != null) { inherit (cfg) priority; };
};
options.programs.json-sort = {
enable = lib.mkEnableOption "json-sort, the JSON formatter";
package = lib.mkOption {
default = pkgs.json-sort;
defaultText = lib.literalExpression "pedantix.packages.\${system}.pedantix-wrapped";
description = "The pedantix package to run. The default wrapper ships nixfmt, alejandra and nixpkgs-fmt on PATH; use the unwrapped `pedantix` package if you provide the base formatter yourself.";
type = lib.types.package;
};
excludes = lib.mkOption {
default = [ ];
description = "Path / file patterns to exclude.";
example = [ "generated/*.json" ];
type = lib.types.listOf lib.types.str;
};
includes = lib.mkOption {
default = [ "*.json" ];
description = "Path / file patterns to include.";
type = lib.types.listOf lib.types.str;
};
priority = lib.mkOption {
default = null;
description = "treefmt priority, for ordering relative to other formatters on the same files.";
type = lib.types.nullOr lib.types.int;
};
};
};
in
{
imports = [
inputs.flake-parts.flakeModules.flakeModules
];

flake = {
flakeModules = {
default =
{ flake-parts-lib, ... }:
{
options.perSystem = flake-parts-lib.mkPerSystemOption {
config.treefmt = {
imports = [ treefmtModule ];
};
};
};
};
treefmtModules = {
default = treefmtModule;
};
};
}
50 changes: 40 additions & 10 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ <h1 class="display-3 fw-bold mb-0">json-sort</h1>
<span id="version" class="badge text-bg-secondary">v...</span>
</div>
<p class="lead text-body-secondary mb-0">
Sort JSON object keys in the browser with the Rust library compiled to WebAssembly.
Sort JSON object keys in the browser with the Rust library compiled
to WebAssembly.
</p>
</div>
<div class="d-flex flex-wrap gap-2">
Expand Down Expand Up @@ -59,7 +60,11 @@ <h1 class="display-3 fw-bold mb-0">json-sort</h1>
/>
</div>
<div class="col-6">
<button id="random" class="btn btn-outline-primary btn-lg w-100" type="button">
<button
id="random"
class="btn btn-outline-primary btn-lg w-100"
type="button"
>
Generate a random JSON
</button>
</div>
Expand All @@ -75,16 +80,30 @@ <h1 class="display-3 fw-bold mb-0">json-sort</h1>
readonly
></textarea>
<div class="row g-2 mt-3">
<button id="sort" class="btn btn-primary btn-lg w-100" type="button">Sort JSON</button>
<button
id="sort"
class="btn btn-primary btn-lg w-100"
type="button"
>
Sort JSON
</button>
</div>
</div>
</section>

<div id="status" class="alert mt-3 mb-0" role="status" aria-live="polite"></div>
<div
id="status"
class="alert mt-3 mb-0"
role="status"
aria-live="polite"
></div>
</main>

<script type="module">
import init, { json_sort_version, sort_json_string } from "./pkg/json_sort.js";
import init, {
json_sort_version,
sort_json_string,
} from "./pkg/json_sort.js";

const input = document.querySelector("#input");
const output = document.querySelector("#output");
Expand All @@ -109,7 +128,9 @@ <h1 class="display-3 fw-bold mb-0">json-sort</h1>
output.value = sort_json_string(input.value);
setStatusOk("Sorted successfully.");
} catch (error) {
setStatusError(error instanceof Error ? error.message : String(error));
setStatusError(
error instanceof Error ? error.message : String(error),
);
}
}

Expand All @@ -123,7 +144,9 @@ <h1 class="display-3 fw-bold mb-0">json-sort</h1>

function randomKey() {
const alphabet = "abcdefghijklmnopqrstuvwxyz";
return Array.from({ length: randomInteger(3, 12) }, () => randomItem(alphabet)).join("");
return Array.from({ length: randomInteger(3, 12) }, () =>
randomItem(alphabet),
).join("");
}

function randomString() {
Expand Down Expand Up @@ -158,11 +181,16 @@ <h1 class="display-3 fw-bold mb-0">json-sort</h1>
];

const nestedValues = [
() => Array.from({ length: randomInteger(2, 5) }, () => randomValue(depth + 1)),
() =>
Array.from({ length: randomInteger(2, 5) }, () =>
randomValue(depth + 1),
),
() => randomObject(depth + 1),
];

return randomItem(depth > 2 ? scalarValues : scalarValues.concat(nestedValues))();
return randomItem(
depth > 2 ? scalarValues : scalarValues.concat(nestedValues),
)();
}

function randomObject(depth = 0) {
Expand Down Expand Up @@ -210,7 +238,9 @@ <h1 class="display-3 fw-bold mb-0">json-sort</h1>
sortInput();
setStatusOk(`Loaded and sorted ${selectedFile.name}.`);
} catch (error) {
setStatusError(error instanceof Error ? error.message : String(error));
setStatusError(
error instanceof Error ? error.message : String(error),
);
}
}

Expand Down