untested, just committing to save everything.
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
178
README.md
Normal file
178
README.md
Normal file
@ -0,0 +1,178 @@
|
||||
# n8n.nvim
|
||||
|
||||
A dark Neovim colorscheme inspired by the [n8n](https://n8n.io) workflow automation platform's dark mode UI.
|
||||
|
||||
Built from n8n's actual CSS design tokens: the same neutrals, the signature orange accent, the purple/blue/green syntax colors you see in the n8n editor and JSON viewer.
|
||||
|
||||
## Features
|
||||
|
||||
- Full Treesitter highlight group support
|
||||
- LSP semantic token highlights
|
||||
- Terminal colors
|
||||
- Lualine theme included
|
||||
- Plugin support: Telescope, NvimTree, Neo-tree, cmp, Blink.cmp, GitSigns, Indent Blankline, Which-Key, Lazy, Mason, Noice, Notify, Trouble, Mini, Bufferline, Snacks, and more
|
||||
- Transparent background option
|
||||
- Customizable styles and color overrides
|
||||
|
||||
## Installation
|
||||
|
||||
### vim.pack (native packages)
|
||||
|
||||
Clone the repo into your Neovim pack path so it loads automatically:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/n8n.nvim \
|
||||
~/.config/nvim/pack/plugins/start/n8n.nvim
|
||||
```
|
||||
|
||||
Then in your `init.lua`:
|
||||
|
||||
```lua
|
||||
require("n8n").setup({
|
||||
-- optional config
|
||||
})
|
||||
vim.cmd("colorscheme n8n")
|
||||
```
|
||||
|
||||
If you prefer to load it on demand, clone into `opt` instead:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/n8n.nvim \
|
||||
~/.config/nvim/pack/plugins/opt/n8n.nvim
|
||||
```
|
||||
|
||||
```lua
|
||||
vim.cmd("packadd n8n.nvim")
|
||||
require("n8n").setup()
|
||||
vim.cmd("colorscheme n8n")
|
||||
```
|
||||
|
||||
### lazy.nvim
|
||||
|
||||
```lua
|
||||
{
|
||||
"your-username/n8n.nvim",
|
||||
lazy = false,
|
||||
priority = 1000,
|
||||
config = function()
|
||||
require("n8n").setup({
|
||||
-- your config here (optional)
|
||||
})
|
||||
vim.cmd("colorscheme n8n")
|
||||
end,
|
||||
}
|
||||
```
|
||||
|
||||
### packer.nvim
|
||||
|
||||
```lua
|
||||
use({
|
||||
"your-username/n8n.nvim",
|
||||
config = function()
|
||||
require("n8n").setup()
|
||||
vim.cmd("colorscheme n8n")
|
||||
end,
|
||||
})
|
||||
```
|
||||
|
||||
### vim-plug
|
||||
|
||||
```vim
|
||||
Plug 'your-username/n8n.nvim'
|
||||
|
||||
" in your init.vim, after plug#end():
|
||||
lua require('n8n').setup()
|
||||
colorscheme n8n
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Call `setup()` **before** setting the colorscheme. All options are optional.
|
||||
|
||||
```lua
|
||||
require("n8n").setup({
|
||||
transparent = false, -- enable transparent background
|
||||
terminal_colors = true, -- configure terminal colors
|
||||
dim_inactive = false, -- dim inactive split windows
|
||||
|
||||
styles = {
|
||||
comments = { italic = true },
|
||||
keywords = {},
|
||||
functions = {},
|
||||
strings = {},
|
||||
variables = {},
|
||||
},
|
||||
|
||||
-- Override specific colors
|
||||
on_colors = function(colors)
|
||||
-- colors.bg = "#000000"
|
||||
return colors
|
||||
end,
|
||||
|
||||
-- Override specific highlight groups
|
||||
on_highlights = function(highlights, colors)
|
||||
-- highlights.Normal = { fg = "#ffffff", bg = "#000000" }
|
||||
end,
|
||||
})
|
||||
```
|
||||
|
||||
## Lualine
|
||||
|
||||
The theme ships with a built-in lualine theme:
|
||||
|
||||
```lua
|
||||
require("lualine").setup({
|
||||
options = {
|
||||
theme = "n8n",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Palette
|
||||
|
||||
The color palette is extracted directly from n8n's dark mode CSS custom properties. Key colors:
|
||||
|
||||
| Role | Color | Hex |
|
||||
|------|-------|-----|
|
||||
| Background |  | `#171717` |
|
||||
| Surface |  | `#212121` |
|
||||
| Foreground |  | `#e0e0e0` |
|
||||
| Accent (Orange) |  | `#ff6f5c` |
|
||||
| Keywords |  | `#ff6f5c` |
|
||||
| Strings |  | `#a098dc` |
|
||||
| Functions |  | `#7fb3e6` |
|
||||
| Types |  | `#c3bee9` |
|
||||
| Numbers |  | `#29a360` |
|
||||
| Constants |  | `#e6a23d` |
|
||||
| Comments |  | `#828282` |
|
||||
| Error |  | `#ea1f30` |
|
||||
| Warning |  | `#ffc400` |
|
||||
| Info |  | `#2878c8` |
|
||||
| Hint |  | `#33cc78` |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
n8n.nvim/
|
||||
├── colors/
|
||||
│ └── n8n.lua # entry point for :colorscheme n8n
|
||||
├── lua/
|
||||
│ ├── n8n/
|
||||
│ │ ├── init.lua # setup() and load() logic
|
||||
│ │ ├── palette.lua # raw hex values from n8n's CSS
|
||||
│ │ ├── theme.lua # semantic color mapping
|
||||
│ │ └── groups.lua # all highlight group definitions
|
||||
│ └── lualine/
|
||||
│ └── themes/
|
||||
│ └── n8n.lua # lualine theme extra
|
||||
├── LICENSE
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Colors derived from the [n8n design system](https://github.com/n8n-io/n8n). This is a community project and is not affiliated with n8n GmbH.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
556
groups.lua
Normal file
556
groups.lua
Normal file
@ -0,0 +1,556 @@
|
||||
local theme = require("n8n.theme")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param opts? table
|
||||
function M.setup(opts)
|
||||
opts = opts or {}
|
||||
local c = theme.colors()
|
||||
|
||||
local groups = {}
|
||||
|
||||
-- ============================================================
|
||||
-- Core editor highlights
|
||||
-- ============================================================
|
||||
groups.Normal = { fg = c.fg, bg = c.bg }
|
||||
groups.NormalFloat = { fg = c.fg, bg = c.bg_float }
|
||||
groups.NormalSB = { fg = c.fg_sidebar, bg = c.bg_sidebar }
|
||||
groups.SignColumn = { fg = c.fg_gutter, bg = c.bg }
|
||||
groups.FoldColumn = { fg = c.fg_gutter, bg = c.bg }
|
||||
groups.MsgArea = { fg = c.fg }
|
||||
groups.MsgSeparator = { fg = c.border }
|
||||
groups.SpellBad = { sp = c.error, undercurl = true }
|
||||
groups.SpellCap = { sp = c.warning, undercurl = true }
|
||||
groups.SpellLocal = { sp = c.info, undercurl = true }
|
||||
groups.SpellRare = { sp = c.hint, undercurl = true }
|
||||
|
||||
-- Cursor and selections
|
||||
groups.Cursor = { fg = c.bg, bg = c.fg_bright }
|
||||
groups.lCursor = { link = "Cursor" }
|
||||
groups.CursorIM = { link = "Cursor" }
|
||||
groups.TermCursor = { fg = c.bg, bg = c.accent }
|
||||
groups.TermCursorNC = { fg = c.bg, bg = c.fg_dark }
|
||||
groups.CursorLine = { bg = c.bg_highlight }
|
||||
groups.CursorColumn = { bg = c.bg_highlight }
|
||||
groups.ColorColumn = { bg = c.bg_highlight }
|
||||
groups.Visual = { bg = c.bg_visual }
|
||||
groups.VisualNOS = { bg = c.bg_visual }
|
||||
|
||||
-- Line numbers
|
||||
groups.LineNr = { fg = c.fg_gutter }
|
||||
groups.CursorLineNr = { fg = c.accent, bold = true }
|
||||
groups.LineNrAbove = { fg = c.fg_gutter }
|
||||
groups.LineNrBelow = { fg = c.fg_gutter }
|
||||
|
||||
-- Search
|
||||
groups.Search = { fg = c.fg_bright, bg = c.bg_search }
|
||||
groups.IncSearch = { fg = c.bg, bg = c.accent }
|
||||
groups.CurSearch = { link = "IncSearch" }
|
||||
groups.Substitute = { fg = c.bg, bg = c.accent }
|
||||
|
||||
-- Popup menu
|
||||
groups.Pmenu = { fg = c.fg, bg = c.bg_popup }
|
||||
groups.PmenuSel = { fg = c.fg_bright, bg = c.bg_visual }
|
||||
groups.PmenuSbar = { bg = c.bg_popup }
|
||||
groups.PmenuThumb = { bg = c.border }
|
||||
groups.PmenuKind = { fg = c.accent }
|
||||
groups.PmenuKindSel = { fg = c.accent, bg = c.bg_visual }
|
||||
groups.PmenuExtra = { fg = c.fg_dark }
|
||||
groups.PmenuExtraSel = { fg = c.fg_dark, bg = c.bg_visual }
|
||||
|
||||
-- Tabline
|
||||
groups.TabLine = { fg = c.fg_dark, bg = c.bg_statusline }
|
||||
groups.TabLineFill = { bg = c.bg_dark }
|
||||
groups.TabLineSel = { fg = c.fg_bright, bg = c.bg }
|
||||
|
||||
-- Statusline
|
||||
groups.StatusLine = { fg = c.fg, bg = c.bg_statusline }
|
||||
groups.StatusLineNC = { fg = c.fg_gutter, bg = c.bg_statusline }
|
||||
|
||||
-- Window separators
|
||||
groups.VertSplit = { fg = c.border }
|
||||
groups.WinSeparator = { fg = c.border }
|
||||
groups.WinBar = { fg = c.fg, bg = c.bg }
|
||||
groups.WinBarNC = { fg = c.fg_dark, bg = c.bg }
|
||||
|
||||
-- Folds and columns
|
||||
groups.Folded = { fg = c.fg_dark, bg = c.bg_highlight }
|
||||
groups.NonText = { fg = c.neutral_700 }
|
||||
groups.EndOfBuffer = { fg = c.neutral_800 }
|
||||
groups.Whitespace = { fg = c.neutral_800 }
|
||||
groups.SpecialKey = { fg = c.neutral_700 }
|
||||
|
||||
-- Messages
|
||||
groups.ErrorMsg = { fg = c.error }
|
||||
groups.WarningMsg = { fg = c.warning }
|
||||
groups.MoreMsg = { fg = c.info }
|
||||
groups.Question = { fg = c.accent }
|
||||
groups.Title = { fg = c.accent, bold = true }
|
||||
groups.Directory = { fg = c.func }
|
||||
groups.Conceal = { fg = c.fg_dark }
|
||||
groups.MatchParen = { fg = c.accent, bold = true, underline = true }
|
||||
groups.QuickFixLine = { bg = c.bg_visual }
|
||||
|
||||
-- Float border
|
||||
groups.FloatBorder = { fg = c.border_highlight, bg = c.bg_float }
|
||||
groups.FloatTitle = { fg = c.accent, bg = c.bg_float, bold = true }
|
||||
|
||||
-- ============================================================
|
||||
-- Standard syntax groups (:h group-name)
|
||||
-- ============================================================
|
||||
groups.Comment = { fg = c.comment, italic = true }
|
||||
groups.Constant = { fg = c.constant }
|
||||
groups.String = { fg = c.string }
|
||||
groups.Character = { fg = c.string }
|
||||
groups.Number = { fg = c.number }
|
||||
groups.Boolean = { fg = c.boolean }
|
||||
groups.Float = { fg = c.number }
|
||||
|
||||
groups.Identifier = { fg = c.variable }
|
||||
groups.Function = { fg = c.func }
|
||||
|
||||
groups.Statement = { fg = c.keyword }
|
||||
groups.Conditional = { fg = c.keyword }
|
||||
groups.Repeat = { fg = c.keyword }
|
||||
groups.Label = { fg = c.keyword }
|
||||
groups.Operator = { fg = c.operator }
|
||||
groups.Keyword = { fg = c.keyword }
|
||||
groups.Exception = { fg = c.keyword }
|
||||
|
||||
groups.PreProc = { fg = c.preproc }
|
||||
groups.Include = { fg = c.keyword }
|
||||
groups.Define = { fg = c.keyword }
|
||||
groups.Macro = { fg = c.preproc }
|
||||
groups.PreCondit = { fg = c.preproc }
|
||||
|
||||
groups.Type = { fg = c.type }
|
||||
groups.StorageClass = { fg = c.keyword }
|
||||
groups.Structure = { fg = c.type }
|
||||
groups.Typedef = { fg = c.type }
|
||||
|
||||
groups.Special = { fg = c.special }
|
||||
groups.SpecialChar = { fg = c.escape }
|
||||
groups.Tag = { fg = c.tag }
|
||||
groups.Delimiter = { fg = c.punctuation }
|
||||
groups.SpecialComment = { fg = c.comment, bold = true }
|
||||
groups.Debug = { fg = c.warning }
|
||||
|
||||
groups.Underlined = { underline = true }
|
||||
groups.Bold = { bold = true }
|
||||
groups.Italic = { italic = true }
|
||||
groups.Ignore = { fg = c.bg }
|
||||
groups.Error = { fg = c.error }
|
||||
groups.Todo = { fg = c.bg, bg = c.accent, bold = true }
|
||||
|
||||
-- ============================================================
|
||||
-- Treesitter highlights (@groups)
|
||||
-- ============================================================
|
||||
|
||||
-- Identifiers
|
||||
groups["@variable"] = { fg = c.variable }
|
||||
groups["@variable.builtin"] = { fg = c.builtin, italic = true }
|
||||
groups["@variable.parameter"] = { fg = c.parameter }
|
||||
groups["@variable.parameter.builtin"] = { fg = c.parameter, italic = true }
|
||||
groups["@variable.member"] = { fg = c.property }
|
||||
|
||||
groups["@constant"] = { fg = c.constant }
|
||||
groups["@constant.builtin"] = { fg = c.constant, bold = true }
|
||||
groups["@constant.macro"] = { fg = c.preproc }
|
||||
|
||||
groups["@module"] = { fg = c.namespace }
|
||||
groups["@module.builtin"] = { fg = c.namespace, italic = true }
|
||||
groups["@label"] = { fg = c.keyword }
|
||||
|
||||
-- Literals
|
||||
groups["@string"] = { fg = c.string }
|
||||
groups["@string.documentation"] = { fg = c.comment }
|
||||
groups["@string.regex"] = { fg = c.regex }
|
||||
groups["@string.escape"] = { fg = c.escape }
|
||||
groups["@string.special"] = { fg = c.special }
|
||||
groups["@string.special.symbol"] = { fg = c.special }
|
||||
groups["@string.special.url"] = { fg = c.info, underline = true }
|
||||
groups["@string.special.path"] = { fg = c.info }
|
||||
|
||||
groups["@character"] = { fg = c.string }
|
||||
groups["@character.special"] = { fg = c.escape }
|
||||
|
||||
groups["@boolean"] = { fg = c.boolean }
|
||||
groups["@number"] = { fg = c.number }
|
||||
groups["@number.float"] = { fg = c.number }
|
||||
|
||||
-- Types
|
||||
groups["@type"] = { fg = c.type }
|
||||
groups["@type.builtin"] = { fg = c.type, italic = true }
|
||||
groups["@type.definition"] = { fg = c.type }
|
||||
groups["@type.qualifier"] = { fg = c.keyword }
|
||||
|
||||
groups["@attribute"] = { fg = c.attribute }
|
||||
groups["@attribute.builtin"] = { fg = c.attribute, italic = true }
|
||||
groups["@property"] = { fg = c.property }
|
||||
|
||||
-- Functions
|
||||
groups["@function"] = { fg = c.func }
|
||||
groups["@function.builtin"] = { fg = c.builtin }
|
||||
groups["@function.call"] = { fg = c.func }
|
||||
groups["@function.macro"] = { fg = c.preproc }
|
||||
groups["@function.method"] = { fg = c.func }
|
||||
groups["@function.method.call"] = { fg = c.func }
|
||||
|
||||
groups["@constructor"] = { fg = c.type }
|
||||
groups["@operator"] = { fg = c.operator }
|
||||
|
||||
-- Keywords
|
||||
groups["@keyword"] = { fg = c.keyword }
|
||||
groups["@keyword.coroutine"] = { fg = c.keyword, italic = true }
|
||||
groups["@keyword.function"] = { fg = c.keyword }
|
||||
groups["@keyword.operator"] = { fg = c.operator }
|
||||
groups["@keyword.import"] = { fg = c.keyword }
|
||||
groups["@keyword.type"] = { fg = c.keyword }
|
||||
groups["@keyword.modifier"] = { fg = c.keyword }
|
||||
groups["@keyword.repeat"] = { fg = c.keyword }
|
||||
groups["@keyword.return"] = { fg = c.keyword }
|
||||
groups["@keyword.debug"] = { fg = c.warning }
|
||||
groups["@keyword.exception"] = { fg = c.keyword }
|
||||
groups["@keyword.conditional"] = { fg = c.keyword }
|
||||
groups["@keyword.conditional.ternary"] = { fg = c.operator }
|
||||
groups["@keyword.directive"] = { fg = c.preproc }
|
||||
groups["@keyword.directive.define"] = { fg = c.preproc }
|
||||
|
||||
-- Punctuation
|
||||
groups["@punctuation.delimiter"] = { fg = c.punctuation }
|
||||
groups["@punctuation.bracket"] = { fg = c.punctuation }
|
||||
groups["@punctuation.special"] = { fg = c.special }
|
||||
|
||||
-- Comments
|
||||
groups["@comment"] = { fg = c.comment, italic = true }
|
||||
groups["@comment.documentation"] = { fg = c.comment }
|
||||
groups["@comment.error"] = { fg = c.error }
|
||||
groups["@comment.warning"] = { fg = c.warning }
|
||||
groups["@comment.todo"] = { fg = c.bg, bg = c.accent, bold = true }
|
||||
groups["@comment.note"] = { fg = c.bg, bg = c.info, bold = true }
|
||||
|
||||
-- Markup (markdown, html, etc.)
|
||||
groups["@markup.strong"] = { bold = true }
|
||||
groups["@markup.italic"] = { italic = true }
|
||||
groups["@markup.strikethrough"] = { strikethrough = true }
|
||||
groups["@markup.underline"] = { underline = true }
|
||||
groups["@markup.heading"] = { fg = c.accent, bold = true }
|
||||
groups["@markup.heading.1"] = { fg = c.accent, bold = true }
|
||||
groups["@markup.heading.2"] = { fg = c.func, bold = true }
|
||||
groups["@markup.heading.3"] = { fg = c.type, bold = true }
|
||||
groups["@markup.heading.4"] = { fg = c.string, bold = true }
|
||||
groups["@markup.heading.5"] = { fg = c.constant, bold = true }
|
||||
groups["@markup.heading.6"] = { fg = c.comment, bold = true }
|
||||
groups["@markup.quote"] = { fg = c.fg_dark, italic = true }
|
||||
groups["@markup.math"] = { fg = c.number }
|
||||
groups["@markup.environment"] = { fg = c.preproc }
|
||||
groups["@markup.link"] = { fg = c.info, underline = true }
|
||||
groups["@markup.link.label"] = { fg = c.info }
|
||||
groups["@markup.link.url"] = { fg = c.info, underline = true }
|
||||
groups["@markup.raw"] = { fg = c.string }
|
||||
groups["@markup.raw.block"] = { fg = c.fg }
|
||||
groups["@markup.list"] = { fg = c.accent }
|
||||
groups["@markup.list.checked"] = { fg = c.git_add }
|
||||
groups["@markup.list.unchecked"] = { fg = c.fg_dark }
|
||||
|
||||
-- Tags (HTML, JSX, etc.)
|
||||
groups["@tag"] = { fg = c.tag }
|
||||
groups["@tag.builtin"] = { fg = c.tag, bold = true }
|
||||
groups["@tag.attribute"] = { fg = c.attribute }
|
||||
groups["@tag.delimiter"] = { fg = c.punctuation }
|
||||
|
||||
-- ============================================================
|
||||
-- LSP Semantic Tokens
|
||||
-- ============================================================
|
||||
groups["@lsp.type.boolean"] = { link = "@boolean" }
|
||||
groups["@lsp.type.builtinType"] = { link = "@type.builtin" }
|
||||
groups["@lsp.type.comment"] = { link = "@comment" }
|
||||
groups["@lsp.type.decorator"] = { link = "@attribute" }
|
||||
groups["@lsp.type.deriveHelper"] = { link = "@attribute" }
|
||||
groups["@lsp.type.enum"] = { link = "@type" }
|
||||
groups["@lsp.type.enumMember"] = { link = "@constant" }
|
||||
groups["@lsp.type.escapeSequence"] = { link = "@string.escape" }
|
||||
groups["@lsp.type.formatSpecifier"] = { link = "@punctuation.special" }
|
||||
groups["@lsp.type.function"] = { link = "@function" }
|
||||
groups["@lsp.type.generic"] = { link = "@variable" }
|
||||
groups["@lsp.type.interface"] = { fg = c.type }
|
||||
groups["@lsp.type.keyword"] = { link = "@keyword" }
|
||||
groups["@lsp.type.lifetime"] = { link = "@keyword.modifier" }
|
||||
groups["@lsp.type.method"] = { link = "@function.method" }
|
||||
groups["@lsp.type.namespace"] = { link = "@module" }
|
||||
groups["@lsp.type.number"] = { link = "@number" }
|
||||
groups["@lsp.type.operator"] = { link = "@operator" }
|
||||
groups["@lsp.type.parameter"] = { link = "@variable.parameter" }
|
||||
groups["@lsp.type.property"] = { link = "@property" }
|
||||
groups["@lsp.type.selfKeyword"] = { fg = c.builtin, italic = true }
|
||||
groups["@lsp.type.selfTypeKeyword"] = { link = "@type.builtin" }
|
||||
groups["@lsp.type.string"] = { link = "@string" }
|
||||
groups["@lsp.type.typeAlias"] = { link = "@type.definition" }
|
||||
groups["@lsp.type.typeParameter"] = { fg = c.type }
|
||||
groups["@lsp.type.unresolvedReference"] = { undercurl = true, sp = c.error }
|
||||
groups["@lsp.type.variable"] = {} -- defer to treesitter
|
||||
groups["@lsp.typemod.class.defaultLibrary"] = { link = "@type.builtin" }
|
||||
groups["@lsp.typemod.enum.defaultLibrary"] = { link = "@type.builtin" }
|
||||
groups["@lsp.typemod.enumMember.defaultLibrary"] = { link = "@constant.builtin" }
|
||||
groups["@lsp.typemod.function.defaultLibrary"] = { link = "@function.builtin" }
|
||||
groups["@lsp.typemod.keyword.async"] = { link = "@keyword.coroutine" }
|
||||
groups["@lsp.typemod.keyword.injected"] = { link = "@keyword" }
|
||||
groups["@lsp.typemod.macro.defaultLibrary"] = { link = "@function.builtin" }
|
||||
groups["@lsp.typemod.method.defaultLibrary"] = { link = "@function.builtin" }
|
||||
groups["@lsp.typemod.operator.injected"] = { link = "@operator" }
|
||||
groups["@lsp.typemod.string.injected"] = { link = "@string" }
|
||||
groups["@lsp.typemod.struct.defaultLibrary"] = { link = "@type.builtin" }
|
||||
groups["@lsp.typemod.type.defaultLibrary"] = { link = "@type.builtin" }
|
||||
groups["@lsp.typemod.typeAlias.defaultLibrary"] = { link = "@type.builtin" }
|
||||
groups["@lsp.typemod.variable.callable"] = { link = "@function" }
|
||||
groups["@lsp.typemod.variable.defaultLibrary"] = { link = "@variable.builtin" }
|
||||
groups["@lsp.typemod.variable.injected"] = { link = "@variable" }
|
||||
groups["@lsp.typemod.variable.static"] = { link = "@constant" }
|
||||
|
||||
-- ============================================================
|
||||
-- Diagnostics
|
||||
-- ============================================================
|
||||
groups.DiagnosticError = { fg = c.error }
|
||||
groups.DiagnosticWarn = { fg = c.warning }
|
||||
groups.DiagnosticInfo = { fg = c.info }
|
||||
groups.DiagnosticHint = { fg = c.hint }
|
||||
groups.DiagnosticOk = { fg = c.git_add }
|
||||
groups.DiagnosticUnderlineError = { undercurl = true, sp = c.error }
|
||||
groups.DiagnosticUnderlineWarn = { undercurl = true, sp = c.warning }
|
||||
groups.DiagnosticUnderlineInfo = { undercurl = true, sp = c.info }
|
||||
groups.DiagnosticUnderlineHint = { undercurl = true, sp = c.hint }
|
||||
groups.DiagnosticUnderlineOk = { undercurl = true, sp = c.git_add }
|
||||
groups.DiagnosticVirtualTextError = { fg = c.error, bg = c.danger_bg }
|
||||
groups.DiagnosticVirtualTextWarn = { fg = c.warning, bg = c.sticky_bg }
|
||||
groups.DiagnosticVirtualTextInfo = { fg = c.info, bg = c.info_bg }
|
||||
groups.DiagnosticVirtualTextHint = { fg = c.hint, bg = c.success_bg }
|
||||
|
||||
-- ============================================================
|
||||
-- Diff
|
||||
-- ============================================================
|
||||
groups.DiffAdd = { bg = c.diff_add }
|
||||
groups.DiffChange = { bg = c.diff_change }
|
||||
groups.DiffDelete = { bg = c.diff_delete }
|
||||
groups.DiffText = { bg = c.diff_text }
|
||||
groups.diffAdded = { fg = c.git_add }
|
||||
groups.diffRemoved = { fg = c.git_delete }
|
||||
groups.diffChanged = { fg = c.git_change }
|
||||
groups.diffOldFile = { fg = c.git_delete }
|
||||
groups.diffNewFile = { fg = c.git_add }
|
||||
groups.diffFile = { fg = c.info }
|
||||
groups.diffLine = { fg = c.comment }
|
||||
groups.diffIndexLine = { fg = c.comment }
|
||||
|
||||
-- ============================================================
|
||||
-- Git Signs
|
||||
-- ============================================================
|
||||
groups.GitSignsAdd = { fg = c.git_add }
|
||||
groups.GitSignsChange = { fg = c.git_change }
|
||||
groups.GitSignsDelete = { fg = c.git_delete }
|
||||
groups.GitSignsAddNr = { fg = c.git_add }
|
||||
groups.GitSignsChangeNr = { fg = c.git_change }
|
||||
groups.GitSignsDeleteNr = { fg = c.git_delete }
|
||||
groups.GitSignsAddLn = { bg = c.diff_add }
|
||||
groups.GitSignsChangeLn = { bg = c.diff_change }
|
||||
groups.GitSignsDeleteLn = { bg = c.diff_delete }
|
||||
groups.GitSignsCurrentLineBlame = { fg = c.fg_gutter, italic = true }
|
||||
|
||||
-- ============================================================
|
||||
-- Telescope
|
||||
-- ============================================================
|
||||
groups.TelescopeNormal = { fg = c.fg, bg = c.bg_float }
|
||||
groups.TelescopeBorder = { fg = c.border_highlight, bg = c.bg_float }
|
||||
groups.TelescopeTitle = { fg = c.accent, bold = true }
|
||||
groups.TelescopePromptNormal = { fg = c.fg_bright, bg = c.bg_popup }
|
||||
groups.TelescopePromptBorder = { fg = c.accent, bg = c.bg_popup }
|
||||
groups.TelescopePromptTitle = { fg = c.bg, bg = c.accent, bold = true }
|
||||
groups.TelescopePromptPrefix = { fg = c.accent }
|
||||
groups.TelescopePreviewTitle = { fg = c.bg, bg = c.info, bold = true }
|
||||
groups.TelescopeResultsTitle = { fg = c.bg, bg = c.hint, bold = true }
|
||||
groups.TelescopeSelection = { bg = c.bg_visual }
|
||||
groups.TelescopeSelectionCaret = { fg = c.accent }
|
||||
groups.TelescopeMatching = { fg = c.accent, bold = true }
|
||||
|
||||
-- ============================================================
|
||||
-- NvimTree / Neo-tree
|
||||
-- ============================================================
|
||||
groups.NvimTreeNormal = { fg = c.fg_sidebar, bg = c.bg_sidebar }
|
||||
groups.NvimTreeNormalNC = { fg = c.fg_sidebar, bg = c.bg_sidebar }
|
||||
groups.NvimTreeRootFolder = { fg = c.accent, bold = true }
|
||||
groups.NvimTreeFolderIcon = { fg = c.func }
|
||||
groups.NvimTreeFolderName = { fg = c.func }
|
||||
groups.NvimTreeOpenedFolderName = { fg = c.func, bold = true }
|
||||
groups.NvimTreeGitDirty = { fg = c.git_change }
|
||||
groups.NvimTreeGitNew = { fg = c.git_add }
|
||||
groups.NvimTreeGitDeleted = { fg = c.git_delete }
|
||||
groups.NvimTreeSpecialFile = { fg = c.special, underline = true }
|
||||
groups.NvimTreeIndentMarker = { fg = c.border }
|
||||
groups.NvimTreeWinSeparator = { fg = c.border, bg = c.bg_sidebar }
|
||||
|
||||
groups.NeoTreeNormal = { fg = c.fg_sidebar, bg = c.bg_sidebar }
|
||||
groups.NeoTreeNormalNC = { fg = c.fg_sidebar, bg = c.bg_sidebar }
|
||||
groups.NeoTreeDimText = { fg = c.fg_gutter }
|
||||
groups.NeoTreeTitleBar = { fg = c.bg, bg = c.accent }
|
||||
|
||||
-- ============================================================
|
||||
-- Indent Blankline
|
||||
-- ============================================================
|
||||
groups.IndentBlanklineChar = { fg = c.neutral_800, nocombine = true }
|
||||
groups.IndentBlanklineContextChar = { fg = c.accent, nocombine = true }
|
||||
groups.IblIndent = { fg = c.neutral_800, nocombine = true }
|
||||
groups.IblScope = { fg = c.accent, nocombine = true }
|
||||
|
||||
-- ============================================================
|
||||
-- Which Key
|
||||
-- ============================================================
|
||||
groups.WhichKey = { fg = c.accent }
|
||||
groups.WhichKeyGroup = { fg = c.func }
|
||||
groups.WhichKeyDesc = { fg = c.fg }
|
||||
groups.WhichKeySeparator = { fg = c.comment }
|
||||
groups.WhichKeyValue = { fg = c.fg_dark }
|
||||
|
||||
-- ============================================================
|
||||
-- Dashboard / Alpha
|
||||
-- ============================================================
|
||||
groups.DashboardHeader = { fg = c.accent }
|
||||
groups.DashboardCenter = { fg = c.func }
|
||||
groups.DashboardShortCut = { fg = c.keyword }
|
||||
groups.DashboardFooter = { fg = c.comment, italic = true }
|
||||
|
||||
-- ============================================================
|
||||
-- Notify
|
||||
-- ============================================================
|
||||
groups.NotifyERRORBorder = { fg = c.error }
|
||||
groups.NotifyERRORIcon = { fg = c.error }
|
||||
groups.NotifyERRORTitle = { fg = c.error }
|
||||
groups.NotifyWARNBorder = { fg = c.warning }
|
||||
groups.NotifyWARNIcon = { fg = c.warning }
|
||||
groups.NotifyWARNTitle = { fg = c.warning }
|
||||
groups.NotifyINFOBorder = { fg = c.info }
|
||||
groups.NotifyINFOIcon = { fg = c.info }
|
||||
groups.NotifyINFOTitle = { fg = c.info }
|
||||
groups.NotifyDEBUGBorder = { fg = c.comment }
|
||||
groups.NotifyDEBUGIcon = { fg = c.comment }
|
||||
groups.NotifyDEBUGTitle = { fg = c.comment }
|
||||
groups.NotifyTRACEBorder = { fg = c.special }
|
||||
groups.NotifyTRACEIcon = { fg = c.special }
|
||||
groups.NotifyTRACETitle = { fg = c.special }
|
||||
|
||||
-- ============================================================
|
||||
-- Noice
|
||||
-- ============================================================
|
||||
groups.NoiceCmdlinePopup = { fg = c.fg, bg = c.bg_float }
|
||||
groups.NoiceCmdlinePopupBorder = { fg = c.accent }
|
||||
groups.NoiceCmdlineIcon = { fg = c.accent }
|
||||
groups.NoiceConfirm = { fg = c.fg, bg = c.bg_float }
|
||||
groups.NoiceConfirmBorder = { fg = c.accent }
|
||||
|
||||
-- ============================================================
|
||||
-- Cmp (completion)
|
||||
-- ============================================================
|
||||
groups.CmpItemAbbr = { fg = c.fg }
|
||||
groups.CmpItemAbbrDeprecated = { fg = c.fg_dark, strikethrough = true }
|
||||
groups.CmpItemAbbrMatch = { fg = c.accent, bold = true }
|
||||
groups.CmpItemAbbrMatchFuzzy = { fg = c.accent, bold = true }
|
||||
groups.CmpItemKind = { fg = c.func }
|
||||
groups.CmpItemMenu = { fg = c.fg_dark }
|
||||
|
||||
groups.CmpItemKindClass = { fg = c.type }
|
||||
groups.CmpItemKindColor = { fg = c.special }
|
||||
groups.CmpItemKindConstant = { fg = c.constant }
|
||||
groups.CmpItemKindConstructor = { fg = c.type }
|
||||
groups.CmpItemKindEnum = { fg = c.type }
|
||||
groups.CmpItemKindEnumMember = { fg = c.constant }
|
||||
groups.CmpItemKindEvent = { fg = c.special }
|
||||
groups.CmpItemKindField = { fg = c.property }
|
||||
groups.CmpItemKindFile = { fg = c.fg }
|
||||
groups.CmpItemKindFolder = { fg = c.func }
|
||||
groups.CmpItemKindFunction = { fg = c.func }
|
||||
groups.CmpItemKindInterface = { fg = c.type }
|
||||
groups.CmpItemKindKeyword = { fg = c.keyword }
|
||||
groups.CmpItemKindMethod = { fg = c.func }
|
||||
groups.CmpItemKindModule = { fg = c.namespace }
|
||||
groups.CmpItemKindOperator = { fg = c.operator }
|
||||
groups.CmpItemKindProperty = { fg = c.property }
|
||||
groups.CmpItemKindReference = { fg = c.constant }
|
||||
groups.CmpItemKindSnippet = { fg = c.special }
|
||||
groups.CmpItemKindStruct = { fg = c.type }
|
||||
groups.CmpItemKindText = { fg = c.fg }
|
||||
groups.CmpItemKindTypeParameter = { fg = c.type }
|
||||
groups.CmpItemKindUnit = { fg = c.constant }
|
||||
groups.CmpItemKindValue = { fg = c.constant }
|
||||
groups.CmpItemKindVariable = { fg = c.variable }
|
||||
|
||||
-- ============================================================
|
||||
-- Blink.cmp
|
||||
-- ============================================================
|
||||
groups.BlinkCmpMenu = { fg = c.fg, bg = c.bg_popup }
|
||||
groups.BlinkCmpMenuBorder = { fg = c.border_highlight, bg = c.bg_popup }
|
||||
groups.BlinkCmpMenuSelection = { bg = c.bg_visual }
|
||||
groups.BlinkCmpLabel = { fg = c.fg }
|
||||
groups.BlinkCmpLabelMatch = { fg = c.accent, bold = true }
|
||||
groups.BlinkCmpKind = { fg = c.func }
|
||||
|
||||
-- ============================================================
|
||||
-- Trouble
|
||||
-- ============================================================
|
||||
groups.TroubleNormal = { fg = c.fg, bg = c.bg_sidebar }
|
||||
groups.TroubleNormalNC = { fg = c.fg_sidebar, bg = c.bg_sidebar }
|
||||
|
||||
-- ============================================================
|
||||
-- Lazy
|
||||
-- ============================================================
|
||||
groups.LazyButton = { fg = c.fg, bg = c.bg_popup }
|
||||
groups.LazyButtonActive = { fg = c.bg, bg = c.accent }
|
||||
groups.LazyH1 = { fg = c.bg, bg = c.accent, bold = true }
|
||||
groups.LazySpecial = { fg = c.accent }
|
||||
groups.LazyProgressDone = { fg = c.accent }
|
||||
groups.LazyProgressTodo = { fg = c.fg_gutter }
|
||||
|
||||
-- ============================================================
|
||||
-- Mason
|
||||
-- ============================================================
|
||||
groups.MasonNormal = { fg = c.fg, bg = c.bg_float }
|
||||
groups.MasonHeader = { fg = c.bg, bg = c.accent, bold = true }
|
||||
groups.MasonHighlight = { fg = c.accent }
|
||||
groups.MasonHighlightBlock = { fg = c.bg, bg = c.accent }
|
||||
groups.MasonMutedBlock = { fg = c.fg, bg = c.bg_popup }
|
||||
|
||||
-- ============================================================
|
||||
-- Mini plugins
|
||||
-- ============================================================
|
||||
groups.MiniStatuslineFilename = { fg = c.fg, bg = c.bg_statusline }
|
||||
groups.MiniStatuslineDevinfo = { fg = c.fg_dark, bg = c.bg_highlight }
|
||||
groups.MiniStatuslineModeNormal = { fg = c.bg, bg = c.accent, bold = true }
|
||||
groups.MiniStatuslineModeInsert = { fg = c.bg, bg = c.hint, bold = true }
|
||||
groups.MiniStatuslineModeVisual = { fg = c.bg, bg = c.special, bold = true }
|
||||
groups.MiniStatuslineModeReplace = { fg = c.bg, bg = c.error, bold = true }
|
||||
groups.MiniStatuslineModeCommand = { fg = c.bg, bg = c.warning, bold = true }
|
||||
|
||||
groups.MiniIndentscopeSymbol = { fg = c.accent }
|
||||
|
||||
groups.MiniCursorword = { bg = c.bg_visual }
|
||||
groups.MiniCursorwordCurrent = { bg = c.bg_visual }
|
||||
|
||||
-- ============================================================
|
||||
-- Bufferline
|
||||
-- ============================================================
|
||||
groups.BufferLineIndicatorSelected = { fg = c.accent }
|
||||
groups.BufferLineFill = { bg = c.bg_dark }
|
||||
|
||||
-- ============================================================
|
||||
-- Snacks
|
||||
-- ============================================================
|
||||
groups.SnacksDashboardHeader = { fg = c.accent }
|
||||
groups.SnacksDashboardFooter = { fg = c.comment, italic = true }
|
||||
groups.SnacksDashboardIcon = { fg = c.func }
|
||||
groups.SnacksDashboardKey = { fg = c.accent }
|
||||
groups.SnacksDashboardDesc = { fg = c.fg }
|
||||
groups.SnacksNotifierInfo = { fg = c.info }
|
||||
groups.SnacksNotifierWarn = { fg = c.warning }
|
||||
groups.SnacksNotifierError = { fg = c.error }
|
||||
|
||||
return groups
|
||||
end
|
||||
|
||||
return M
|
||||
130
init.lua
Normal file
130
init.lua
Normal file
@ -0,0 +1,130 @@
|
||||
local M = {}
|
||||
|
||||
---@class N8nConfig
|
||||
M.config = {
|
||||
transparent = false, -- enable transparent background
|
||||
terminal_colors = true, -- set terminal colors
|
||||
dim_inactive = false, -- dim inactive windows
|
||||
styles = {
|
||||
comments = { italic = true },
|
||||
keywords = {},
|
||||
functions = {},
|
||||
strings = {},
|
||||
variables = {},
|
||||
},
|
||||
---@type table<string, vim.api.keyset.highlight>
|
||||
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
|
||||
55
mnt/user-data/outputs/n8n.nvim/lua/lualine/themes/n8n.lua
Normal file
55
mnt/user-data/outputs/n8n.nvim/lua/lualine/themes/n8n.lua
Normal file
@ -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
|
||||
151
palette.lua
Normal file
151
palette.lua
Normal file
@ -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
|
||||
118
theme.lua
Normal file
118
theme.lua
Normal file
@ -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
|
||||
Reference in New Issue
Block a user