From 578e71442e7bba3d5b64c44522b86e42304b3c30 Mon Sep 17 00:00:00 2001 From: Norm Rasmussen Date: Tue, 14 Apr 2026 20:20:41 -0400 Subject: [PATCH] untested, just committing to save everything. --- .DS_Store | Bin 0 -> 6148 bytes LICENSE | 21 + README.md | 178 ++++++ groups.lua | 556 ++++++++++++++++++ init.lua | 130 ++++ .../n8n.nvim/lua/lualine/themes/n8n.lua | 55 ++ n8n.lua | 1 + palette.lua | 151 +++++ theme.lua | 118 ++++ 9 files changed, 1210 insertions(+) create mode 100644 .DS_Store create mode 100644 LICENSE create mode 100644 README.md create mode 100644 groups.lua create mode 100644 init.lua create mode 100644 mnt/user-data/outputs/n8n.nvim/lua/lualine/themes/n8n.lua create mode 100644 n8n.lua create mode 100644 palette.lua create mode 100644 theme.lua diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + on_highlights = function(highlights, colors) end, + ---@type fun(colors: table): table + on_colors = function(colors) return colors end, +} + +---@param opts? N8nConfig +function M.setup(opts) + M.config = vim.tbl_deep_extend("force", M.config, opts or {}) +end + +function M.load() + if vim.g.colors_name then + vim.cmd("hi clear") + end + if vim.fn.exists("syntax_on") then + vim.cmd("syntax reset") + end + + vim.o.termguicolors = true + vim.g.colors_name = "n8n" + vim.o.background = "dark" + + local theme = require("n8n.theme") + local groups_mod = require("n8n.groups") + local c = theme.colors() + + -- Let user modify colors + if type(M.config.on_colors) == "function" then + local custom = M.config.on_colors(c) + if custom then + c = vim.tbl_deep_extend("force", c, custom) + end + end + + -- Handle transparent mode + if M.config.transparent then + c.bg = "NONE" + c.bg_sidebar = "NONE" + c.bg_float = "NONE" + end + + local groups = groups_mod.setup({ colors = c }) + + -- Apply style overrides + if M.config.styles.comments then + groups.Comment = vim.tbl_extend("force", groups.Comment or {}, M.config.styles.comments) + groups["@comment"] = vim.tbl_extend("force", groups["@comment"] or {}, M.config.styles.comments) + end + if M.config.styles.keywords then + for _, key in ipairs({ "Keyword", "Statement", "Conditional", "Repeat", "@keyword" }) do + if groups[key] then + groups[key] = vim.tbl_extend("force", groups[key], M.config.styles.keywords) + end + end + end + if M.config.styles.functions then + for _, key in ipairs({ "Function", "@function", "@function.call" }) do + if groups[key] then + groups[key] = vim.tbl_extend("force", groups[key], M.config.styles.functions) + end + end + end + if M.config.styles.strings then + for _, key in ipairs({ "String", "@string" }) do + if groups[key] then + groups[key] = vim.tbl_extend("force", groups[key], M.config.styles.strings) + end + end + end + if M.config.styles.variables then + for _, key in ipairs({ "Identifier", "@variable" }) do + if groups[key] then + groups[key] = vim.tbl_extend("force", groups[key], M.config.styles.variables) + end + end + end + + -- Dim inactive windows + if M.config.dim_inactive then + groups.NormalNC = { fg = c.fg_dark, bg = c.bg_dark } + end + + -- Let user modify highlights + if type(M.config.on_highlights) == "function" then + M.config.on_highlights(groups, c) + end + + -- Apply all highlight groups + for group, hl in pairs(groups) do + vim.api.nvim_set_hl(0, group, hl) + end + + -- Set terminal colors + if M.config.terminal_colors then + local t = theme.colors().terminal + vim.g.terminal_color_0 = t.black + vim.g.terminal_color_1 = t.red + vim.g.terminal_color_2 = t.green + vim.g.terminal_color_3 = t.yellow + vim.g.terminal_color_4 = t.blue + vim.g.terminal_color_5 = t.magenta + vim.g.terminal_color_6 = t.cyan + vim.g.terminal_color_7 = t.white + vim.g.terminal_color_8 = t.bright_black + vim.g.terminal_color_9 = t.bright_red + vim.g.terminal_color_10 = t.bright_green + vim.g.terminal_color_11 = t.bright_yellow + vim.g.terminal_color_12 = t.bright_blue + vim.g.terminal_color_13 = t.bright_magenta + vim.g.terminal_color_14 = t.bright_cyan + vim.g.terminal_color_15 = t.bright_white + end +end + +return M diff --git a/mnt/user-data/outputs/n8n.nvim/lua/lualine/themes/n8n.lua b/mnt/user-data/outputs/n8n.nvim/lua/lualine/themes/n8n.lua new file mode 100644 index 0000000..8fc8b0d --- /dev/null +++ b/mnt/user-data/outputs/n8n.nvim/lua/lualine/themes/n8n.lua @@ -0,0 +1,55 @@ +local palette = require("n8n.palette") + +local n8n = {} + +local c = { + bg = palette.neutral_950, + bg_light = palette.neutral_900, + fg = palette.neutral_200, + fg_dim = palette.neutral_500, + accent = palette.orange_300, + green = palette.green_500, + blue = palette.blue_400, + purple = palette.purple_500, + red = palette.red_500, + yellow = palette.yellow_500, +} + +n8n.normal = { + a = { bg = c.accent, fg = c.bg, gui = "bold" }, + b = { bg = c.bg_light, fg = c.accent }, + c = { bg = c.bg, fg = c.fg_dim }, +} + +n8n.insert = { + a = { bg = c.green, fg = c.bg, gui = "bold" }, + b = { bg = c.bg_light, fg = c.green }, +} + +n8n.visual = { + a = { bg = c.purple, fg = c.bg, gui = "bold" }, + b = { bg = c.bg_light, fg = c.purple }, +} + +n8n.replace = { + a = { bg = c.red, fg = c.bg, gui = "bold" }, + b = { bg = c.bg_light, fg = c.red }, +} + +n8n.command = { + a = { bg = c.yellow, fg = c.bg, gui = "bold" }, + b = { bg = c.bg_light, fg = c.yellow }, +} + +n8n.terminal = { + a = { bg = c.blue, fg = c.bg, gui = "bold" }, + b = { bg = c.bg_light, fg = c.blue }, +} + +n8n.inactive = { + a = { bg = c.bg, fg = c.fg_dim }, + b = { bg = c.bg, fg = c.fg_dim }, + c = { bg = c.bg, fg = c.fg_dim }, +} + +return n8n diff --git a/n8n.lua b/n8n.lua new file mode 100644 index 0000000..8fb9924 --- /dev/null +++ b/n8n.lua @@ -0,0 +1 @@ +require("n8n").load() diff --git a/palette.lua b/palette.lua new file mode 100644 index 0000000..d1ced87 --- /dev/null +++ b/palette.lua @@ -0,0 +1,151 @@ +---@class N8nPalette +local M = {} + +-- n8n Design System palette +-- Extracted from the official n8n dark theme CSS custom properties + +-- Neutrals (the backbone of n8n's dark UI) +M.neutral_white = "#ffffff" +M.neutral_50 = "#fcfcfc" +M.neutral_100 = "#f9f9f9" +M.neutral_125 = "#f5f5f5" +M.neutral_150 = "#ededed" +M.neutral_200 = "#e0e0e0" +M.neutral_250 = "#cccccc" +M.neutral_300 = "#adadad" +M.neutral_400 = "#949494" +M.neutral_500 = "#828282" +M.neutral_600 = "#757575" +M.neutral_700 = "#4d4d4d" +M.neutral_750 = "#424242" +M.neutral_800 = "#3d3d3d" +M.neutral_850 = "#2b2b2b" +M.neutral_900 = "#212121" +M.neutral_950 = "#171717" +M.neutral_black = "#000000" + +-- Orange (n8n's brand accent in dark mode) +M.orange_50 = "#fff6f5" +M.orange_100 = "#ffe8e6" +M.orange_150 = "#ffdfdb" +M.orange_200 = "#ffc9c2" +M.orange_250 = "#ff9c8f" +M.orange_300 = "#ff6f5c" +M.orange_400 = "#ff4b33" +M.orange_500 = "#ff1e00" +M.orange_600 = "#cc1800" +M.orange_700 = "#991200" +M.orange_800 = "#660c00" +M.orange_900 = "#330600" +M.orange_950 = "#1a0300" + +-- Purple (used for pinned nodes, code syntax, accents) +M.purple_50 = "#f8f7fc" +M.purple_100 = "#edecf8" +M.purple_200 = "#e6e4f6" +M.purple_300 = "#c3bee9" +M.purple_400 = "#a098dc" +M.purple_500 = "#7d72cf" +M.purple_600 = "#5a4cc2" +M.purple_700 = "#4438a3" +M.purple_800 = "#3b308d" +M.purple_900 = "#302772" +M.purple_950 = "#211b50" + +-- Green (success states, boolean/number syntax) +M.green_50 = "#ebfaf1" +M.green_100 = "#d6f5e3" +M.green_200 = "#adebc7" +M.green_300 = "#85e0ac" +M.green_400 = "#5cd693" +M.green_500 = "#33cc78" +M.green_600 = "#29a360" +M.green_700 = "#1f7a48" +M.green_800 = "#19663d" +M.green_900 = "#145231" +M.green_950 = "#0a291a" + +-- Mint (chat user backgrounds, alternative green) +M.mint_500 = "#16e975" +M.mint_600 = "#13cd67" +M.mint_700 = "#0d8c46" + +-- Red (danger, errors, diagnostics) +M.red_50 = "#fef1f2" +M.red_100 = "#fcdadd" +M.red_200 = "#faccd0" +M.red_250 = "#f7abb1" +M.red_300 = "#f5949c" +M.red_400 = "#f16a75" +M.red_500 = "#ee4452" +M.red_600 = "#ea1f30" +M.red_700 = "#c41221" +M.red_800 = "#ad101d" +M.red_900 = "#7e0c15" +M.red_950 = "#4f070d" + +-- Blue (info states, links, selections) +M.blue_50 = "#eaf2fb" +M.blue_100 = "#ddebf8" +M.blue_200 = "#b2d1f0" +M.blue_300 = "#7fb3e6" +M.blue_400 = "#4891db" +M.blue_500 = "#2878c8" +M.blue_600 = "#236bb3" +M.blue_700 = "#1b5288" +M.blue_800 = "#13385e" +M.blue_900 = "#081a2b" + +-- Yellow (warnings, sticky notes) +M.yellow_100 = "#fff5d6" +M.yellow_200 = "#ffe48a" +M.yellow_300 = "#ffdb66" +M.yellow_400 = "#ffcf33" +M.yellow_500 = "#ffc400" +M.yellow_600 = "#cc9c00" +M.yellow_700 = "#a37d00" +M.yellow_800 = "#705600" +M.yellow_900 = "#332700" + +-- Gold (alternative warm accent) +M.gold_50 = "#fdf9f1" +M.gold_100 = "#f7e3c4" +M.gold_200 = "#f4d8ae" +M.gold_300 = "#efc381" +M.gold_400 = "#e6a23d" +M.gold_500 = "#d48a1c" +M.gold_600 = "#b57617" +M.gold_700 = "#905e13" +M.gold_800 = "#63410d" +M.gold_900 = "#2d1d06" + +-- Slate (alternative neutral with blue tint) +M.slate_100 = "#e4e3e8" +M.slate_200 = "#c8c7d1" +M.slate_300 = "#adabba" +M.slate_400 = "#928fa3" +M.slate_500 = "#76738c" +M.slate_600 = "#5f5c70" +M.slate_700 = "#474554" +M.slate_800 = "#2f2e38" +M.slate_900 = "#18171c" + +-- n8n brand pink (logo, marketing) +M.brand_pink = "#EA4B71" +M.brand_dark = "#101330" + +-- Assistant/AI highlight gradient stops +M.highlight_1 = "#8c90f2" +M.highlight_2 = "#a977f0" +M.highlight_3 = "#f0778b" + +-- Node icon accent colors (from the canvas) +M.icon_blue = "#898fff" +M.icon_light_blue = "#58abff" +M.icon_dark_blue = "#7ba7ff" +M.icon_pink_red = "#f85d82" + +-- Special +M.none = "NONE" + +return M diff --git a/theme.lua b/theme.lua new file mode 100644 index 0000000..668457b --- /dev/null +++ b/theme.lua @@ -0,0 +1,118 @@ +local palette = require("n8n.palette") + +---@class N8nTheme +local M = {} + +function M.colors() + return { + -- Editor backgrounds (mirroring n8n's layered dark surfaces) + bg = palette.neutral_950, -- #171717 canvas background + bg_dark = palette.neutral_black, -- #000000 deepest bg + bg_float = palette.neutral_900, -- #212121 floating panels + bg_popup = palette.neutral_850, -- #2b2b2b popup menus + bg_sidebar = palette.neutral_900, -- #212121 sidebar/tree + bg_statusline = palette.neutral_900, -- #212121 statusline + bg_visual = palette.neutral_750, -- #424242 visual selection + bg_highlight = palette.neutral_850, -- #2b2b2b cursorline + bg_search = palette.yellow_900, -- #332700 search highlight bg + + -- Foregrounds + fg = palette.neutral_200, -- #e0e0e0 primary text + fg_bright = palette.neutral_white, -- #ffffff bright text + fg_dark = palette.neutral_400, -- #949494 muted text + fg_gutter = palette.neutral_600, -- #757575 gutter/line numbers + fg_sidebar = palette.neutral_300, -- #adadad sidebar text + + -- Borders (n8n uses white alpha overlays on dark) + border = palette.neutral_700, -- #4d4d4d default border + border_highlight = palette.neutral_600, -- #757575 active border + + -- Brand accent (n8n orange in dark mode) + accent = palette.orange_300, -- #ff6f5c brand accent + accent_hover = palette.orange_400, -- #ff4b33 hover state + accent_active = palette.orange_500, -- #ff1e00 active/pressed + + -- Syntax colors (derived from n8n's code editor + JSON viewer) + keyword = palette.orange_300, -- #ff6f5c keywords (brand color) + string = palette.purple_400, -- #a098dc strings + func = palette.blue_300, -- #7fb3e6 functions + variable = palette.neutral_200, -- #e0e0e0 variables + constant = palette.gold_400, -- #e6a23d constants + number = palette.green_600, -- #29a360 numbers + boolean = palette.green_600, -- #29a360 booleans + type = palette.purple_300, -- #c3bee9 types + operator = palette.orange_250, -- #ff9c8f operators + property = palette.blue_400, -- #4891db properties/fields + parameter = palette.gold_300, -- #efc381 parameters + comment = palette.neutral_500, -- #828282 comments + punctuation = palette.neutral_400, -- #949494 punctuation + tag = palette.orange_300, -- #ff6f5c HTML/XML tags + attribute = palette.purple_400, -- #a098dc attributes + namespace = palette.slate_300, -- #adabba namespaces + preproc = palette.brand_pink, -- #EA4B71 preprocessor + special = palette.highlight_2, -- #a977f0 special symbols + regex = palette.mint_500, -- #16e975 regex + escape = palette.mint_600, -- #13cd67 escape sequences + builtin = palette.blue_300, -- #7fb3e6 built-in functions + + -- JSON viewer colors (directly from n8n's JSON display) + json_key = palette.neutral_125, -- #f5f5f5 JSON keys + json_string = palette.purple_400, -- #a098dc JSON string values + json_number = palette.green_600, -- #29a360 JSON numbers + json_boolean = palette.green_600, -- #29a360 JSON booleans + json_null = palette.red_400, -- #f16a75 JSON null + json_bracket = palette.neutral_700, -- #4d4d4d brackets + + -- Diagnostics + error = palette.red_600, -- #ea1f30 + warning = palette.yellow_500, -- #ffc400 + info = palette.blue_500, -- #2878c8 + hint = palette.green_500, -- #33cc78 + + -- Diff + diff_add = palette.green_950, -- #0a291a + diff_change = palette.blue_900, -- #081a2b + diff_delete = palette.red_950, -- #4f070d + diff_text = palette.blue_800, -- #13385e + + -- Git signs + git_add = palette.green_500, -- #33cc78 + git_change = palette.blue_400, -- #4891db + git_delete = palette.red_500, -- #ee4452 + + -- n8n-specific semantic colors + node_bg = palette.neutral_850, -- node card background + node_border = palette.purple_500, -- pinned node border + sticky_bg = palette.yellow_900, -- sticky note background + sticky_border = palette.yellow_800, -- sticky note border + sticky_text = palette.neutral_125, -- sticky note text + success_bg = palette.green_950, -- success state bg + success_fg = palette.green_50, -- success state text + danger_bg = palette.red_950, -- danger state bg + danger_fg = palette.red_50, -- danger state text + info_bg = palette.blue_900, -- info state bg + info_fg = palette.blue_50, -- info state text + + -- Terminal colors + terminal = { + black = palette.neutral_950, + red = palette.red_500, + green = palette.green_500, + yellow = palette.yellow_500, + blue = palette.blue_400, + magenta = palette.purple_500, + cyan = palette.mint_500, + white = palette.neutral_200, + bright_black = palette.neutral_600, + bright_red = palette.red_400, + bright_green = palette.green_400, + bright_yellow = palette.yellow_300, + bright_blue = palette.blue_300, + bright_magenta = palette.purple_400, + bright_cyan = palette.mint_600, + bright_white = palette.neutral_white, + }, + } +end + +return M