noctalia
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "37e681728b2fec11796989fc48cc3d31"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.antigravity]
|
||||
name = "Antigravity"
|
||||
category = "ai"
|
||||
|
||||
[templates.antigravity]
|
||||
input_path = "antigravity.json"
|
||||
output_path = "~/.gemini/config/theme.json"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "b2c456fb15853159cfcb213f38b91b97"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[catalog.archetype-pokemmo]
|
||||
name = "Archetype (PokeMMO)"
|
||||
category = "gaming"
|
||||
|
||||
[templates.archetype-pokemmo]
|
||||
input_path_modes = { dark = "archetype-colors-dark.json", light = "archetype-colors-light.json" }
|
||||
output_path = "$XDG_CACHE_HOME/noctalia/archetype-pokemmo/colors.json"
|
||||
post_hook = "python3 '{{ config_dir }}/apply.py'"
|
||||
hook_async = false
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"files": {
|
||||
"README.md": "c971168a3f8d5a0c570c8a7813760655",
|
||||
"apply.sh": "72fdf03821d232593cf85ea926253472",
|
||||
"bat.tmTheme": "48ce50cbdc345e4a61d8a3dc95b4fce8",
|
||||
"template.toml": "6ee484a55483e12300a00641ec38aecc"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# bat
|
||||
|
||||
Adds a Noctalia syntax-highlighting theme for bat.
|
||||
|
||||
Enable **bat** in **Noctalia Settings -> Templates**. The template writes `$XDG_CONFIG_HOME/bat/themes/noctalia.tmTheme` (`~/.config/bat/themes/noctalia.tmTheme` by default).
|
||||
|
||||
The Bash post-hook creates `$XDG_CONFIG_HOME/bat/config` if necessary and selects `--theme=noctalia`. Unless that exact line is already present, it removes existing lines beginning with `--theme=` before appending the new selection. Back up your config first; no backup is created.
|
||||
|
||||
Install `bat` or `batcat`: the hook runs the available executable with `cache --build` after generation. If neither exists, it prints a warning; run `bat cache --build` (or `batcat cache --build`) yourself after installation.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
bat_config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/bat"
|
||||
themes_dir="$bat_config_dir/themes"
|
||||
config_file="$bat_config_dir/config"
|
||||
theme_file="$themes_dir/noctalia.tmTheme"
|
||||
theme_line="--theme=noctalia"
|
||||
|
||||
mkdir -p "$themes_dir"
|
||||
touch "$config_file" "$theme_file"
|
||||
|
||||
write_if_changed() {
|
||||
local target="$1" tmp="$2"
|
||||
if ! cmp -s "$target" "$tmp"; then
|
||||
cat "$tmp" >"$target"
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
if ! grep -Fxq -- "$theme_line" "$config_file"; then
|
||||
tmp_file="$(mktemp "${config_file}.tmp.XXXXXX")"
|
||||
sed '/^--theme=/d' "$config_file" >"$tmp_file"
|
||||
[ -s "$tmp_file" ] && [ -n "$(tail -c1 "$tmp_file")" ] && echo >>"$tmp_file"
|
||||
printf '%s\n' "$theme_line" >>"$tmp_file"
|
||||
write_if_changed "$config_file" "$tmp_file"
|
||||
fi
|
||||
|
||||
if command -v bat >/dev/null 2>&1; then
|
||||
bat cache --build
|
||||
elif command -v batcat >/dev/null 2>&1; then
|
||||
batcat cache --build
|
||||
else
|
||||
echo "Warning: 'bat' executable not found. Please run 'bat cache --build' manually once it is installed."
|
||||
fi
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
[catalog.bat]
|
||||
name = "bat"
|
||||
category = "terminal"
|
||||
|
||||
[templates.bat]
|
||||
input_path = "bat.tmTheme"
|
||||
output_path = "$XDG_CONFIG_HOME/bat/themes/noctalia.tmTheme"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"files": {
|
||||
"README.md": "af0b5fd57df6929d6d1f629518541b08",
|
||||
"blender_theme.py": "1a0cd158ac744d4887a832631d1c58b3",
|
||||
"screenshot.png": "35fe418801156063765900cb85780f4e",
|
||||
"template.toml": "2268722156753442c3797250df7f4222"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
# Blender
|
||||
|
||||
Blender's theme system isn't a CSS file, it's roughly 570 individual color properties on
|
||||
`bpy.context.preferences.themes[0]`, saved into a binary `userpref.blend`, not a plain-text
|
||||
config. So this template doesn't just render a file, `input_path` is a Python script (with
|
||||
`{{colors.role.default.hex}}` placeholders substituted the normal way), and `post_hook` runs it
|
||||
through Blender itself in headless mode, which applies the colors via the real `bpy` API and
|
||||
saves preferences directly. No GUI window opens, `--background` mode is fully invisible.
|
||||
|
||||
## What gets themed, and what deliberately doesn't
|
||||
|
||||
Only structural chrome: panel backgrounds, headers, tab strips, widget fills/outlines/text,
|
||||
editor borders, list backgrounds, metadata overlay boxes. Around 345 of the ~570 properties.
|
||||
|
||||
The rest (about 225) are left at Blender's own defaults on purpose: mesh-editing selection
|
||||
states (vertex/edge/face colors), node category colors, sequencer strip-type colors, syntax
|
||||
highlighting, keyframe types, axis/gizmo colors. These are workflow conventions users rely on
|
||||
for actual 3D work, not decoration, recoloring them to an arbitrary palette would hurt
|
||||
usability rather than improve consistency. Same reasoning already applied to terminal ANSI
|
||||
colors and Blender's own axis-color convention (X=red, Y=green, Z=blue) elsewhere.
|
||||
|
||||
## Native install
|
||||
|
||||
Runs `blender --background --python ...` directly. No setup beyond having `blender` on `PATH`.
|
||||
|
||||
## Flatpak install (`org.blender.Blender`)
|
||||
|
||||
Blender's Flatpak has `filesystems=host` (full host filesystem access), broader than most
|
||||
sandboxed apps here. `$XDG_CONFIG_HOME` inside the sandbox is still remapped to
|
||||
`~/.var/app/org.blender.Blender/config` regardless, same as every other Flatpak app, but that
|
||||
doesn't matter for this template: the rendered script lives at a plain host path
|
||||
(`~/.cache/noctalia/blender_theme_rendered.py`), and Blender's `host` grant means it can read
|
||||
that path directly by its real location, no `flatpak override` or `.var/app`-local copy needed
|
||||
at all.
|
||||
|
||||
## Testing
|
||||
|
||||
Tested against Blender 5.2.0 LTS (Flatpak). Verified via a full audit: captured Blender's true
|
||||
factory-default theme values (`--factory-startup`) and diffed against the post-apply state
|
||||
property by property, confirming exactly which of the ~570 were intentionally changed versus
|
||||
intentionally left alone, not just spot-checked visually.
|
||||
@@ -0,0 +1,192 @@
|
||||
"""Applies Noctalia's palette to Blender's UI chrome, run headless via `blender --background --python`.
|
||||
|
||||
Only structural chrome is themed: panel backgrounds, headers, widget fills/outlines/text.
|
||||
Workflow-meaningful colors (mesh selection states, node categories, sequencer strip types,
|
||||
syntax highlighting) are deliberately left at Blender's own defaults, since users rely on those
|
||||
as functional conventions, not decoration.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
||||
COLORS = {
|
||||
"surface": "{{colors.surface.default.hex}}",
|
||||
"on_surface": "{{colors.on_surface.default.hex}}",
|
||||
"surface_variant": "{{colors.surface_variant.default.hex}}",
|
||||
"on_surface_variant": "{{colors.on_surface_variant.default.hex}}",
|
||||
"surface_container": "{{colors.surface_container.default.hex}}",
|
||||
"surface_container_low": "{{colors.surface_container_low.default.hex}}",
|
||||
"surface_container_high": "{{colors.surface_container_high.default.hex}}",
|
||||
"outline": "{{colors.outline.default.hex}}",
|
||||
"outline_variant": "{{colors.outline_variant.default.hex}}",
|
||||
"primary": "{{colors.primary.default.hex}}",
|
||||
"on_primary": "{{colors.on_primary.default.hex}}",
|
||||
"primary_container": "{{colors.primary_container.default.hex}}",
|
||||
"on_primary_container": "{{colors.on_primary_container.default.hex}}",
|
||||
"secondary": "{{colors.secondary.default.hex}}",
|
||||
"secondary_container": "{{colors.secondary_container.default.hex}}",
|
||||
"on_secondary_container": "{{colors.on_secondary_container.default.hex}}",
|
||||
"tertiary": "{{colors.tertiary.default.hex}}",
|
||||
"tertiary_container": "{{colors.tertiary_container.default.hex}}",
|
||||
"on_tertiary_container": "{{colors.on_tertiary_container.default.hex}}",
|
||||
"error": "{{colors.error.default.hex}}",
|
||||
"on_error": "{{colors.on_error.default.hex}}",
|
||||
"error_container": "{{colors.error_container.default.hex}}",
|
||||
}
|
||||
|
||||
|
||||
def hex_to_rgb(hex_str):
|
||||
hex_str = hex_str.lstrip("#")
|
||||
return tuple(int(hex_str[i : i + 2], 16) / 255.0 for i in (0, 2, 4))
|
||||
|
||||
|
||||
RGB = {name: hex_to_rgb(value) for name, value in COLORS.items()}
|
||||
|
||||
|
||||
def classify(path):
|
||||
if path.endswith(".space.back"):
|
||||
return "surface"
|
||||
if path.endswith(".space.header"):
|
||||
return "surface_container"
|
||||
if path.endswith(".space.header_text"):
|
||||
return "on_surface"
|
||||
if path.endswith(".space.header_text_hi"):
|
||||
return "primary"
|
||||
if path.endswith(".space.text"):
|
||||
return "on_surface"
|
||||
if path.endswith(".space.text_hi"):
|
||||
return "primary"
|
||||
if path.endswith(".space.title"):
|
||||
return "on_surface_variant"
|
||||
if path.endswith(".space.tab_active"):
|
||||
return "surface_container_high"
|
||||
if path.endswith(".space.tab_back"):
|
||||
return "surface_container_low"
|
||||
if path.endswith(".space.tab_outline"):
|
||||
return "outline"
|
||||
if path.endswith(".space.gradients.gradient"):
|
||||
return "surface"
|
||||
if path.endswith(".space.gradients.high_gradient"):
|
||||
return "surface_container"
|
||||
if path.endswith("row_alternate"):
|
||||
return "surface_container_low"
|
||||
|
||||
if ".wcol_" in path:
|
||||
suffix = path.rsplit(".", 1)[-1]
|
||||
wcol_map = {
|
||||
"inner": "surface_container",
|
||||
"inner_sel": "primary_container",
|
||||
"inner_key": "tertiary_container",
|
||||
"inner_key_sel": "tertiary_container",
|
||||
"inner_anim": "secondary_container",
|
||||
"inner_anim_sel": "secondary_container",
|
||||
"inner_driven": "tertiary",
|
||||
"inner_driven_sel": "tertiary",
|
||||
"inner_changed": "primary",
|
||||
"inner_changed_sel": "primary",
|
||||
"inner_overridden": "error_container",
|
||||
"inner_overridden_sel": "error_container",
|
||||
"outline": "outline",
|
||||
"outline_sel": "primary",
|
||||
"item": "on_surface_variant",
|
||||
"text": "on_surface",
|
||||
"text_sel": "on_primary",
|
||||
"error": "error",
|
||||
"warning": "tertiary",
|
||||
"success": "secondary",
|
||||
"info": "primary",
|
||||
}
|
||||
if suffix in wcol_map:
|
||||
return wcol_map[suffix]
|
||||
|
||||
if path.startswith("regions."):
|
||||
if path.endswith(".back") or path.endswith(".header_back"):
|
||||
return "surface_container"
|
||||
if path.endswith(".tab_back"):
|
||||
return "surface_container_low"
|
||||
if path.endswith(".text"):
|
||||
return "on_surface"
|
||||
if path.endswith(".text_selected"):
|
||||
return "primary"
|
||||
|
||||
direct = {
|
||||
"text_editor.line_numbers": "on_surface_variant",
|
||||
"text_editor.line_numbers_background": "surface_container_low",
|
||||
"text_editor.cursor": "primary",
|
||||
"text_editor.selected_text": "primary_container",
|
||||
"image_editor.metadatabg": "surface_container",
|
||||
"image_editor.metadatatext": "on_surface",
|
||||
"sequence_editor.metadatabg": "surface_container",
|
||||
"sequence_editor.metadatatext": "on_surface",
|
||||
"sequence_editor.preview_back": "surface",
|
||||
"clip_editor.metadatabg": "surface_container",
|
||||
"clip_editor.metadatatext": "on_surface",
|
||||
"node_editor.node_outline": "outline",
|
||||
"user_interface.widget_text_cursor": "primary",
|
||||
"user_interface.editor_border": "outline",
|
||||
"user_interface.editor_outline": "outline_variant",
|
||||
"user_interface.editor_outline_active": "primary",
|
||||
"user_interface.panel_header": "surface_container",
|
||||
"user_interface.panel_back": "surface_container_low",
|
||||
"user_interface.panel_outline": "outline",
|
||||
"user_interface.panel_title": "on_surface",
|
||||
"user_interface.panel_text": "on_surface",
|
||||
"user_interface.panel_active": "primary",
|
||||
"outliner.selected_highlight": "primary_container",
|
||||
"outliner.active": "primary",
|
||||
"outliner.selected_object": "on_primary_container",
|
||||
"outliner.active_object": "on_primary",
|
||||
"outliner.match": "tertiary_container",
|
||||
"info.info_error_text": "error",
|
||||
"info.info_warning_text": "tertiary",
|
||||
"info.info_info_text": "on_surface",
|
||||
"info.info_property_text": "secondary",
|
||||
"info.info_operator_text": "primary",
|
||||
"info.info_debug_text": "outline",
|
||||
"info.info_selected": "primary_container",
|
||||
"info.info_selected_text": "on_primary_container",
|
||||
"console.line_output": "on_surface",
|
||||
"console.line_input": "primary",
|
||||
"console.line_info": "secondary",
|
||||
"console.line_error": "error",
|
||||
"console.select": "primary_container",
|
||||
"console.cursor": "primary",
|
||||
"file_browser.selected_file": "primary_container",
|
||||
"preferences.match": "tertiary_container",
|
||||
"properties.match": "tertiary_container",
|
||||
}
|
||||
if path in direct:
|
||||
return direct[path]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def walk_and_apply(obj, path="", depth=0):
|
||||
if depth > 4:
|
||||
return 0
|
||||
applied = 0
|
||||
for prop in obj.bl_rna.properties:
|
||||
if prop.identifier == "rna_type":
|
||||
continue
|
||||
try:
|
||||
val = getattr(obj, prop.identifier)
|
||||
except Exception:
|
||||
continue
|
||||
full = f"{path}.{prop.identifier}" if path else prop.identifier
|
||||
if prop.type == "POINTER" and val is not None:
|
||||
applied += walk_and_apply(val, full, depth + 1)
|
||||
elif prop.type == "FLOAT" and getattr(prop, "array_length", 0) in (3, 4):
|
||||
role = classify(full)
|
||||
if role is None:
|
||||
continue
|
||||
rgb = RGB[role]
|
||||
current = list(val)
|
||||
current[0], current[1], current[2] = rgb
|
||||
setattr(obj, prop.identifier, current)
|
||||
applied += 1
|
||||
return applied
|
||||
|
||||
|
||||
theme = bpy.context.preferences.themes[0]
|
||||
count = walk_and_apply(theme)
|
||||
print(f"noctalia-theme: applied {count} properties")
|
||||
bpy.ops.wm.save_userpref()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 396 KiB |
@@ -0,0 +1,15 @@
|
||||
[catalog.blender]
|
||||
name = "Blender"
|
||||
category = "editor"
|
||||
|
||||
[templates.blender]
|
||||
input_path = "blender_theme.py"
|
||||
output_path = "~/.cache/noctalia/blender_theme_rendered.py"
|
||||
post_hook = "blender --background --python ~/.cache/noctalia/blender_theme_rendered.py"
|
||||
requires_path = "~/.config/blender"
|
||||
|
||||
[templates.blender-flatpak]
|
||||
input_path = "blender_theme.py"
|
||||
output_path = "~/.cache/noctalia/blender_theme_rendered.py"
|
||||
post_hook = "flatpak run org.blender.Blender --background --python ~/.cache/noctalia/blender_theme_rendered.py"
|
||||
requires_path = "~/.var/app/org.blender.Blender"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "b00582c206b5456ae8fd82882d0c8084"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[catalog.brave-origin]
|
||||
name = "Brave Origin"
|
||||
category = "browser"
|
||||
|
||||
[templates.brave-origin]
|
||||
input_path = "manifest.json"
|
||||
output_path = "$XDG_CACHE_HOME/noctalia/brave-origin-theme/manifest.json"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh' {{ mode }}"
|
||||
requires_path = "~/.config/BraveSoftware/Brave-Origin"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "5824b129b9a884cf0a1d6ce1ac0c2c7a"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[catalog.brave]
|
||||
name = "Brave"
|
||||
category = "browser"
|
||||
|
||||
[templates.brave]
|
||||
input_path = "manifest.json"
|
||||
output_path = "$XDG_CACHE_HOME/noctalia/brave-theme/manifest.json"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh' {{ mode }}"
|
||||
requires_path = "~/.config/BraveSoftware/Brave-Browser"
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "630b15c67a7b75a02d88151b21b09a06"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[catalog.chromium-based]
|
||||
name = "Chromium based"
|
||||
category = "browser"
|
||||
|
||||
[templates.chromium-based]
|
||||
input_path = "color.json"
|
||||
output_path_dynamic = "bash '{{ config_dir }}/apply.sh' output"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh' refresh"
|
||||
undo_hook = "bash '{{ config_dir }}/apply.sh' undo"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "47a5727698275d6e0a4dd457a0a93bc9"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[catalog.claude-code]
|
||||
name = "Claude Code"
|
||||
category = "ai"
|
||||
|
||||
[templates.claude-code]
|
||||
input_path = "claude-code.json"
|
||||
output_path = "~/.claude/themes/noctalia.json"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "d3540eaa368262a0691d7f21f1c537f3"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[catalog.codex]
|
||||
name = "Codex"
|
||||
category = "ai"
|
||||
|
||||
[templates.codex]
|
||||
input_path = "codex.tmTheme"
|
||||
output_path = "~/.codex/themes/noctalia.tmTheme"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "695af0569a2f5d7067a8079466115416"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
[catalog.cosmic]
|
||||
name = "COSMIC"
|
||||
category = "system"
|
||||
|
||||
[templates.cosmic]
|
||||
input_path = "cosmic-colors"
|
||||
output_path = "$XDG_CACHE_HOME/noctalia/cosmic-palette"
|
||||
post_hook = "python3 '{{ config_dir }}/apply.py'"
|
||||
undo_hook = "bash '{{ config_dir }}/undo.sh'"
|
||||
hook_async = false
|
||||
requires_path = "~/.config/cosmic"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "20dd9a1cf1df1d87e3674062ed53df2b"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[catalog.cressida]
|
||||
name = "Cressida"
|
||||
category = "chat"
|
||||
|
||||
[templates.cressida]
|
||||
input_path = "cressida.toml"
|
||||
output_path = "$XDG_CONFIG_HOME/cressida/themes/noctalia.toml"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "6759a4e4a2ffde8fd624f67a73cefdeb"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[catalog.darktable]
|
||||
name = "darktable"
|
||||
category = "editor"
|
||||
|
||||
[templates.darktable]
|
||||
input_path = "noctalia.css"
|
||||
output_path = "~/.config/darktable/themes/noctalia.css"
|
||||
requires_path = "~/.config/darktable"
|
||||
|
||||
[templates.darktable-flatpak]
|
||||
input_path = "noctalia-flatpak.css"
|
||||
output_path = "~/.var/app/org.darktable.Darktable/config/darktable/themes/noctalia.css"
|
||||
requires_path = "~/.var/app/org.darktable.Darktable"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "b7fcfda472b57734eb8259fa80bf2fd2"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
[catalog.discord]
|
||||
name = "Discord"
|
||||
category = "chat"
|
||||
|
||||
[templates.discord_midnight_vesktop]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/vesktop/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_vesktop]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/vesktop/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_vesktop]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/vesktop/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_vesktop_flatpak]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "~/.var/app/dev.vencord.Vesktop/config/vesktop/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_vesktop_flatpak]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "~/.var/app/dev.vencord.Vesktop/config/vesktop/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_vesktop_flatpak]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "~/.var/app/dev.vencord.Vesktop/config/vesktop/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_webcord]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/webcord/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_webcord]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/webcord/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_webcord]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/webcord/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_legcord]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/legcord/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_legcord]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/legcord/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_legcord]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/legcord/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_equibop]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/equibop/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_equibop]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/equibop/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_equibop]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/equibop/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_equicord]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/Equicord/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_equicord]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/Equicord/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_equicord]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/Equicord/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_lightcord]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/lightcord/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_lightcord]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/lightcord/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_lightcord]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/lightcord/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_dorion]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/dorion/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_dorion]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/dorion/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_dorion]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/dorion/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_vencord]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/Vencord/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_vencord]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/Vencord/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_vencord]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/Vencord/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_vencord_flatpak]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "~/.var/app/com.discordapp.Discord/config/Vencord/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_vencord_flatpak]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "~/.var/app/com.discordapp.Discord/config/Vencord/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_vencord_flatpak]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "~/.var/app/com.discordapp.Discord/config/Vencord/themes/discord-system24.css"
|
||||
|
||||
[templates.discord_midnight_betterdiscord]
|
||||
input_path = "discord-midnight.css"
|
||||
output_path = "$XDG_CONFIG_HOME/BetterDiscord/themes/noctalia.theme.css"
|
||||
|
||||
[templates.discord_material_betterdiscord]
|
||||
input_path = "discord-material.css"
|
||||
output_path = "$XDG_CONFIG_HOME/BetterDiscord/themes/noctalia-material.theme.css"
|
||||
|
||||
[templates.discord_system24_betterdiscord]
|
||||
input_path = "discord-system24.css"
|
||||
output_path = "$XDG_CONFIG_HOME/BetterDiscord/themes/discord-system24.css"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "2be6fd472586a5be0c40b4e2de4bdf4c"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.driftwm]
|
||||
name = "DriftWM"
|
||||
category = "compositor"
|
||||
|
||||
[templates.driftwm]
|
||||
input_path = "driftwm-colors"
|
||||
output_path = "$XDG_CACHE_HOME/noctalia-driftwm-colors"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"files": {
|
||||
"README.md": "eaa53d6ac50931e057bf030c678fd3d7",
|
||||
"apply.sh": "c605011961d37be31b8c710c83303360",
|
||||
"fastfetch-colors.jsonc": "3de977e47b4cc00e76866e680974700a",
|
||||
"screenshot.png": "e5be2fe0b3041fd4342ccfce6877a169",
|
||||
"template.toml": "f05501b07584db28af6d779612bb58cf"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
# fastfetch
|
||||
|
||||
Themes [fastfetch](https://github.com/fastfetch-cli/fastfetch) — sets `display.color.keys`,
|
||||
`display.color.title`, `display.percent.color.{green,yellow,red}` and `logo.color.{1,2}`.
|
||||
|
||||
fastfetch's config (`~/.config/fastfetch/config.jsonc`) has no include/merge directive, so
|
||||
`apply.sh` merges the rendered color object into the user's real config.jsonc directly (`jq -s
|
||||
'.[0] * .[1]'`), preserving everything else in it (modules list, custom module config, etc.).
|
||||
|
||||
**Known limitation: strict JSON only, not full JSONC.** `jq` (used for the merge) only parses
|
||||
strict JSON — `//`/`/* */` comments and trailing commas, both valid JSONC, will make `apply.sh`
|
||||
fail. It fails loudly with a clear message in that case rather than silently corrupting the file
|
||||
or applying nothing with no explanation. If your `config.jsonc` uses comments, remove them to use
|
||||
this template (fastfetch's own `--gen-config`/`--gen-config-force` output has none by default).
|
||||
Also fails loudly (rather than auto-creating one) if `config.jsonc` doesn't exist at all yet —
|
||||
run fastfetch once first to generate a default config.
|
||||
|
||||
**Idempotency note**: the merge is guarded by comparing only the `logo`/`display` sub-objects
|
||||
semantically (`jq -S`), not the whole file's raw bytes — a naive whole-file `cmp` after a `jq`
|
||||
merge will never actually match hand-formatted JSON (`jq` re-serializes with its own canonical
|
||||
formatting), which silently defeats the guard and rewrites the file on every apply regardless of
|
||||
whether colors changed. Verified idempotent: running `apply.sh` twice with unchanged colors
|
||||
leaves the file's mtime and content completely untouched.
|
||||
|
||||
**Known upstream bug (worked around here): `logo.color` silently drops pastel/light colors.**
|
||||
Confirmed live against fastfetch 2.66.0: a `logo.color.N` value is dropped with no error — the
|
||||
logo falls back to its default palette — whenever its truecolor SGR string (`38;2;R;G;B`) is
|
||||
exactly 16 characters, i.e. every one of R/G/B is a 3-digit number (`>=100`). That covers a large
|
||||
share of real accent colors, including most pastel/light theme colors. `display.color.keys`/
|
||||
`title`/`percent` are unaffected — only `logo.color.N` goes through the broken code path.
|
||||
Isolated by testing the exact byte-length trigger directly (both via `--logo-color-N` and via this
|
||||
same JSON key) with fully saturated colors of the same hue (worked) vs. desaturated/light colors
|
||||
producing a 16-char string (failed), including a control test with a non-pastel color that still
|
||||
had all three channels `>=100` (also failed) — confirming it's the string length, not the hue or
|
||||
lightness itself.
|
||||
|
||||
`apply.sh` routes around it: whenever a `logo.color` value would trip the bug, the single
|
||||
*smallest* RGB channel is nudged down to 99 — the minimal change that drops the SGR string below
|
||||
16 characters, and since it's already the channel closest to the 100 boundary, it's the smallest
|
||||
possible perceptual shift (e.g. `#fff59b` → `#fff563`). An earlier version of this fix quantized
|
||||
to the nearest ANSI-256 cube color instead, but the 216-color cube only has 6 steps per channel,
|
||||
so a near-white pastel like `#fff59b` snapped to `#ffffaf` — visually just white on a small ascii
|
||||
logo. The channel-nudge keeps full 24-bit truecolor and stays close to the real color.
|
||||
|
||||
Tested against fastfetch 2.66.0.
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
config_dir_xdg="${XDG_CONFIG_HOME:-$HOME/.config}/fastfetch"
|
||||
config_file="$config_dir_xdg/config.jsonc"
|
||||
theme_file="$config_dir_xdg/themes/noctalia.jsonc"
|
||||
|
||||
if [ ! -f "$config_file" ]; then
|
||||
echo "Error: fastfetch config not found at $config_file -- run fastfetch once to generate a default config first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$theme_file" ]; then
|
||||
echo "Warning: fastfetch theme file not found: $theme_file" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# jq only accepts strict JSON. config.jsonc is JSONC (comments/trailing commas allowed), so
|
||||
# fail loudly with a clear message rather than let a bare jq parse error explain nothing, or
|
||||
# silently skip and leave the user without any indication why colors never apply.
|
||||
if ! jq empty "$config_file" 2>/dev/null; then
|
||||
echo "Error: $config_file could not be parsed as strict JSON. Comments and trailing commas (valid JSONC, not valid JSON) are not currently supported by this hook -- remove them to use this template." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# fastfetch 2.66.0 has a confirmed real bug in its logo renderer: a
|
||||
# logo.color value is dropped silently -- the logo falls back to its
|
||||
# default palette with no error -- whenever its truecolor SGR string
|
||||
# ("38;2;R;G;B") is exactly 16 characters, i.e. every one of R/G/B is a
|
||||
# 3-digit number (>=100). That covers a large share of real accent colors
|
||||
# (most pastel/light theme colors included). display.color.keys/title/
|
||||
# percent are unaffected -- only logo.color.N goes through the broken path.
|
||||
# Verified live against 2.66.0 by isolating the exact byte-length trigger:
|
||||
# any hex where all three channels are >=100 reproduces it, regardless of
|
||||
# hue; anything with at least one channel <100 (a shorter SGR string)
|
||||
# renders correctly.
|
||||
#
|
||||
# Route around it by nudging the single *smallest* channel down to 99
|
||||
# whenever all three are >=100 -- that's the minimal change that drops the
|
||||
# SGR string below 16 chars, and it's always the channel closest to the
|
||||
# 100 boundary already, so it's the smallest possible perceptual shift.
|
||||
# (An earlier version of this fix quantized to the nearest ANSI-256 cube
|
||||
# color instead, but the 216-color cube only has 6 steps per channel, so a
|
||||
# near-white pastel like #fff59b snapped to #ffffaf -- visually just
|
||||
# "white" on a small ascii logo. This keeps full 24-bit truecolor.)
|
||||
nudge_channel() {
|
||||
local hex="${1#\#}"
|
||||
local r=$((16#${hex:0:2}))
|
||||
local g=$((16#${hex:2:2}))
|
||||
local b=$((16#${hex:4:2}))
|
||||
if [ "$r" -ge 100 ] && [ "$g" -ge 100 ] && [ "$b" -ge 100 ]; then
|
||||
if [ "$r" -le "$g" ] && [ "$r" -le "$b" ]; then
|
||||
r=99
|
||||
elif [ "$g" -le "$r" ] && [ "$g" -le "$b" ]; then
|
||||
g=99
|
||||
else
|
||||
b=99
|
||||
fi
|
||||
fi
|
||||
printf '#%02x%02x%02x' "$r" "$g" "$b"
|
||||
}
|
||||
|
||||
tmp_theme="$(mktemp)"
|
||||
tmp_file=""
|
||||
trap 'rm -f "$tmp_theme" "${tmp_file:-}"' EXIT
|
||||
|
||||
logo_1="$(jq -r '.logo.color."1" // empty' "$theme_file")"
|
||||
logo_2="$(jq -r '.logo.color."2" // empty' "$theme_file")"
|
||||
|
||||
jq \
|
||||
--arg c1 "$([ -n "$logo_1" ] && nudge_channel "$logo_1" || echo "")" \
|
||||
--arg c2 "$([ -n "$logo_2" ] && nudge_channel "$logo_2" || echo "")" \
|
||||
'(if $c1 != "" then .logo.color."1" = $c1 else . end)
|
||||
| (if $c2 != "" then .logo.color."2" = $c2 else . end)' \
|
||||
"$theme_file" >"$tmp_theme"
|
||||
|
||||
# Compare only the "logo"/"display" sub-objects semantically (jq -S, sorted+canonical),
|
||||
# not the whole file's raw bytes -- jq's own re-serialization would never byte-match
|
||||
# hand-formatted JSON, which made a naive cmp-the-whole-file guard fire on every single
|
||||
# apply regardless of whether colors actually changed.
|
||||
current_logo="$(jq -S '.logo // {}' "$config_file")"
|
||||
current_display="$(jq -S '.display // {}' "$config_file")"
|
||||
new_logo="$(jq -S '.logo // {}' "$tmp_theme")"
|
||||
new_display="$(jq -S '.display // {}' "$tmp_theme")"
|
||||
|
||||
if [ "$current_logo" != "$new_logo" ] || [ "$current_display" != "$new_display" ]; then
|
||||
tmp_file="$(mktemp)"
|
||||
jq -s '.[0] * .[1]' "$config_file" "$tmp_theme" >"$tmp_file"
|
||||
cat "$tmp_file" >"$config_file"
|
||||
fi
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"logo": {
|
||||
"color": {
|
||||
"1": "{{colors.primary.default.hex}}",
|
||||
"2": "{{colors.secondary.default.hex}}"
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"color": {
|
||||
"keys": "{{colors.primary.default.hex}}",
|
||||
"title": "{{colors.secondary.default.hex}}"
|
||||
},
|
||||
"percent": {
|
||||
"color": {
|
||||
"green": "{{colors.tertiary.default.hex}}",
|
||||
"yellow": "{{colors.primary_fixed_dim.default.hex}}",
|
||||
"red": "{{colors.error.default.hex}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
@@ -0,0 +1,8 @@
|
||||
[catalog.fastfetch]
|
||||
name = "Fastfetch"
|
||||
category = "misc"
|
||||
|
||||
[templates.fastfetch]
|
||||
input_path = "fastfetch-colors.jsonc"
|
||||
output_path = "$XDG_CONFIG_HOME/fastfetch/themes/noctalia.jsonc"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "56a010cefb7570319d53289c27a99513"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.fcitx5]
|
||||
name = "Fcitx5"
|
||||
category = "system"
|
||||
|
||||
[templates.fcitx5]
|
||||
input_path = "theme.conf"
|
||||
output_path = "$XDG_DATA_HOME/fcitx5/themes/noctalia/theme.conf"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "5b838e0791ee65415c48ad1524f17435"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[catalog.feishin]
|
||||
name = "Feishin"
|
||||
category = "audio"
|
||||
|
||||
[templates.feishin]
|
||||
input_path = "custom.css"
|
||||
output_path = "$XDG_CONFIG_HOME/feishin/custom.css"
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"files": {
|
||||
"README.md": "5273001c9d22560e14e9ab07c580c3e9",
|
||||
"apply.sh": "2cdc7ebbd5d3798fa896b1191214468c",
|
||||
"fuzzel.conf": "ada6c69528e9fd1f32f27a82ba24c9d3",
|
||||
"template.toml": "07c2e5d778a043872eadddea0a2edfa4"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Fuzzel
|
||||
|
||||
Generates Noctalia colors for the Fuzzel launcher, including translucent background and selection colors.
|
||||
|
||||
Enable **Fuzzel** in **Noctalia Settings -> Templates**. The theme is written to `$XDG_CONFIG_HOME/fuzzel/themes/noctalia` (`~/.config/fuzzel/themes/noctalia` by default).
|
||||
|
||||
The Bash post-hook creates or updates `$XDG_CONFIG_HOME/fuzzel/fuzzel.ini` to include the generated theme using an absolute `include=.../fuzzel/themes/noctalia` line. If the exact include is absent, existing lines beginning with `include=` and containing `themes` are replaced; otherwise the include is appended. Other settings are retained.
|
||||
|
||||
Install Fuzzel and back up `fuzzel.ini` first: the hook changes it without creating a backup. No launcher reload command is included.
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
config_dir="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
config_file="$config_dir/fuzzel/fuzzel.ini"
|
||||
include_line="include=$config_dir/fuzzel/themes/noctalia"
|
||||
|
||||
mkdir -p "$(dirname "$config_file")"
|
||||
|
||||
write_if_changed() {
|
||||
local target="$1" tmp="$2"
|
||||
if [ ! -e "$target" ] && [ ! -L "$target" ]; then
|
||||
mv "$tmp" "$target"
|
||||
return
|
||||
fi
|
||||
if ! cmp -s "$target" "$tmp"; then
|
||||
cat "$tmp" >"$target"
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
if [ ! -f "$config_file" ]; then
|
||||
echo "$include_line" >"$config_file"
|
||||
elif grep -q "^$include_line$" "$config_file"; then
|
||||
:
|
||||
elif grep -q '^include=.*themes' "$config_file"; then
|
||||
tmp_file="$(mktemp "${config_file}.tmp.XXXXXX")"
|
||||
sed 's|^include=.*themes.*|'"$include_line"'|' "$config_file" >"$tmp_file"
|
||||
write_if_changed "$config_file" "$tmp_file"
|
||||
else
|
||||
[ -s "$config_file" ] && [ -n "$(tail -c1 "$config_file")" ] && echo >>"$config_file"
|
||||
echo "$include_line" >>"$config_file"
|
||||
fi
|
||||
@@ -0,0 +1,15 @@
|
||||
# Fuzzel Colors
|
||||
# Generated by Noctalia's Template Processor
|
||||
|
||||
[colors]
|
||||
background={{colors.background.default.hex_stripped}}CC
|
||||
text={{colors.on_surface.default.hex_stripped}}ff
|
||||
prompt={{colors.secondary.default.hex_stripped}}ff
|
||||
placeholder={{colors.tertiary.default.hex_stripped}}ff
|
||||
input={{colors.primary.default.hex_stripped}}ff
|
||||
match={{colors.tertiary.default.hex_stripped}}ff
|
||||
selection={{colors.primary.default.hex_stripped}}80
|
||||
selection-text={{colors.on_surface.default.hex_stripped}}ff
|
||||
selection-match={{colors.on_primary.default.hex_stripped}}ff
|
||||
counter={{colors.secondary.default.hex_stripped}}ff
|
||||
border={{colors.primary.default.hex_stripped}}ff
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.fuzzel]
|
||||
name = "Fuzzel"
|
||||
category = "launcher"
|
||||
|
||||
[templates.fuzzel]
|
||||
input_path = "fuzzel.conf"
|
||||
output_path = "$XDG_CONFIG_HOME/fuzzel/themes/noctalia"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "49ef166bf4868c326404dcd1f35120ea"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
[catalog.fzf]
|
||||
name = "fzf"
|
||||
category = "terminal"
|
||||
|
||||
[templates.fzf_bash]
|
||||
input_path = "fzf.sh"
|
||||
output_path = "$XDG_CONFIG_HOME/fzf/themes/noctalia.sh"
|
||||
|
||||
[templates.fzf_fish]
|
||||
input_path = "fzf.fish"
|
||||
output_path = "$XDG_CONFIG_HOME/fzf/themes/noctalia.fish"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"files": {
|
||||
"README.md": "2776c8398f20a6a106c3cddb9b7e1171",
|
||||
"gimp.css": "782d352483659abf7382546573c9d167",
|
||||
"screenshot-preferences.png": "d946d563f7bbebc75c6c202982c790dc",
|
||||
"screenshot.png": "ea41bc5097843dac92792cbd902a3c3b",
|
||||
"template.toml": "e612bf68941874992ce2120e4f0a6455"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# GIMP
|
||||
|
||||
GIMP has its own personal-override CSS hook, separate from the auto-generated `theme.css` that
|
||||
ships with the app (which is regenerated on every theme change and explicitly says not to edit
|
||||
it by hand). This template writes to that personal file directly: `gimp.css`, imported
|
||||
automatically if present, no extra setup needed once the template is enabled.
|
||||
|
||||
## What gets themed, and the two things that needed extra care
|
||||
|
||||
GIMP's own theme only defines 17 named colors (`fg-color`, `bg-color`, `selected-color`, and so
|
||||
on), reused across `common.css`/`common-dark.css`. Most of the UI follows from setting those.
|
||||
Two things needed more than a plain 1:1 color swap:
|
||||
|
||||
- **Context menus and other `GtkPopoverMenu` content had no background rule at all** in GIMP's
|
||||
own theme (only narrow button/list-row styling), so they fell through to GTK's stock light
|
||||
default. Fixed with explicit `popover`/`popover contents` rules.
|
||||
- **`selected-color`/`extreme-selected-color` are always paired with white text** in GIMP's own
|
||||
CSS, with no dark-text variant the way Noctalia's other templates use `on_primary` on top of a
|
||||
`primary`-colored background. Mapping them straight to Noctalia's yellow accent made text
|
||||
unreadable everywhere that yellow shows up (menu hovers, selected list rows, the Preferences
|
||||
sidebar). Fixed by keeping the yellow and adding an explicit dark-text override for every
|
||||
selector GIMP's `common.css` actually uses those two variables as a background for (checked via
|
||||
grep, not guessed).
|
||||
- A few widgets, confirmed just the Preferences dialog's own page title bar, don't use GIMP's
|
||||
custom variables at all. GIMP's own source comment on that exact element admits it "doesn't
|
||||
have any more specific way to style it," meaning it falls back to standard GTK/Adwaita
|
||||
variable names (`@theme_bg_color`, `@theme_selected_bg_color`, etc.) instead. Those are set
|
||||
too, as a safety net, since the system `gtk.css` those would normally come from never loads
|
||||
inside a Flatpak sandbox.
|
||||
|
||||
## Requires GIMP's own "Default" base theme
|
||||
|
||||
GIMP has two selectable base themes (Preferences > Interface > Theme): `Default` and `System`.
|
||||
This template is built against `Default` (`themes/Default/gimp-dark.css`), the one this personal
|
||||
override's own 17 variables and extra selectors are checked against. `System` imports a
|
||||
different, much smaller CSS file with no guarantee it uses the same variable names, not tested
|
||||
or supported here. If colors look wrong after enabling this template, check Preferences first.
|
||||
|
||||
## Native install
|
||||
|
||||
`gimp.css` lives at `~/.config/GIMP/3.2/gimp.css`.
|
||||
|
||||
## Flatpak install (`org.gimp.GIMP`)
|
||||
|
||||
Same file, inside the sandbox's own isolated config: `~/.var/app/org.gimp.GIMP/config/GIMP/3.2/
|
||||
gimp.css`. No `flatpak override` needed, GIMP reads its own config from inside its sandbox
|
||||
regardless of any host `~/.config` access.
|
||||
|
||||
## Testing
|
||||
|
||||
Tested against GIMP 3.2.4 (Flatpak). Verified visually across three passes: main window and
|
||||
toolbox (`screenshot.png`), right-click context menus, and the Preferences dialog specifically
|
||||
(`screenshot-preferences.png`), the hardest case since it touches nearly every one of GIMP's 17
|
||||
variables plus the GTK fallback ones.
|
||||
@@ -0,0 +1,119 @@
|
||||
@define-color fg-color {{colors.on_surface.default.hex}};
|
||||
@define-color bg-color {{colors.surface.default.hex}};
|
||||
@define-color border-color {{colors.outline.default.hex}};
|
||||
@define-color dimmed-fg-color {{colors.on_surface_variant.default.hex}};
|
||||
@define-color disabled-fg-color {{colors.outline_variant.default.hex}};
|
||||
@define-color disabled-button-color {{colors.surface_container_low.default.hex}};
|
||||
@define-color hover-color {{colors.surface_container_high.default.hex}};
|
||||
@define-color widget-bg-color {{colors.surface_container.default.hex}};
|
||||
@define-color selected-color {{colors.primary.default.hex}};
|
||||
@define-color extreme-bg-color {{colors.surface_container_low.default.hex}};
|
||||
@define-color extreme-selected-color {{colors.primary.default.hex}};
|
||||
@define-color strong-border-color {{colors.outline.default.hex}};
|
||||
@define-color stronger-border-color {{colors.outline.default.hex}};
|
||||
@define-color edge-border-color {{colors.outline_variant.default.hex}};
|
||||
@define-color scrollbar-slider-color {{colors.outline.default.hex}};
|
||||
@define-color scrollbar-trough-color {{colors.surface_container.default.hex}};
|
||||
@define-color ruler-color {{colors.outline_variant.default.rgba | set_alpha: 0.3}};
|
||||
|
||||
/* Standard GTK/Adwaita variable names, not GIMP's own. Some widgets
|
||||
(confirmed: the Preferences page title bar, per GIMP's own source
|
||||
comment admitting it "doesn't have any more specific way to style it")
|
||||
fall back to these instead of GIMP's custom palette above. Without
|
||||
this they'd stay unthemed since the system gtk.css never loads inside
|
||||
a Flatpak sandbox. */
|
||||
@define-color theme_bg_color {{colors.surface.default.hex}};
|
||||
@define-color theme_fg_color {{colors.on_surface.default.hex}};
|
||||
@define-color theme_base_color {{colors.surface_container.default.hex}};
|
||||
@define-color theme_text_color {{colors.on_surface.default.hex}};
|
||||
@define-color theme_selected_bg_color {{colors.primary.default.hex}};
|
||||
@define-color theme_selected_fg_color {{colors.on_primary.default.hex}};
|
||||
@define-color borders {{colors.outline.default.hex}};
|
||||
|
||||
/* Most of GIMP's UI reuses selected-color/extreme-selected-color as a full
|
||||
background fill for selection/hover/checked states. Left as bright
|
||||
Noctalia yellow, that fill makes GIMP's own default (light) icon
|
||||
rendering invisible on several widgets, confirmed live and not fixable
|
||||
by recoloring the icon directly (tried extensively: direct color
|
||||
targeting, wildcard inheritance, -gtk-icon-shadow; `filter` isn't even
|
||||
a valid GTK3 CSS property at all, confirmed via a real parse error).
|
||||
|
||||
Real prior art settles this cleanly: community GIMP dark+accent themes
|
||||
(e.g. github.com/bunnywaffle/GIMP-3-Themes, "Black Green Glow") never
|
||||
use a bright accent as a full selection fill either, only as a thin
|
||||
border stripe on top of a still-dark background. Applying that same
|
||||
pattern here: every selector below keeps a dark, subtle background
|
||||
(hover-color) and gets the yellow as a left border accent instead. No
|
||||
per-widget icon or text color override is needed this way, since GIMP's
|
||||
own default text/icon rendering already works fine against a dark
|
||||
background, that's the entire point.
|
||||
|
||||
Uses box-shadow, not a real border: GIMP's own common.css already
|
||||
renders a bottom accent bar this way in several places (e.g. `menubar >
|
||||
menuitem:hover { box-shadow: inset 0 -3px @stronger-border-color; }`),
|
||||
and stronger-border-color is mapped to Noctalia's outline role (a
|
||||
blue-purple tone) elsewhere in this file, which is exactly the stray
|
||||
blue bar seen live alongside an earlier version of this fix that used a
|
||||
real `border` property instead: two separate indicators stacking, not
|
||||
one. Matching GIMP's own mechanism here replaces that blue bar outright
|
||||
instead of adding a second one next to it.
|
||||
|
||||
One deliberate exception, kept as a full yellow fill instead (below):
|
||||
toolbox tool selection. Confirmed working with a full fill plus a dark
|
||||
icon override, and that's the preferred look there specifically. The
|
||||
Preferences category sidebar is a GtkTreeView (confirmed by its expander
|
||||
chevrons), matched by `.view:selected` below, not a GtkListBox `list
|
||||
row`, so it stays with this box-shadow treatment; pulling it out into a
|
||||
full-fill override was tried and also recolored the page's title-bar
|
||||
header the same way (both fall back to the same GTK theme variables),
|
||||
which looked wrong, so left as-is. */
|
||||
.view:selected,
|
||||
.view row:selected,
|
||||
menuitem *:hover,
|
||||
popover list row:selected,
|
||||
combobox button:hover,
|
||||
notebook header button:hover,
|
||||
notebook header tabs tab:checked,
|
||||
GimpDeviceStatus widget:selected,
|
||||
GimpDeviceStatus widget:selected box,
|
||||
button:checked,
|
||||
button.titlebutton:hover,
|
||||
spinbutton button:hover {
|
||||
background-color: {{colors.surface_container_high.default.hex}};
|
||||
background-image: none;
|
||||
color: {{colors.on_surface.default.hex}};
|
||||
border-width: 0;
|
||||
box-shadow: inset 0 -3px {{colors.primary.default.hex}};
|
||||
}
|
||||
|
||||
/* Full yellow fill for the toolbox, matching selected-color's real value
|
||||
(unchanged from GIMP's own base rule, no override needed for the
|
||||
background itself). Text/icon color need the explicit dark override
|
||||
GIMP's own CSS never provides. The small corner triangle marking a tool
|
||||
group (e.g. on the Paintbrush/Pencil/Airbrush group) stays whatever
|
||||
color GIMP draws it: confirmed no dedicated icon asset exists for it
|
||||
anywhere in GIMP's own icon set, so it's a fixed-color overlay drawn
|
||||
directly in GIMP's C code, not a themeable CSS node. */
|
||||
toolbutton button.flat:hover,
|
||||
toolbutton button.flat:checked,
|
||||
toolbutton button.flat:checked:hover {
|
||||
color: {{colors.on_primary.default.hex}};
|
||||
}
|
||||
toolbutton button.flat:checked image,
|
||||
toolbutton button.flat:checked icon {
|
||||
color: {{colors.on_primary.default.hex}};
|
||||
}
|
||||
|
||||
/* GIMP's own theme has no general rule for GtkPopoverMenu backgrounds
|
||||
(only narrow button/list-row styling), so context menus fall through
|
||||
to GTK's stock light default without this. */
|
||||
popover, popover contents, popover.menu, popover.background {
|
||||
background-color: @bg-color;
|
||||
color: @fg-color;
|
||||
}
|
||||
popover modelbutton, popover menuitem {
|
||||
color: @fg-color;
|
||||
}
|
||||
popover modelbutton:hover, popover menuitem:hover {
|
||||
background-color: @extreme-bg-color;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
@@ -0,0 +1,13 @@
|
||||
[catalog.gimp]
|
||||
name = "GIMP"
|
||||
category = "editor"
|
||||
|
||||
[templates.gimp]
|
||||
input_path = "gimp.css"
|
||||
output_path = "~/.config/GIMP/3.2/gimp.css"
|
||||
requires_path = "~/.config/GIMP"
|
||||
|
||||
[templates.gimp-flatpak]
|
||||
input_path = "gimp.css"
|
||||
output_path = "~/.var/app/org.gimp.GIMP/config/GIMP/3.2/gimp.css"
|
||||
requires_path = "~/.var/app/org.gimp.GIMP"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "03732f9df248ab5075647e694192479d"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[catalog.glow]
|
||||
name = "Glow"
|
||||
category = "terminal"
|
||||
|
||||
[templates.glow]
|
||||
input_path = "glow.json"
|
||||
output_path = "$XDG_CONFIG_HOME/glow/noctalia.json"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "bffcacd872da4661aba3a4be3759027d"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.gruvbox-plus-icons]
|
||||
name = "Gruvbox Plus Icon Theme"
|
||||
category = "system"
|
||||
|
||||
[templates.gruvbox_plus_icons]
|
||||
input_path = "colors"
|
||||
output_path = "colors-final"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "4f13dc5fc08a089dad1426a692b45bb4"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.halloy]
|
||||
name = "halloy"
|
||||
category = "chat"
|
||||
|
||||
[templates.halloy]
|
||||
input_path = "halloy.toml"
|
||||
output_path = "$XDG_CONFIG_HOME/halloy/themes/noctalia.toml"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "fcdf331f3b03ce4d352930fbf6539e91"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.herdr]
|
||||
name = "herdr"
|
||||
category = "terminal"
|
||||
|
||||
[templates.herdr]
|
||||
input_path = "herdr-colors.toml"
|
||||
output_path = "$XDG_CONFIG_HOME/herdr/noctalia-colors.toml"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "0af766d5cbf7b20ef059d8f26c04afd4"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[catalog.heroiclauncher]
|
||||
name = "Heroic Launcher"
|
||||
category = "gaming"
|
||||
|
||||
[templates.heroiclauncher]
|
||||
input_path = 'heroic.css'
|
||||
output_path = '$XDG_CONFIG_HOME/heroic/themes/matugen.css'
|
||||
requires_path = '~/.config/heroic'
|
||||
|
||||
[templates.heroiclauncher-flatpak]
|
||||
input_path = 'heroic.css'
|
||||
output_path = '~/.var/app/com.heroicgameslauncher.hgl/config/heroic/themes/matugen.css'
|
||||
requires_path = '~/.var/app/com.heroicgameslauncher.hgl'
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "99b9324b0bdc834bfe71fb85febea677"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[catalog.hyprtoolkit]
|
||||
name = "Hyprtoolkit"
|
||||
category = "system"
|
||||
|
||||
[templates.hyprtoolkit]
|
||||
input_path = "hyprtoolkit.conf"
|
||||
output_path = "$XDG_CONFIG_HOME/hypr/hyprtoolkit.conf"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "4fe75090ad20b8fa348f9409deeb469e"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[catalog.inkscape]
|
||||
name = "Inkscape"
|
||||
category = "editor"
|
||||
|
||||
[templates.inkscape]
|
||||
input_path = "user.css"
|
||||
output_path = "~/.config/inkscape/ui/user.css"
|
||||
requires_path = "~/.config/inkscape"
|
||||
|
||||
[templates.inkscape-flatpak]
|
||||
input_path = "user.css"
|
||||
output_path = "~/.var/app/org.inkscape.Inkscape/config/inkscape/ui/user.css"
|
||||
requires_path = "~/.var/app/org.inkscape.Inkscape"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "e99b61279760be238ac83f299c5d5382"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.jay]
|
||||
name = "Jay"
|
||||
category = "compositor"
|
||||
|
||||
[templates.jay]
|
||||
input_path = "jay.toml"
|
||||
output_path = "$XDG_CACHE_HOME/noctalia/templates/jay-theme.toml"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "e2327271c97a1ab46a8ef7c16a0ef979"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.karere]
|
||||
name = "Karere Custom CSS"
|
||||
category = "chat"
|
||||
|
||||
[templates.karere]
|
||||
input_path = "karere.css"
|
||||
output_path = "$XDG_CONFIG_HOME/karere/custom.css"
|
||||
requires_path = "$XDG_CONFIG_HOME/karere"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "787e3f76d9e2675a05eb6e1bd0bc4496"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[catalog.konsole]
|
||||
name = "Konsole"
|
||||
category = "terminal"
|
||||
|
||||
[templates.konsole]
|
||||
input_path = "noctalia.colorscheme"
|
||||
output_path = "$XDG_DATA_HOME/konsole/noctalia.colorscheme"
|
||||
pre_hook = "bash '{{ config_dir }}/pre-apply.sh'"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "0497bb389ed096b6d40238f68e8d9162"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.lazygit]
|
||||
name = "lazygit"
|
||||
category = "terminal"
|
||||
|
||||
[templates.lazygit]
|
||||
input_path = "lazygit.yml"
|
||||
output_path = "$XDG_CONFIG_HOME/lazygit/themes/noctalia.yml"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "1f5ca395e7fe79bedb37b30bb74babac"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[catalog.lazyvim]
|
||||
name = "LazyVim"
|
||||
category = "editor"
|
||||
|
||||
[templates.lazyvim]
|
||||
input_path = "noctalia.lua"
|
||||
output_path = "$XDG_CONFIG_HOME/nvim/colors/noctalia.lua"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
requires_path = "$XDG_CONFIG_HOME/nvim/lazyvim.json"
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"files": {
|
||||
"Paths.xcu": "f0249a769fed68b4329baf57ac5c1bac",
|
||||
"README.md": "c36760d40cae238078e2c8ceae480730",
|
||||
"Theme_Colors.xcu": "9e3918407865e787a1081059d19187fd",
|
||||
"apply.sh": "79b637c398e457e22e1975169c1f7f2f",
|
||||
"description.xml": "810920710dcde3c1bfe9fb1ea671316c",
|
||||
"light-screenshot.png": "ad688f5dc4feda44ed3da38827165497",
|
||||
"pkg-description.en": "50f53d956476e61f87005bf9399e36f4",
|
||||
"screenshot.png": "8f29907e3b5fd8a6471914503a3c8b2b",
|
||||
"template.toml": "e1da6de79923919b05291dddf6ff5fd0"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Paths" oor:package="org.openoffice.Office">
|
||||
<node oor:name="Paths">
|
||||
<node oor:name="Palette">
|
||||
<node oor:name="InternalPaths">
|
||||
<node oor:name="%origin%/palettes" oor:op="fuse"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</oor:component-data>
|
||||
@@ -0,0 +1,104 @@
|
||||
# LibreOffice
|
||||
|
||||
Tested against LibreOffice 26.2.4.2 (Flatpak, `org.libreoffice.LibreOffice`).
|
||||
|
||||
## Why this ships as an extension, not a rendered config file
|
||||
|
||||
LibreOffice's main window chrome (menus, toolbars, buttons, dialogs) is drawn by its own widget
|
||||
framework, not read from `gtk.css`. Confirmed live: an unmistakable
|
||||
`window { background-color: #ff0000; }` override in
|
||||
`~/.var/app/org.libreoffice.LibreOffice/config/gtk-3.0/gtk.css` had zero effect, even with the
|
||||
GTK3 VCL plugin explicitly forced (`SAL_USE_VCLPLUGIN=gtk3`). LibreOffice's real theming
|
||||
mechanism is its own **ColorScheme** system (Tools > Options > LibreOffice > Application Colors),
|
||||
distributed as an installable `.oxt` extension package, the same format real community themes
|
||||
like [libre-nord](https://github.com/gomesluiz/libre-nord) use.
|
||||
|
||||
## The property list is confirmed against LibreOffice's own source, not guessed
|
||||
|
||||
Every `ColorScheme` property name and its real meaning is confirmed against
|
||||
[`officecfg/registry/schema/org/openoffice/Office/UI.xcs`](https://github.com/LibreOffice/core/blob/master/officecfg/registry/schema/org/openoffice/Office/UI.xcs)
|
||||
in the LibreOffice/core repository, not a partial third-party example. This mattered in practice:
|
||||
`FieldColor`'s own schema description is "Allows to overwrite the system field color", it
|
||||
controls input/dropdown widget backgrounds, not document-embedded field shading the way its name
|
||||
first suggests. An earlier pass mapped it to a literal document-shading color by analogy with a
|
||||
third-party reference theme, and dropdown boxes, the Options sidebar, and text fields stayed on
|
||||
a stock dark color as a result, exactly the kind of "confirmed working" that only turns out to
|
||||
be partially true once someone actually looks closely. Fixed by mapping `FieldColor` to a real
|
||||
Noctalia surface role, then cross-checking the *entire* property list against the schema (several
|
||||
other properties, `DisabledColor`, `ActiveTextColor`, `InactiveColor`, and their pairs, were
|
||||
missing from the theme entirely and are now set too).
|
||||
|
||||
Colors below are hex placeholders in the template source; `Theme_Colors.xcu` uses this schema's
|
||||
own decimal-integer format, not hex, so `apply.sh` converts every value at render time (plain
|
||||
`int(hex, 16)`, confirmed against the Document Foundation's own blog post examples).
|
||||
|
||||
## Document canvas and BASIC editor colors stay literal, deliberately
|
||||
|
||||
Same reasoning as darktable's neutral photo-viewing background: `DocColor`, `FontColor`,
|
||||
`DocBoundaries`, `CalcGrid`, and the BASIC IDE syntax-highlighting colors are kept as sensible
|
||||
literal light/dark values regardless of how dark the surrounding chrome is. A document is still
|
||||
meant to look like a normal page (or be printed), and code syntax highlighting needs
|
||||
distinguishable, conventional colors (keywords, strings, comments), not four or five UI accent
|
||||
roles stretched over a dozen token types. These are functional, not chrome.
|
||||
|
||||
## Real gotchas found building this, not theoretical
|
||||
|
||||
- **The scheme has to be selected manually, once.** Installing the extension registers "Noctalia"
|
||||
as an available option in the Scheme dropdown, it does not auto-select it. Confirmed live: same
|
||||
behavior class as darktable's own theme dropdown. Go to Tools > Options > LibreOffice >
|
||||
Application Colors, pick "Noctalia" from the Scheme dropdown, click Apply/OK. After that one
|
||||
manual step, every later theme change re-renders and reinstalls the extension automatically
|
||||
through Noctalia's own template pipeline, no further manual selection needed.
|
||||
- **A restart is needed to see updated colors**, same as Heroic's own documented limitation.
|
||||
Confirmed live: switching Noctalia's theme mode while LibreOffice was already open did not
|
||||
change the running window at all; closing and reopening it did. This is not a bug in the
|
||||
template, extensions are loaded at LibreOffice startup.
|
||||
- **`unopkg add --force` alone is not reliable for reinstalling the same extension identifier.**
|
||||
Confirmed live, the hard way: after several reinstalls it left the extension in a broken state,
|
||||
`unopkg list` reported nothing installed at all, while a stale binary cache index
|
||||
(`uno_packages/cache/uno_packages.pmap`) still pointed at a deleted temp directory, causing
|
||||
every subsequent install attempt to fail with "file opening ... NOT_EXISTING" until the whole
|
||||
cache directory was cleared by hand. `apply.sh` now explicitly `unopkg remove`s the extension
|
||||
identifier before every `add`, ignoring failure since it may not be installed yet, rather than
|
||||
relying on `--force` to handle that atomically.
|
||||
- **`unopkg add` while LibreOffice is running can corrupt the install the same way.** `apply.sh`
|
||||
checks for a running `soffice.bin` process first and skips the install step entirely if found,
|
||||
rather than risk it, the `.oxt` is still rebuilt with the current colors either way, so the next
|
||||
render (once LibreOffice is closed) or the next manual re-apply installs them, and a restart is
|
||||
already required regardless.
|
||||
- **`unopkg` is not on the sandbox's `PATH`** inside the Flatpak. Confirmed live:
|
||||
`flatpak run --command=unopkg ...` fails with "No such file or directory", the full path
|
||||
`/app/libreoffice/program/unopkg` is required.
|
||||
- **If LibreOffice was open at the exact moment the theme changed, the install-skip above has no
|
||||
automatic retry.** The `.oxt` still gets rebuilt with the current colors every render, but
|
||||
since the install step is skipped while LibreOffice is running, closing LibreOffice alone is
|
||||
not enough, nothing re-triggers the install afterward on its own. Confirmed live: after
|
||||
changing the palette while LibreOffice was open, colors stayed stale even after closing and
|
||||
reopening it, until `apply.sh` was run again by hand with LibreOffice closed. In practice this
|
||||
means a color change made while LibreOffice happens to be open may need the theme re-applied
|
||||
once more (`noctalia msg templates-apply`) after closing it, not just a restart.
|
||||
|
||||
## Native install
|
||||
|
||||
Same `unopkg` mechanism, invoked directly. `apply.sh` resolves `unopkg` from `PATH` first, then
|
||||
falls back to the official TDF install layout (`/opt/libreoffice*/program/unopkg`,
|
||||
`/usr/lib/libreoffice/program/unopkg`, `/usr/lib64/libreoffice/program/unopkg`) so the official
|
||||
`.deb`/`.rpm` packages, which do **not** put `unopkg` on `PATH`, are detected too. If no native
|
||||
`unopkg` is found it falls back to the Flatpak `flatpak run --command=` form.
|
||||
|
||||
**Verified live** against LibreOffice 26.2.4.2 from the official TDF `.deb` packages on
|
||||
Kali Linux (amd64), including a clean-PATH run where `command -v unopkg` returned nothing and
|
||||
`/opt/libreoffice26.2/program/unopkg` was picked up by the fallback; the extension installed
|
||||
and registered correctly.
|
||||
|
||||
## Flatpak install (`org.libreoffice.LibreOffice`)
|
||||
|
||||
Extension cache lives at
|
||||
`~/.var/app/org.libreoffice.LibreOffice/config/libreoffice/4/user/uno_packages/`. No
|
||||
`flatpak override` needed.
|
||||
|
||||
## Status
|
||||
|
||||
Verified live against LibreOffice 26.2.4.2 (Flatpak) through Noctalia's own real render pipeline,
|
||||
`community_ids` + local `community-templates/libreoffice/`, both dark and light mode, confirmed
|
||||
after a restart in each case. Native install path is implemented but not live-tested.
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Colors below are hex placeholders, {{ config_dir }}/apply.sh converts them to the decimal
|
||||
integers this schema actually requires (standard int(hex, 16) RRGGBB conversion, confirmed
|
||||
against LibreOffice/core's own officecfg/registry/schema/org/openoffice/Office/UI.xcs, the
|
||||
authoritative source for every ColorScheme property name and description used below,
|
||||
including FieldColor, which really does control input-widget backgrounds despite its name
|
||||
reading like a document-field-shading setting at first glance). Chrome roles map to Noctalia
|
||||
colors. Document/BASIC-editor colors stay literal, legible regardless of chrome darkness,
|
||||
same reasoning as darktable's neutral photo-viewing background: these are functional, not
|
||||
chrome. -->
|
||||
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" oor:name="UI" oor:package="org.openoffice.Office">
|
||||
<node oor:name="ColorScheme">
|
||||
<node oor:name="ColorSchemes">
|
||||
<node oor:name="Noctalia" oor:op="fuse">
|
||||
<node oor:name="AppBackground"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="DocColor"><prop oor:name="Color" oor:op="fuse"><value>f7f7fa</value></prop></node>
|
||||
<node oor:name="FontColor"><prop oor:name="Color" oor:op="fuse"><value>1a1a1a</value></prop></node>
|
||||
<node oor:name="DocBoundaries"><prop oor:name="Color" oor:op="fuse"><value>cccccc</value></prop></node>
|
||||
|
||||
<node oor:name="WindowColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="WindowTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_surface.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="BaseColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="ButtonColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface_container_high.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="ButtonTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_surface.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="AccentColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="DisabledColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.outline_variant.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="DisabledTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_surface_variant.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="ShadowColor"><prop oor:name="Color" oor:op="fuse"><value>808080</value></prop></node>
|
||||
<node oor:name="Shadow"><prop oor:name="Color" oor:op="fuse"><value xsi:nil="false" /></prop><prop oor:name="IsVisible" oor:op="fuse"><value>false</value></prop></node>
|
||||
<node oor:name="SeparatorColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.outline_variant.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="FaceColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface_container.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="ActiveColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="ActiveTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="ActiveBorderColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="FieldColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface_container_high.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuBarColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface_container.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuBarTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_surface.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuBarHighlightColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuBarHighlightTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface_container.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_surface.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuHighlightColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuHighlightTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_primary.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="MenuBorderColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.outline.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="InactiveColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.surface_container.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="InactiveTextColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.on_surface_variant.default.hex_stripped}}</value></prop></node>
|
||||
<node oor:name="InactiveBorderColor"><prop oor:name="Color" oor:op="fuse"><value>{{colors.outline_variant.default.hex_stripped}}</value></prop></node>
|
||||
|
||||
<node oor:name="BASICEditor"><prop oor:name="Color" oor:op="fuse"><value>ffffff</value></prop></node>
|
||||
<node oor:name="BASICError"><prop oor:name="Color" oor:op="fuse"><value>d32f2f</value></prop></node>
|
||||
<node oor:name="BASICIdentifier"><prop oor:name="Color" oor:op="fuse"><value>1a1a1a</value></prop></node>
|
||||
<node oor:name="BASICKeyword"><prop oor:name="Color" oor:op="fuse"><value>0b57d0</value></prop></node>
|
||||
<node oor:name="BASICNumber"><prop oor:name="Color" oor:op="fuse"><value>d97706</value></prop></node>
|
||||
<node oor:name="BASICOperator"><prop oor:name="Color" oor:op="fuse"><value>444444</value></prop></node>
|
||||
<node oor:name="BASICString"><prop oor:name="Color" oor:op="fuse"><value>15803d</value></prop></node>
|
||||
<node oor:name="BASICComment"><prop oor:name="Color" oor:op="fuse"><value>6b7280</value></prop></node>
|
||||
|
||||
<node oor:name="WriterIdxShadings"><prop oor:name="Color" oor:op="fuse"><value>e8e8e8</value></prop><prop oor:name="IsVisible" oor:op="fuse"><value>true</value></prop></node>
|
||||
<node oor:name="WriterFieldShadings"><prop oor:name="Color" oor:op="fuse"><value>e8e8e8</value></prop><prop oor:name="IsVisible" oor:op="fuse"><value>true</value></prop></node>
|
||||
<node oor:name="CalcGrid"><prop oor:name="Color" oor:op="fuse"><value>d9d9d9</value></prop></node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</oor:component-data>
|
||||
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env bash
|
||||
# Runs on every theme change (post_hook). Converts the rendered Theme_Colors.xcu's
|
||||
# hex color values to the decimal integers LibreOffice's ColorScheme schema
|
||||
# actually requires, assembles a fresh .oxt from this directory's static files
|
||||
# plus the converted colors, and installs it via unopkg.
|
||||
set -euo pipefail
|
||||
|
||||
CONFIG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
RENDERED="${XDG_STATE_HOME:-$HOME/.local/state}/noctalia/libreoffice-theme-staging/Theme_Colors.xcu"
|
||||
BUILD_DIR="$CONFIG_DIR/build"
|
||||
OXT_PATH="$BUILD_DIR/noctalia-theme.oxt"
|
||||
|
||||
if [ ! -f "$RENDERED" ]; then
|
||||
echo "noctalia libreoffice: rendered Theme_Colors.xcu not found at $RENDERED" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf "$BUILD_DIR/pkg"
|
||||
mkdir -p "$BUILD_DIR/pkg/META-INF"
|
||||
|
||||
# Convert every 6-hex-digit <value>...</value> to its decimal equivalent.
|
||||
# ColorScheme's schema stores colors as base-10 integers, not hex strings.
|
||||
python3 - "$RENDERED" "$BUILD_DIR/pkg/Theme_Colors.xcu" << 'PYEOF'
|
||||
import re
|
||||
import sys
|
||||
|
||||
src, dst = sys.argv[1], sys.argv[2]
|
||||
with open(src) as f:
|
||||
content = f.read()
|
||||
|
||||
|
||||
def hex_to_dec(match):
|
||||
return f"<value>{int(match.group(1), 16)}</value>"
|
||||
|
||||
|
||||
converted = re.sub(r"<value>([0-9a-fA-F]{6})</value>", hex_to_dec, content)
|
||||
with open(dst, "w") as f:
|
||||
f.write(converted)
|
||||
PYEOF
|
||||
|
||||
cp "$CONFIG_DIR/Paths.xcu" "$BUILD_DIR/pkg/Paths.xcu"
|
||||
cp "$CONFIG_DIR/description.xml" "$BUILD_DIR/pkg/description.xml"
|
||||
cp "$CONFIG_DIR/pkg-description.en" "$BUILD_DIR/pkg/pkg-description.en"
|
||||
|
||||
# Write the package manifest inline rather than copying it from the template directory.
|
||||
# The template distribution pipeline only ships top-level files, so the
|
||||
# META-INF/manifest.xml that used to live here was never delivered to users and
|
||||
# the previous `cp` aborted under set -euo pipefail before the .oxt was built.
|
||||
# The manifest is static and small, so generating it here keeps the template
|
||||
# self-contained and removes the only subdirectory dependency.
|
||||
cat > "$BUILD_DIR/pkg/META-INF/manifest.xml" <<'MANIFEST'
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
|
||||
<manifest:file-entry manifest:full-path="Theme_Colors.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
|
||||
<manifest:file-entry manifest:full-path="Paths.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
|
||||
</manifest:manifest>
|
||||
MANIFEST
|
||||
|
||||
rm -f "$OXT_PATH"
|
||||
(cd "$BUILD_DIR/pkg" && zip -qr "$OXT_PATH" .)
|
||||
|
||||
# unopkg add --force while LibreOffice is running has been confirmed live to
|
||||
# silently corrupt the install (it can remove the old registration before
|
||||
# failing to add the new one, leaving nothing installed at all). Skip the
|
||||
# install step entirely rather than risk that -- the .oxt is still rebuilt
|
||||
# above so the next run (once LibreOffice is closed) installs the current
|
||||
# colors, and a restart is already required to see any change regardless.
|
||||
if pgrep -x soffice.bin >/dev/null 2>&1; then
|
||||
# The .oxt above is already rebuilt with the current colors, only the
|
||||
# install step is skipped here. A restart alone does NOT pick up anything
|
||||
# new, the previously-installed extension is still what's registered.
|
||||
# Close LibreOffice, then re-run the theme apply (or wait for the next
|
||||
# theme change) to actually install this build.
|
||||
echo "noctalia libreoffice: LibreOffice is running, skipping extension install this run (installing while it's open has been confirmed to corrupt the existing install). Close LibreOffice, then re-apply the theme to actually install these colors, a restart alone will not pick them up." >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
EXT_ID="dev.noctalia.libreoffice.theme"
|
||||
INSTALLED_ANY=0
|
||||
|
||||
# `add --force` alone has been confirmed live to leave the extension in a
|
||||
# broken state (a stale cache index pointing at a deleted temp dir, `list`
|
||||
# then reports nothing installed at all, and every later reinstall fails
|
||||
# with "file opening ... NOT_EXISTING" until the cache is cleared by hand).
|
||||
# Explicitly removing the old registration first, ignoring failure since it
|
||||
# may not be installed yet, avoids relying on --force to do that atomically.
|
||||
|
||||
# Install to every LibreOffice found, not just whichever `unopkg` a plain
|
||||
# PATH lookup happens to resolve first. A machine with both a native
|
||||
# LibreOffice (providing `unopkg` on PATH) and the Flatpak (the tested
|
||||
# target) installed would otherwise only get themed on whichever one won
|
||||
# that lookup, silently leaving the other one unthemed.
|
||||
#
|
||||
# Native detection here also covers the official TDF `.deb`/`.rpm` layout,
|
||||
# which installs into /opt/libreoffice<major>.<minor>/ and does NOT place
|
||||
# `unopkg` on PATH. `command -v unopkg` alone misses it, so fall back to the
|
||||
# known install dirs before concluding there is no native install.
|
||||
UNOPKG="$(command -v unopkg || true)"
|
||||
if [ -z "$UNOPKG" ]; then
|
||||
for candidate in /opt/libreoffice*/program/unopkg \
|
||||
/usr/lib/libreoffice/program/unopkg \
|
||||
/usr/lib64/libreoffice/program/unopkg; do
|
||||
if [ -x "$candidate" ]; then
|
||||
UNOPKG="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "$UNOPKG" ]; then
|
||||
"$UNOPKG" remove "$EXT_ID" >/dev/null 2>&1 || true
|
||||
if "$UNOPKG" add --force "$OXT_PATH" 2>&1; then
|
||||
INSTALLED_ANY=1
|
||||
else
|
||||
echo "noctalia libreoffice: native unopkg install failed ($UNOPKG)" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
if flatpak info org.libreoffice.LibreOffice >/dev/null 2>&1; then
|
||||
flatpak run --command=/app/libreoffice/program/unopkg org.libreoffice.LibreOffice remove "$EXT_ID" >/dev/null 2>&1 || true
|
||||
if flatpak run --command=/app/libreoffice/program/unopkg org.libreoffice.LibreOffice add --force "$OXT_PATH" 2>&1; then
|
||||
INSTALLED_ANY=1
|
||||
else
|
||||
echo "noctalia libreoffice: Flatpak unopkg install failed" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$INSTALLED_ANY" -eq 0 ]; then
|
||||
echo "noctalia libreoffice: no LibreOffice installation found (neither native unopkg on PATH nor the org.libreoffice.LibreOffice Flatpak)" >&2
|
||||
fi
|
||||
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
|
||||
<manifest:file-entry manifest:full-path="Theme_Colors.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
|
||||
<manifest:file-entry manifest:full-path="Paths.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
|
||||
</manifest:manifest>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Paths" oor:package="org.openoffice.Office">
|
||||
<node oor:name="Paths">
|
||||
<node oor:name="Palette">
|
||||
<node oor:name="InternalPaths">
|
||||
<node oor:name="%origin%/palettes" oor:op="fuse"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</oor:component-data>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Colors below are hex placeholders, /home/yuri/.local/state/noctalia/community-templates/libreoffice/apply.sh converts them to the decimal
|
||||
integers this schema actually requires (standard int(hex, 16) RRGGBB conversion, confirmed
|
||||
against LibreOffice/core's own officecfg/registry/schema/org/openoffice/Office/UI.xcs, the
|
||||
authoritative source for every ColorScheme property name and description used below,
|
||||
including FieldColor, which really does control input-widget backgrounds despite its name
|
||||
reading like a document-field-shading setting at first glance). Chrome roles map to Noctalia
|
||||
colors. Document/BASIC-editor colors stay literal, legible regardless of chrome darkness,
|
||||
same reasoning as darktable's neutral photo-viewing background: these are functional, not
|
||||
chrome. -->
|
||||
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" oor:name="UI" oor:package="org.openoffice.Office">
|
||||
<node oor:name="ColorScheme">
|
||||
<node oor:name="ColorSchemes">
|
||||
<node oor:name="Noctalia" oor:op="fuse">
|
||||
<node oor:name="AppBackground"><prop oor:name="Color" oor:op="fuse"><value>1250068</value></prop></node>
|
||||
<node oor:name="DocColor"><prop oor:name="Color" oor:op="fuse"><value>16250874</value></prop></node>
|
||||
<node oor:name="FontColor"><prop oor:name="Color" oor:op="fuse"><value>1710618</value></prop></node>
|
||||
<node oor:name="DocBoundaries"><prop oor:name="Color" oor:op="fuse"><value>13421772</value></prop></node>
|
||||
|
||||
<node oor:name="WindowColor"><prop oor:name="Color" oor:op="fuse"><value>1250068</value></prop></node>
|
||||
<node oor:name="WindowTextColor"><prop oor:name="Color" oor:op="fuse"><value>15000290</value></prop></node>
|
||||
<node oor:name="BaseColor"><prop oor:name="Color" oor:op="fuse"><value>1250068</value></prop></node>
|
||||
<node oor:name="ButtonColor"><prop oor:name="Color" oor:op="fuse"><value>2763306</value></prop></node>
|
||||
<node oor:name="ButtonTextColor"><prop oor:name="Color" oor:op="fuse"><value>15000290</value></prop></node>
|
||||
<node oor:name="AccentColor"><prop oor:name="Color" oor:op="fuse"><value>12568530</value></prop></node>
|
||||
<node oor:name="DisabledColor"><prop oor:name="Color" oor:op="fuse"><value>4474699</value></prop></node>
|
||||
<node oor:name="DisabledTextColor"><prop oor:name="Color" oor:op="fuse"><value>12961483</value></prop></node>
|
||||
<node oor:name="ShadowColor"><prop oor:name="Color" oor:op="fuse"><value>8421504</value></prop></node>
|
||||
<node oor:name="Shadow"><prop oor:name="Color" oor:op="fuse"><value xsi:nil="false" /></prop><prop oor:name="IsVisible" oor:op="fuse"><value>false</value></prop></node>
|
||||
<node oor:name="SeparatorColor"><prop oor:name="Color" oor:op="fuse"><value>4474699</value></prop></node>
|
||||
<node oor:name="FaceColor"><prop oor:name="Color" oor:op="fuse"><value>2039584</value></prop></node>
|
||||
<node oor:name="ActiveColor"><prop oor:name="Color" oor:op="fuse"><value>12568530</value></prop></node>
|
||||
<node oor:name="ActiveTextColor"><prop oor:name="Color" oor:op="fuse"><value>2699577</value></prop></node>
|
||||
<node oor:name="ActiveBorderColor"><prop oor:name="Color" oor:op="fuse"><value>12568530</value></prop></node>
|
||||
<node oor:name="FieldColor"><prop oor:name="Color" oor:op="fuse"><value>2763306</value></prop></node>
|
||||
<node oor:name="MenuBarColor"><prop oor:name="Color" oor:op="fuse"><value>2039584</value></prop></node>
|
||||
<node oor:name="MenuBarTextColor"><prop oor:name="Color" oor:op="fuse"><value>15000290</value></prop></node>
|
||||
<node oor:name="MenuBarHighlightColor"><prop oor:name="Color" oor:op="fuse"><value>12568530</value></prop></node>
|
||||
<node oor:name="MenuBarHighlightTextColor"><prop oor:name="Color" oor:op="fuse"><value>2699577</value></prop></node>
|
||||
<node oor:name="MenuColor"><prop oor:name="Color" oor:op="fuse"><value>2039584</value></prop></node>
|
||||
<node oor:name="MenuTextColor"><prop oor:name="Color" oor:op="fuse"><value>15000290</value></prop></node>
|
||||
<node oor:name="MenuHighlightColor"><prop oor:name="Color" oor:op="fuse"><value>12568530</value></prop></node>
|
||||
<node oor:name="MenuHighlightTextColor"><prop oor:name="Color" oor:op="fuse"><value>2699577</value></prop></node>
|
||||
<node oor:name="MenuBorderColor"><prop oor:name="Color" oor:op="fuse"><value>9343381</value></prop></node>
|
||||
<node oor:name="InactiveColor"><prop oor:name="Color" oor:op="fuse"><value>2039584</value></prop></node>
|
||||
<node oor:name="InactiveTextColor"><prop oor:name="Color" oor:op="fuse"><value>12961483</value></prop></node>
|
||||
<node oor:name="InactiveBorderColor"><prop oor:name="Color" oor:op="fuse"><value>4474699</value></prop></node>
|
||||
|
||||
<node oor:name="BASICEditor"><prop oor:name="Color" oor:op="fuse"><value>16777215</value></prop></node>
|
||||
<node oor:name="BASICError"><prop oor:name="Color" oor:op="fuse"><value>13840175</value></prop></node>
|
||||
<node oor:name="BASICIdentifier"><prop oor:name="Color" oor:op="fuse"><value>1710618</value></prop></node>
|
||||
<node oor:name="BASICKeyword"><prop oor:name="Color" oor:op="fuse"><value>743376</value></prop></node>
|
||||
<node oor:name="BASICNumber"><prop oor:name="Color" oor:op="fuse"><value>14251782</value></prop></node>
|
||||
<node oor:name="BASICOperator"><prop oor:name="Color" oor:op="fuse"><value>4473924</value></prop></node>
|
||||
<node oor:name="BASICString"><prop oor:name="Color" oor:op="fuse"><value>1409085</value></prop></node>
|
||||
<node oor:name="BASICComment"><prop oor:name="Color" oor:op="fuse"><value>7041664</value></prop></node>
|
||||
|
||||
<node oor:name="WriterIdxShadings"><prop oor:name="Color" oor:op="fuse"><value>15263976</value></prop><prop oor:name="IsVisible" oor:op="fuse"><value>true</value></prop></node>
|
||||
<node oor:name="WriterFieldShadings"><prop oor:name="Color" oor:op="fuse"><value>15263976</value></prop><prop oor:name="IsVisible" oor:op="fuse"><value>true</value></prop></node>
|
||||
<node oor:name="CalcGrid"><prop oor:name="Color" oor:op="fuse"><value>14277081</value></prop></node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</oor:component-data>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<description xmlns="http://openoffice.org/extensions/description/2006"
|
||||
xmlns:d="http://openoffice.org/extensions/description/2006"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<identifier value="dev.noctalia.libreoffice.theme" />
|
||||
<version value="1.0.0" />
|
||||
<publisher>
|
||||
<name xlink:href="https://github.com/noctalia-dev/community-templates" lang="en">Noctalia</name>
|
||||
</publisher>
|
||||
<display-name>
|
||||
<name lang="en">Noctalia Theme</name>
|
||||
</display-name>
|
||||
<extension-description>
|
||||
<src xlink:href="pkg-description.en" lang="en" />
|
||||
</extension-description>
|
||||
</description>
|
||||
@@ -0,0 +1,2 @@
|
||||
Colors LibreOffice's application chrome (menus, toolbars, buttons, dialogs) to match the active
|
||||
Noctalia palette. Installed and kept in sync automatically by Noctalia's own template pipeline.
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<description xmlns="http://openoffice.org/extensions/description/2006"
|
||||
xmlns:d="http://openoffice.org/extensions/description/2006"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<identifier value="dev.noctalia.libreoffice.theme" />
|
||||
<version value="1.0.0" />
|
||||
<publisher>
|
||||
<name xlink:href="https://github.com/noctalia-dev/community-templates" lang="en">Noctalia</name>
|
||||
</publisher>
|
||||
<display-name>
|
||||
<name lang="en">Noctalia Theme</name>
|
||||
</display-name>
|
||||
<extension-description>
|
||||
<src xlink:href="pkg-description.en" lang="en" />
|
||||
</extension-description>
|
||||
</description>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
@@ -0,0 +1,2 @@
|
||||
Colors LibreOffice's application chrome (menus, toolbars, buttons, dialogs) to match the active
|
||||
Noctalia palette. Installed and kept in sync automatically by Noctalia's own template pipeline.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@@ -0,0 +1,8 @@
|
||||
[catalog.libreoffice]
|
||||
name = "LibreOffice"
|
||||
category = "editor"
|
||||
|
||||
[templates.libreoffice]
|
||||
input_path = "Theme_Colors.xcu"
|
||||
output_path = "$XDG_STATE_HOME/noctalia/libreoffice-theme-staging/Theme_Colors.xcu"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files": {
|
||||
"template.toml": "73d384d321a6f561082a439d8ef474ab"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[catalog.lsd]
|
||||
name = "lsd"
|
||||
category = "terminal"
|
||||
|
||||
[templates.lsd]
|
||||
input_path = "colors.yaml"
|
||||
output_path = "$XDG_CONFIG_HOME/lsd/colors.yaml"
|
||||
post_hook = "bash '{{ config_dir }}/apply.sh'"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user