lol
1/**
2 # Example
3
4 Prettier with plugins and Vim Home Manager configuration
5
6 ```nix
7 pkgs.prettier.override {
8 plugins = with pkgs.nodePackages; [
9 prettier-plugin-toml
10 # ...
11 ];
12 }
13 ```
14*/
15{
16 fetchFromGitHub,
17 lib,
18 makeBinaryWrapper,
19 nodejs,
20 stdenv,
21 versionCheckHook,
22 yarn-berry,
23 plugins ? [ ],
24}:
25let
26 /**
27 # Example
28
29 ```nix
30 exportRelativePathOf (builtins.fromJSON "./package.json")
31 =>
32 lib/node_modules/prettier-plugin-toml/./lib/index.cjs
33 ```
34
35 # Type
36
37 ```
38 exportRelativePathOf :: AttrSet => String
39 ```
40
41 # Arguments
42
43 packageJsonAttrs
44 : Attribute set with shape similar to `package.json` file
45 */
46 ## Blame NodeJS
47 exportRelativePathOf =
48 let
49 nodeExportAttrAddresses = [
50 [ "main" ]
51 [
52 "exports"
53 "."
54 "default"
55 ]
56 [
57 "exports"
58 "."
59 ]
60 [
61 "exports"
62 "default"
63 ]
64 [ "exports" ]
65 ];
66
67 recAttrByPath =
68 addresses: default: attrs:
69 if builtins.length addresses == 0 then
70 default
71 else
72 let
73 addressNext = builtins.head addresses;
74 addressesRemaning = lib.lists.drop 1 addresses;
75 in
76 lib.attrByPath addressNext (recAttrByPath addressesRemaning default attrs) attrs;
77 in
78 packageJsonAttrs:
79 recAttrByPath nodeExportAttrAddresses (builtins.head (
80 lib.attrByPath [ "prettier" "plugins" ] [ "null" ] packageJsonAttrs
81 )) packageJsonAttrs;
82
83 /**
84 # Example
85
86 ```nix
87 nodeEntryPointOf pkgs.nodePackages.prettier-plugin-toml
88 =>
89 /nix/store/<NAR_HASH>-prettier-plugin-toml-<VERSION>/lib/node_modules/prettier-plugin-toml/./lib/index.cjs
90 ```
91
92 # Type
93
94 ```
95 nodeEntryPointOf :: AttrSet => String
96 ```
97
98 # Arguments
99
100 plugin
101 : Attribute set with `.packageName` and `.outPath` defined
102 */
103 nodeEntryPointOf =
104 plugin:
105 let
106 pluginDir = "${plugin.outPath}/lib/node_modules/${plugin.packageName}";
107
108 packageJsonAttrs = builtins.fromJSON (builtins.readFile "${pluginDir}/package.json");
109
110 exportPath = exportRelativePathOf packageJsonAttrs;
111
112 pathAbsoluteNaive = "${pluginDir}/${exportPath}";
113 pathAbsoluteFallback = "${pluginDir}/${exportPath}.js";
114 in
115 if builtins.pathExists pathAbsoluteNaive then
116 pathAbsoluteNaive
117 else if builtins.pathExists pathAbsoluteFallback then
118 pathAbsoluteFallback
119 else
120 lib.warn ''
121 ${plugin.packageName}: error context, tried finding entry point under;
122 pathAbsoluteNaive -> ${pathAbsoluteNaive}
123 pathAbsoluteFallback -> ${pathAbsoluteFallback}
124 '' throw ''${plugin.packageName}: does not provide parse-able entry point'';
125in
126stdenv.mkDerivation (finalAttrs: {
127 pname = "prettier";
128 version = "3.6.2";
129
130 src = fetchFromGitHub {
131 owner = "prettier";
132 repo = "prettier";
133 tag = finalAttrs.version;
134 hash = "sha256-uMLRFBZP7/42R6nReONcb9/kVGCn3yGHLcLFajMZLmQ=";
135 };
136
137 missingHashes = ./missing-hashes.json;
138
139 offlineCache = yarn-berry.fetchYarnBerryDeps {
140 inherit (finalAttrs) src missingHashes;
141 hash = "sha256-dpxzbtWyXsHS6tH6DJ9OqSsUSc+YqYeAPJYb95Qy5wQ=";
142 };
143
144 nativeBuildInputs = [
145 makeBinaryWrapper
146 yarn-berry
147 yarn-berry.yarnBerryConfigHook
148 ];
149
150 installPhase = ''
151 runHook preInstall
152
153 yarn install --immutable
154 yarn build --clean
155
156 cp --recursive dist/prettier "$out"
157
158 makeBinaryWrapper "${lib.getExe nodejs}" "$out/bin/prettier" \
159 --add-flags "$out/bin/prettier.cjs"
160 ''
161 + lib.optionalString (builtins.length plugins > 0) ''
162 wrapProgram $out/bin/prettier --add-flags "${
163 builtins.concatStringsSep " " (lib.map (plugin: "--plugin=${nodeEntryPointOf plugin}") plugins)
164 }";
165 ''
166 + ''
167 runHook postInstall
168 '';
169
170 doInstallCheck = true;
171 nativeInstallCheckInputs = [ versionCheckHook ];
172 versionCheckProgramArg = "--version";
173
174 passthru.updateScript = ./update.sh;
175
176 meta = {
177 changelog = "https://github.com/prettier/prettier/blob/${finalAttrs.version}/CHANGELOG.md";
178 description = "Code formatter";
179 homepage = "https://prettier.io/";
180 license = lib.licenses.mit;
181 mainProgram = "prettier";
182 maintainers = with lib.maintainers; [
183 l0b0
184 S0AndS0
185 ];
186 };
187})