Add obsidian theming

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2024-07-12 19:34:40 +03:00
parent 124f6ab292
commit 5640075117
9 changed files with 305 additions and 124 deletions

View File

@@ -37,14 +37,18 @@ let
"workspaces"
"zk-prefixer"
];
toCssName = path: lib.strings.removeSuffix ".css" (builtins.baseNameOf path);
in
{
options.programs.obsidian =
with lib;
with types;
let
checkCssPath = path: lib.filesystem.pathIsRegularFile path && lib.strings.hasSuffix ".css" path;
cssSnippetsOptions =
{ name, config, ... }:
{ config, ... }:
{
options = {
enable = mkOption {
@@ -55,22 +59,24 @@ in
name = mkOption {
type = str;
defaultText = literalExpression "name";
defaultText = literalExpression "lib.strings.removeSuffix \".css\" (builtins.baseNameOf source)";
description = "Name of the snippet.";
};
source = mkOption {
type = addCheck path (path: if path != null then lib.filesystem.pathIsRegularFile path else true);
type = nullOr (addCheck path checkCssPath);
description = "Path of the source file.";
default = null;
};
text = mkOption {
type = str;
type = nullOr str;
description = "Text of the file.";
default = null;
};
};
config.name = mkDefault name;
config.name = mkDefault (toCssName config.source);
};
pluginsExtraFilesOptions =
@@ -78,13 +84,15 @@ in
{
options = {
source = mkOption {
type = path;
type = nullOr path;
description = "Path of the source file or directory.";
default = null;
};
text = mkOption {
type = str;
type = nullOr str;
description = "Text of the file.";
default = null;
};
target = mkOption {
@@ -94,7 +102,7 @@ in
};
};
config.target = mkIf (config ? text) (mkDefault name);
config.target = mkDefault name;
};
pluginsOptions =
@@ -125,11 +133,8 @@ in
options = {
enable = mkOption {
type = bool;
default = false;
description = ''
Whether to set the theme as active.
Only one theme can be active at a time.
'';
default = true;
description = "Whether to set the theme as active.";
};
pkg = mkOption {
@@ -184,7 +189,7 @@ in
cssSnippets = mkOption {
description = "CSS snippets to install.";
type = raw;
default = { };
default = [ ];
};
plugins = mkOption {
@@ -240,19 +245,19 @@ in
cssSnippets = mkOption {
description = "CSS snippets to install.";
type = attrsOf (submodule cssSnippetsOptions);
type = listOf (either (addCheck path checkCssPath) (submodule cssSnippetsOptions));
default = cfg.sharedSettings.cssSnippets;
};
plugins = mkOption {
description = "Community plugins to install and activate.";
type = listOf (submodule pluginsOptions);
type = listOf (either package (submodule pluginsOptions));
default = cfg.sharedSettings.plugins;
};
themes = mkOption {
description = "Themes to install.";
type = listOf (submodule themesOptions);
type = listOf (either package (submodule themesOptions));
default = cfg.sharedSettings.themes;
};
};
@@ -269,11 +274,13 @@ in
config =
let
vaults = builtins.filter (vault: vault.enable == true) (builtins.attrValues cfg.vaults);
readDir = dir: builtins.attrNames (builtins.readDir dir);
toPkg = item: if item ? pkg then item.pkg else item;
isEnabled = item: if item ? enable then item.enable else true;
getCssName = item: if builtins.isAttrs item then item.name else toCssName item;
getManifest =
pkg:
item:
let
manifest = builtins.fromJSON (builtins.readFile "${pkg}/manifest.json");
manifest = builtins.fromJSON (builtins.readFile "${toPkg item}/manifest.json");
in
manifest.id or manifest.name;
in
@@ -294,20 +301,18 @@ in
name = "${vault.target}/.obsidian/appearance.json";
value =
let
enabledSnippets = builtins.filter (snippet: snippet.enable) (
builtins.attrValues vault.settings.cssSnippets
);
activeTheme = lib.lists.findSingle (
theme: theme.enable
) null (throw "Only one theme can be enabled at a time.") vault.settings.themes;
enabledCssSnippets = builtins.filter isEnabled vault.settings.cssSnippets;
activeTheme =
lib.lists.findSingle isEnabled null (throw "Only one theme can be enabled at a time.")
vault.settings.themes;
in
{
source = (pkgs.formats.json { }).generate "appearance.json" (
vault.settings.appearance
// {
enabledCssSnippets = builtins.map (snippet: snippet.name) enabledSnippets;
enabledCssSnippets = builtins.map getCssName enabledCssSnippets;
}
// lib.attrsets.optionalAttrs (activeTheme != null) { cssTheme = getManifest activeTheme.pkg; }
// lib.attrsets.optionalAttrs (activeTheme != null) { cssTheme = getManifest activeTheme; }
);
};
};
@@ -327,7 +332,7 @@ in
builtins.map (plugin: {
name = plugin;
value = builtins.elem plugin vault.settings.corePlugins;
}) corePlugins
}) vault.settings.corePlugins
)
);
};
@@ -337,14 +342,14 @@ in
mkCommunityPlugins =
vault:
let
enabledPlugins = builtins.filter (plugin: plugin.enable) vault.settings.plugins;
enabledPlugins = builtins.filter isEnabled vault.settings.plugins;
in
[
{
name = "${vault.target}/.obsidian/community-plugins.json";
value = {
source = (pkgs.formats.json { }).generate "community-plugins.json" (
builtins.map (plugin: getManifest plugin.pkg) enabledPlugins
builtins.map getManifest enabledPlugins
);
};
}
@@ -362,34 +367,42 @@ in
*/
++ builtins.map (
plugin:
let
pkg = toPkg plugin;
files = builtins.attrNames (builtins.readDir pkg);
in
builtins.map (file: {
name = "${vault.target}/.obsidian/plugins/${getManifest plugin.pkg}/${file}";
name = "${vault.target}/.obsidian/plugins/${getManifest plugin}/${file}";
value = {
source = "${plugin.pkg}/${file}";
source = "${pkg}/${file}";
};
}) (readDir plugin.pkg)
}) files
) vault.settings.plugins
++ builtins.map (
plugin:
builtins.map (file: {
name = "${vault.target}/.obsidian/plugins/${getManifest plugin.pkg}/${file.target}";
value = if file ? source then { source = file.source; } else { text = file.text; };
}) (builtins.attrValues plugin.extraFiles)
name = "${vault.target}/.obsidian/plugins/${getManifest plugin}/${file.target}";
value = if file.source != null then { inherit (file) source; } else { inherit (file) text; };
}) (builtins.attrValues (plugin.extraFiles or { }))
) vault.settings.plugins;
mkCssSnippets =
vault:
builtins.map (snippet: {
name = "${vault.target}/.obsidian/snippets/${snippet.name}.css";
value = if snippet ? source then { source = snippet.source; } else { text = snippet.text; };
}) (builtins.attrValues vault.settings.cssSnippets);
name = "${vault.target}/.obsidian/snippets/${getCssName snippet}.css";
value =
if snippet ? source || snippet ? text then
if snippet.source != null then { inherit (snippet) source; } else { inherit (snippet) text; }
else
{ source = snippet; };
}) vault.settings.cssSnippets;
mkThemes =
vault:
builtins.map (theme: {
name = "${vault.target}/.obsidian/themes/${getManifest theme.pkg}";
name = "${vault.target}/.obsidian/themes/${getManifest theme}";
value = {
source = theme.pkg;
source = toPkg theme;
};
}) vault.settings.themes;
in
@@ -416,6 +429,31 @@ in
} // (lib.attrsets.optionalAttrs ((builtins.length vaults) == 1) { open = true; });
}) vaults
);
updateDisabled = true;
};
assertions = [
{
assertion = builtins.all (
vault:
builtins.all (
snippet: (!snippet ? source && !snippet ? text) || (snippet.source == null || snippet.text == null)
) vault.settings.cssSnippets
) (builtins.attrValues cfg.vaults);
message = "Only one of `source` and `text` must be set";
}
{
assertion = builtins.all (
vault:
builtins.all (
plugin:
builtins.all (file: file.source == null || file.text == null) (
builtins.attrValues (plugin.extraFiles or { })
)
) vault.settings.plugins
) (builtins.attrValues cfg.vaults);
message = "Only one of `source` and `text` must be set";
}
];
};
}