@carlesandres/house 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/LICENSE +21 -0
  3. package/README.md +99 -0
  4. package/package.json +67 -0
  5. package/src/Browser.tsx +472 -0
  6. package/src/Footer.tsx +151 -0
  7. package/src/HelpOverlay.tsx +130 -0
  8. package/src/cli/argv.ts +106 -0
  9. package/src/discovery/filter.ts +56 -0
  10. package/src/discovery/walk.ts +143 -0
  11. package/src/index.tsx +265 -0
  12. package/src/io/readFile.ts +14 -0
  13. package/src/keymap/browser.ts +229 -0
  14. package/src/keymap/keymap.ts +86 -0
  15. package/src/serve/css.ts +120 -0
  16. package/src/serve/openBrowser.ts +19 -0
  17. package/src/serve/render.ts +56 -0
  18. package/src/serve/server.ts +163 -0
  19. package/src/theme/atom.ts +23 -0
  20. package/src/theme/colors.ts +79 -0
  21. package/src/theme/loader.ts +110 -0
  22. package/src/theme/registry.ts +12 -0
  23. package/src/theme/resolve.ts +168 -0
  24. package/src/theme/themes/aura.json +58 -0
  25. package/src/theme/themes/ayu.json +69 -0
  26. package/src/theme/themes/carbonfox.json +201 -0
  27. package/src/theme/themes/catppuccin-frappe.json +186 -0
  28. package/src/theme/themes/catppuccin-macchiato.json +186 -0
  29. package/src/theme/themes/catppuccin.json +212 -0
  30. package/src/theme/themes/cobalt2.json +181 -0
  31. package/src/theme/themes/cursor.json +202 -0
  32. package/src/theme/themes/dracula.json +172 -0
  33. package/src/theme/themes/everforest.json +194 -0
  34. package/src/theme/themes/flexoki.json +190 -0
  35. package/src/theme/themes/github.json +186 -0
  36. package/src/theme/themes/gruvbox.json +195 -0
  37. package/src/theme/themes/kanagawa.json +180 -0
  38. package/src/theme/themes/lucent-orng.json +186 -0
  39. package/src/theme/themes/material.json +188 -0
  40. package/src/theme/themes/matrix.json +180 -0
  41. package/src/theme/themes/mercury.json +198 -0
  42. package/src/theme/themes/monokai.json +174 -0
  43. package/src/theme/themes/nightowl.json +174 -0
  44. package/src/theme/themes/nord.json +176 -0
  45. package/src/theme/themes/one-dark.json +184 -0
  46. package/src/theme/themes/opencode.json +198 -0
  47. package/src/theme/themes/orng.json +202 -0
  48. package/src/theme/themes/osaka-jade.json +193 -0
  49. package/src/theme/themes/palenight.json +175 -0
  50. package/src/theme/themes/rosepine.json +187 -0
  51. package/src/theme/themes/solarized.json +176 -0
  52. package/src/theme/themes/synthwave84.json +179 -0
  53. package/src/theme/themes/tokyonight.json +196 -0
  54. package/src/theme/themes/vercel.json +198 -0
  55. package/src/theme/themes/vesper.json +171 -0
  56. package/src/theme/themes/zenburn.json +176 -0
  57. package/src/theme/types.ts +109 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * themeAtom — signals the active theme identity to React.
3
+ *
4
+ * Components read this atom only to subscribe to re-renders; they pull the
5
+ * actual token values from the `colors` singleton (mutated by
6
+ * `setActiveTheme` before the re-render fires).
7
+ *
8
+ * Shape: `{ id, tone }` so that a future theme picker can write both fields
9
+ * atomically and the component sees a single re-render.
10
+ */
11
+
12
+ import * as Atom from "effect/unstable/reactivity/Atom"
13
+ import type { Tone } from "./types.ts"
14
+
15
+ export interface ThemeState {
16
+ readonly id: string
17
+ readonly tone: Tone
18
+ }
19
+
20
+ export const themeAtom: Atom.Writable<ThemeState, ThemeState> = Atom.make<ThemeState>({
21
+ id: "opencode",
22
+ tone: "dark",
23
+ })
@@ -0,0 +1,79 @@
1
+ import type { StyleDefinitionInput } from "@opentui/core"
2
+ import { resolveTheme } from "./resolve.ts"
3
+ import type { ColorPalette, ResolvedTheme, ThemeDefinition, Tone } from "./types.ts"
4
+
5
+ /**
6
+ * Adapt a resolved theme (opencode-shaped flat tokens) to the
7
+ * {@link ColorPalette} shape consumed by Browser / HelpOverlay / index.
8
+ *
9
+ * - UI tokens map name-for-name where they overlap.
10
+ * - `surface` ← `backgroundPanel`, `selectedBg` ← `backgroundElement`,
11
+ * `selectedBgInactive` ← `borderSubtle`.
12
+ * - `textStrong` borrows `markdownStrong` (the brightest/most-emphasized
13
+ * text token in opencode's palette).
14
+ * - `syntax` is a fully populated opentui tree-sitter scope map built from
15
+ * `markdown*` and `syntax*` tokens.
16
+ */
17
+ const buildPalette = (r: ResolvedTheme): ColorPalette => ({
18
+ background: r.background,
19
+ surface: r.backgroundPanel,
20
+ text: r.text,
21
+ textStrong: r.markdownStrong,
22
+ textMuted: r.textMuted,
23
+ border: r.border,
24
+ borderActive: r.borderActive,
25
+ selectedBg: r.backgroundElement,
26
+ selectedBgInactive: r.borderSubtle,
27
+ error: r.error,
28
+ syntax: buildSyntaxMap(r),
29
+ })
30
+
31
+ const buildSyntaxMap = (r: ResolvedTheme): Record<string, StyleDefinitionInput> => {
32
+ const codeBg = r.backgroundPanel
33
+ return {
34
+ keyword: { fg: r.syntaxKeyword, bold: true },
35
+ string: { fg: r.syntaxString },
36
+ comment: { fg: r.syntaxComment, italic: true },
37
+ number: { fg: r.syntaxNumber },
38
+ function: { fg: r.syntaxFunction },
39
+ type: { fg: r.syntaxType },
40
+ operator: { fg: r.syntaxOperator },
41
+ variable: { fg: r.syntaxVariable },
42
+ property: { fg: r.syntaxFunction },
43
+ "punctuation.bracket": { fg: r.syntaxPunctuation },
44
+ "punctuation.delimiter": { fg: r.syntaxPunctuation },
45
+ "punctuation.special": { fg: r.syntaxPunctuation },
46
+ "markup.heading": { fg: r.markdownHeading, bold: true },
47
+ "markup.heading.1": { fg: r.markdownHeading, bold: true, underline: true },
48
+ "markup.heading.2": { fg: r.markdownHeading, bold: true },
49
+ "markup.heading.3": { fg: r.markdownHeading },
50
+ "markup.bold": { fg: r.markdownStrong, bold: true },
51
+ "markup.strong": { fg: r.markdownStrong, bold: true },
52
+ "markup.italic": { fg: r.markdownEmph, italic: true },
53
+ "markup.list": { fg: r.markdownListItem },
54
+ "markup.quote": { fg: r.markdownBlockQuote, italic: true },
55
+ "markup.raw": { fg: r.markdownCode, bg: codeBg },
56
+ "markup.raw.block": { fg: r.markdownCodeBlock, bg: codeBg },
57
+ "markup.raw.inline": { fg: r.markdownCode, bg: codeBg },
58
+ "markup.link": { fg: r.markdownLink, underline: true },
59
+ "markup.link.label": { fg: r.markdownLinkText, underline: true },
60
+ "markup.link.url": { fg: r.markdownLink, underline: true },
61
+ label: { fg: r.markdownListItem },
62
+ conceal: { fg: r.borderSubtle },
63
+ default: { fg: r.markdownText },
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Active flat palette. Components import `colors` and read tokens
69
+ * directly. `setActiveTheme` mutates this in place so the reference stays
70
+ * stable (no Provider/context).
71
+ *
72
+ * Initial value uses the all-fallback resolution; `setActiveTheme` is
73
+ * called at boot from `index.tsx` before the React tree mounts.
74
+ */
75
+ export const colors: ColorPalette = buildPalette(resolveTheme({ theme: {} }, "dark"))
76
+
77
+ export const setActiveTheme = (definition: ThemeDefinition, tone: Tone): void => {
78
+ Object.assign(colors, buildPalette(resolveTheme(definition.source, tone)))
79
+ }
@@ -0,0 +1,110 @@
1
+ // THIS FILE IS AUTO-GENERATED by dev/build-themes.ts — do not edit by hand.
2
+ // Run `bun run build:themes` to regenerate after adding or updating themes.
3
+ import auraJson from "./themes/aura.json" with { type: "json" }
4
+ import ayuJson from "./themes/ayu.json" with { type: "json" }
5
+ import carbonfoxJson from "./themes/carbonfox.json" with { type: "json" }
6
+ import catppuccinJson from "./themes/catppuccin.json" with { type: "json" }
7
+ import catppuccinFrappeJson from "./themes/catppuccin-frappe.json" with { type: "json" }
8
+ import catppuccinMacchiatoJson from "./themes/catppuccin-macchiato.json" with { type: "json" }
9
+ import cobalt2Json from "./themes/cobalt2.json" with { type: "json" }
10
+ import cursorJson from "./themes/cursor.json" with { type: "json" }
11
+ import draculaJson from "./themes/dracula.json" with { type: "json" }
12
+ import everforestJson from "./themes/everforest.json" with { type: "json" }
13
+ import flexokiJson from "./themes/flexoki.json" with { type: "json" }
14
+ import githubJson from "./themes/github.json" with { type: "json" }
15
+ import gruvboxJson from "./themes/gruvbox.json" with { type: "json" }
16
+ import kanagawaJson from "./themes/kanagawa.json" with { type: "json" }
17
+ import lucentOrngJson from "./themes/lucent-orng.json" with { type: "json" }
18
+ import materialJson from "./themes/material.json" with { type: "json" }
19
+ import matrixJson from "./themes/matrix.json" with { type: "json" }
20
+ import mercuryJson from "./themes/mercury.json" with { type: "json" }
21
+ import monokaiJson from "./themes/monokai.json" with { type: "json" }
22
+ import nightowlJson from "./themes/nightowl.json" with { type: "json" }
23
+ import nordJson from "./themes/nord.json" with { type: "json" }
24
+ import oneDarkJson from "./themes/one-dark.json" with { type: "json" }
25
+ import opencodeJson from "./themes/opencode.json" with { type: "json" }
26
+ import orngJson from "./themes/orng.json" with { type: "json" }
27
+ import osakaJadeJson from "./themes/osaka-jade.json" with { type: "json" }
28
+ import palenightJson from "./themes/palenight.json" with { type: "json" }
29
+ import rosepineJson from "./themes/rosepine.json" with { type: "json" }
30
+ import solarizedJson from "./themes/solarized.json" with { type: "json" }
31
+ import synthwave84Json from "./themes/synthwave84.json" with { type: "json" }
32
+ import tokyonightJson from "./themes/tokyonight.json" with { type: "json" }
33
+ import vercelJson from "./themes/vercel.json" with { type: "json" }
34
+ import vesperJson from "./themes/vesper.json" with { type: "json" }
35
+ import zenburnJson from "./themes/zenburn.json" with { type: "json" }
36
+ import { isThemeJson } from "./resolve.ts"
37
+ import type { ThemeDefinition, ThemeJson } from "./types.ts"
38
+
39
+ interface BundledEntry {
40
+ readonly id: string
41
+ readonly json: unknown
42
+ }
43
+
44
+ const bundled: readonly BundledEntry[] = [
45
+ { id: "aura", json: auraJson },
46
+ { id: "ayu", json: ayuJson },
47
+ { id: "carbonfox", json: carbonfoxJson },
48
+ { id: "catppuccin", json: catppuccinJson },
49
+ { id: "catppuccin-frappe", json: catppuccinFrappeJson },
50
+ { id: "catppuccin-macchiato", json: catppuccinMacchiatoJson },
51
+ { id: "cobalt2", json: cobalt2Json },
52
+ { id: "cursor", json: cursorJson },
53
+ { id: "dracula", json: draculaJson },
54
+ { id: "everforest", json: everforestJson },
55
+ { id: "flexoki", json: flexokiJson },
56
+ { id: "github", json: githubJson },
57
+ { id: "gruvbox", json: gruvboxJson },
58
+ { id: "kanagawa", json: kanagawaJson },
59
+ { id: "lucent-orng", json: lucentOrngJson },
60
+ { id: "material", json: materialJson },
61
+ { id: "matrix", json: matrixJson },
62
+ { id: "mercury", json: mercuryJson },
63
+ { id: "monokai", json: monokaiJson },
64
+ { id: "nightowl", json: nightowlJson },
65
+ { id: "nord", json: nordJson },
66
+ { id: "one-dark", json: oneDarkJson },
67
+ { id: "opencode", json: opencodeJson },
68
+ { id: "orng", json: orngJson },
69
+ { id: "osaka-jade", json: osakaJadeJson },
70
+ { id: "palenight", json: palenightJson },
71
+ { id: "rosepine", json: rosepineJson },
72
+ { id: "solarized", json: solarizedJson },
73
+ { id: "synthwave84", json: synthwave84Json },
74
+ { id: "tokyonight", json: tokyonightJson },
75
+ { id: "vercel", json: vercelJson },
76
+ { id: "vesper", json: vesperJson },
77
+ { id: "zenburn", json: zenburnJson },
78
+ ]
79
+
80
+ const toDefinition = (id: string, raw: unknown): ThemeDefinition | null => {
81
+ if (!isThemeJson(raw)) return null
82
+ const json = raw as ThemeJson
83
+ return { id, name: json.name ?? id, source: json }
84
+ }
85
+
86
+ /** Load all bundled themes, indexed by id. Invalid entries are dropped. */
87
+ export const loadBundledThemes = (): Map<string, ThemeDefinition> => {
88
+ const map = new Map<string, ThemeDefinition>()
89
+ for (const { id, json } of bundled) {
90
+ const def = toDefinition(id, json)
91
+ if (def) map.set(id, def)
92
+ }
93
+ return map
94
+ }
95
+
96
+ /**
97
+ * Stub for user-supplied themes. A future release will load these from the
98
+ * XDG config dir and from project-local `.house/themes/`. Until then,
99
+ * returns an empty map.
100
+ */
101
+ export const loadUserThemes = async (): Promise<Map<string, ThemeDefinition>> => {
102
+ return new Map()
103
+ }
104
+
105
+ /** Bundled + user themes merged. User themes override built-ins by id. */
106
+ export const loadAllThemes = async (): Promise<Map<string, ThemeDefinition>> => {
107
+ const all = loadBundledThemes()
108
+ for (const [id, def] of await loadUserThemes()) all.set(id, def)
109
+ return all
110
+ }
@@ -0,0 +1,12 @@
1
+ import { loadBundledThemes } from "./loader.ts"
2
+ import type { ThemeDefinition } from "./types.ts"
3
+
4
+ const map: Map<string, ThemeDefinition> = loadBundledThemes()
5
+
6
+ /** All known themes. Order is the bundled-themes order in `loader.ts`. */
7
+ export const themeDefinitions: readonly ThemeDefinition[] = [...map.values()]
8
+
9
+ export const getThemeDefinition = (id: string): ThemeDefinition | undefined => map.get(id)
10
+
11
+ export const isThemeId = (value: unknown): value is string =>
12
+ typeof value === "string" && map.has(value)
@@ -0,0 +1,168 @@
1
+ import type {
2
+ ColorValue,
3
+ HexColor,
4
+ ResolvedTheme,
5
+ ThemeJson,
6
+ ThemeTokens,
7
+ TokenName,
8
+ Tone,
9
+ } from "./types.ts"
10
+
11
+ /**
12
+ * Hard-coded safe defaults for every UI / markdown / syntax token. Used when
13
+ * a theme JSON omits a token entirely (validation is permissive — opencode
14
+ * does the same). Fallback values are reasonable greys so the app stays
15
+ * legible even with a near-empty theme.
16
+ */
17
+ const HARD_FALLBACK_RAW: Readonly<Record<TokenName, HexColor>> = {
18
+ primary: "#7AA2F7",
19
+ secondary: "#9ECE6A",
20
+ accent: "#BB9AF7",
21
+ error: "#F7768E",
22
+ warning: "#E0AF68",
23
+ success: "#9ECE6A",
24
+ info: "#7DCFFF",
25
+ text: "#D8DEE9",
26
+ textMuted: "#7B8794",
27
+ selectedListItemText: "#FFFFFF",
28
+ background: "#1A1B26",
29
+ backgroundPanel: "#24283B",
30
+ backgroundElement: "#414868",
31
+ border: "#3B4261",
32
+ borderActive: "#7AA2F7",
33
+ borderSubtle: "#292E42",
34
+ markdownText: "#D8DEE9",
35
+ markdownHeading: "#7AA2F7",
36
+ markdownLink: "#7DCFFF",
37
+ markdownLinkText: "#7AA2F7",
38
+ markdownCode: "#9ECE6A",
39
+ markdownBlockQuote: "#7B8794",
40
+ markdownEmph: "#E0AF68",
41
+ markdownStrong: "#FFFFFF",
42
+ markdownHorizontalRule: "#7B8794",
43
+ markdownListItem: "#7AA2F7",
44
+ markdownListEnumeration: "#BB9AF7",
45
+ markdownImage: "#7DCFFF",
46
+ markdownImageText: "#BB9AF7",
47
+ markdownCodeBlock: "#D8DEE9",
48
+ syntaxComment: "#7B8794",
49
+ syntaxKeyword: "#7AA2F7",
50
+ syntaxFunction: "#7DCFFF",
51
+ syntaxVariable: "#D8DEE9",
52
+ syntaxString: "#9ECE6A",
53
+ syntaxNumber: "#BB9AF7",
54
+ syntaxType: "#E0AF68",
55
+ syntaxOperator: "#7AA2F7",
56
+ syntaxPunctuation: "#D8DEE9",
57
+ }
58
+
59
+ const HEX_RE_INIT = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/
60
+ const lowerHex = (hex: HexColor): HexColor => {
61
+ const v = hex.replace("#", "")
62
+ const expanded =
63
+ v.length === 3 || v.length === 4
64
+ ? v
65
+ .split("")
66
+ .map((c) => c + c)
67
+ .join("")
68
+ : v
69
+ const rgb = expanded.length === 8 ? expanded.slice(0, 6) : expanded
70
+ return `#${rgb.toLowerCase()}` as HexColor
71
+ }
72
+ // Sanity: ensure HARD_FALLBACK_RAW matches the hex regex (catch a typo at load).
73
+ for (const v of Object.values(HARD_FALLBACK_RAW)) {
74
+ if (!HEX_RE_INIT.test(v)) throw new Error(`bad fallback hex: ${v}`)
75
+ }
76
+ const HARD_FALLBACK: Readonly<Record<TokenName, HexColor>> = Object.fromEntries(
77
+ Object.entries(HARD_FALLBACK_RAW).map(([k, v]) => [k, lowerHex(v)]),
78
+ ) as Readonly<Record<TokenName, HexColor>>
79
+
80
+ /**
81
+ * Tokens that fall back to another token (rather than `HARD_FALLBACK`) when
82
+ * the theme omits them. Mirrors opencode's resolve behavior.
83
+ */
84
+ const TOKEN_FALLBACK: Partial<Record<TokenName, TokenName>> = {
85
+ selectedListItemText: "background",
86
+ markdownText: "text",
87
+ markdownCodeBlock: "text",
88
+ borderSubtle: "border",
89
+ }
90
+
91
+ const HEX_RE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/
92
+
93
+ const isHex = (value: string): value is HexColor => HEX_RE.test(value)
94
+
95
+ /** Normalize a hex value to `#rrggbb` (lowercase, 6-digit). */
96
+ const normalizeHex = (value: HexColor): HexColor => {
97
+ const v = value.replace("#", "")
98
+ const expanded =
99
+ v.length === 3 || v.length === 4
100
+ ? v
101
+ .split("")
102
+ .map((c) => c + c)
103
+ .join("")
104
+ : v
105
+ const rgb = expanded.length === 8 ? expanded.slice(0, 6) : expanded
106
+ return `#${rgb.toLowerCase()}` as HexColor
107
+ }
108
+
109
+ /**
110
+ * Resolve a single side of a {dark,light} variant — i.e. a string that's
111
+ * either a hex literal or a name in the theme's `defs` map. Returns `null`
112
+ * if the input doesn't resolve (caller falls back).
113
+ */
114
+ const resolveSide = (value: string, defs: Record<string, string>): HexColor | null => {
115
+ if (isHex(value)) return normalizeHex(value)
116
+ const looked = defs[value]
117
+ if (looked && isHex(looked)) return normalizeHex(looked)
118
+ return null
119
+ }
120
+
121
+ /** Resolve a single ColorValue (variant, hex, or defs ref) for a tone. */
122
+ export const resolveColorValue = (
123
+ value: ColorValue | undefined,
124
+ tone: Tone,
125
+ defs: Record<string, string> = {},
126
+ ): HexColor | null => {
127
+ if (value === undefined) return null
128
+ if (typeof value === "string") return resolveSide(value, defs)
129
+ const side = value[tone]
130
+ return resolveSide(side, defs)
131
+ }
132
+
133
+ /**
134
+ * Resolve a theme JSON to a flat record of `{ token → #rrggbb }` for the
135
+ * given tone. Missing tokens fall back via `TOKEN_FALLBACK` (chained) and
136
+ * ultimately `HARD_FALLBACK`.
137
+ */
138
+ export const resolveTheme = (theme: ThemeJson, tone: Tone): ResolvedTheme => {
139
+ const defs = theme.defs ?? {}
140
+ const out: Partial<Record<TokenName, HexColor>> = {}
141
+
142
+ const tokenNames = Object.keys(HARD_FALLBACK) as readonly TokenName[]
143
+ const seen = new Set<TokenName>()
144
+ const resolveOne = (name: TokenName): HexColor => {
145
+ if (seen.has(name)) return HARD_FALLBACK[name]
146
+ seen.add(name)
147
+ const direct = resolveColorValue(theme.theme[name], tone, defs)
148
+ if (direct) return direct
149
+ const fallback = TOKEN_FALLBACK[name]
150
+ if (fallback) return resolveOne(fallback)
151
+ return HARD_FALLBACK[name]
152
+ }
153
+
154
+ for (const name of tokenNames) {
155
+ seen.clear()
156
+ out[name] = resolveOne(name)
157
+ }
158
+ return out as ResolvedTheme
159
+ }
160
+
161
+ /** Permissive runtime validation: any object with a `theme` object passes. */
162
+ export const isThemeJson = (value: unknown): value is ThemeJson => {
163
+ if (typeof value !== "object" || value === null) return false
164
+ const v = value as Record<string, unknown>
165
+ return typeof v["theme"] === "object" && v["theme"] !== null
166
+ }
167
+
168
+ export type { ThemeTokens }
@@ -0,0 +1,58 @@
1
+ {
2
+ "defs": {
3
+ "darkBg": "#0f0f0f",
4
+ "darkBgPanel": "#15141b",
5
+ "darkBorder": "#2d2d2d",
6
+ "darkFgMuted": "#6d6d6d",
7
+ "darkFg": "#edecee",
8
+ "purple": "#a277ff",
9
+ "pink": "#f694ff",
10
+ "blue": "#82e2ff",
11
+ "red": "#ff6767",
12
+ "orange": "#ffca85",
13
+ "cyan": "#61ffca",
14
+ "green": "#9dff65"
15
+ },
16
+ "theme": {
17
+ "primary": "purple",
18
+ "secondary": "pink",
19
+ "accent": "purple",
20
+ "error": "red",
21
+ "warning": "orange",
22
+ "success": "cyan",
23
+ "info": "purple",
24
+ "text": "darkFg",
25
+ "textMuted": "darkFgMuted",
26
+ "background": "darkBg",
27
+ "backgroundPanel": "darkBgPanel",
28
+ "backgroundElement": "darkBgPanel",
29
+ "border": "darkBorder",
30
+ "borderActive": "darkFgMuted",
31
+ "borderSubtle": "darkBorder",
32
+ "markdownText": "darkFg",
33
+ "markdownHeading": "purple",
34
+ "markdownLink": "pink",
35
+ "markdownLinkText": "purple",
36
+ "markdownCode": "cyan",
37
+ "markdownBlockQuote": "darkFgMuted",
38
+ "markdownEmph": "orange",
39
+ "markdownStrong": "purple",
40
+ "markdownHorizontalRule": "darkFgMuted",
41
+ "markdownListItem": "purple",
42
+ "markdownListEnumeration": "purple",
43
+ "markdownImage": "pink",
44
+ "markdownImageText": "purple",
45
+ "markdownCodeBlock": "darkFg",
46
+ "syntaxComment": "darkFgMuted",
47
+ "syntaxKeyword": "pink",
48
+ "syntaxFunction": "purple",
49
+ "syntaxVariable": "purple",
50
+ "syntaxString": "cyan",
51
+ "syntaxNumber": "green",
52
+ "syntaxType": "purple",
53
+ "syntaxOperator": "pink",
54
+ "syntaxPunctuation": "darkFg"
55
+ },
56
+ "name": "Aura",
57
+ "$schema": "../../../schema/house-theme.schema.json"
58
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "defs": {
3
+ "darkBg": "#0B0E14",
4
+ "darkBgAlt": "#0D1017",
5
+ "darkLine": "#11151C",
6
+ "darkPanel": "#0F131A",
7
+ "darkFg": "#BFBDB6",
8
+ "darkFgMuted": "#565B66",
9
+ "darkGutter": "#6C7380",
10
+ "darkTag": "#39BAE6",
11
+ "darkFunc": "#FFB454",
12
+ "darkEntity": "#59C2FF",
13
+ "darkString": "#AAD94C",
14
+ "darkRegexp": "#95E6CB",
15
+ "darkMarkup": "#F07178",
16
+ "darkKeyword": "#FF8F40",
17
+ "darkSpecial": "#E6B673",
18
+ "darkComment": "#ACB6BF",
19
+ "darkConstant": "#D2A6FF",
20
+ "darkOperator": "#F29668",
21
+ "darkAdded": "#7FD962",
22
+ "darkRemoved": "#F26D78",
23
+ "darkAccent": "#E6B450",
24
+ "darkError": "#D95757",
25
+ "darkIndentActive": "#6C7380"
26
+ },
27
+ "theme": {
28
+ "primary": "darkEntity",
29
+ "secondary": "darkConstant",
30
+ "accent": "darkAccent",
31
+ "error": "darkError",
32
+ "warning": "darkSpecial",
33
+ "success": "darkAdded",
34
+ "info": "darkTag",
35
+ "text": "darkFg",
36
+ "textMuted": "darkFgMuted",
37
+ "background": "darkBg",
38
+ "backgroundPanel": "darkPanel",
39
+ "backgroundElement": "darkBgAlt",
40
+ "border": "darkGutter",
41
+ "borderActive": "darkIndentActive",
42
+ "borderSubtle": "darkLine",
43
+ "markdownText": "darkFg",
44
+ "markdownHeading": "darkConstant",
45
+ "markdownLink": "darkEntity",
46
+ "markdownLinkText": "darkTag",
47
+ "markdownCode": "darkString",
48
+ "markdownBlockQuote": "darkSpecial",
49
+ "markdownEmph": "darkSpecial",
50
+ "markdownStrong": "darkFunc",
51
+ "markdownHorizontalRule": "darkFgMuted",
52
+ "markdownListItem": "darkEntity",
53
+ "markdownListEnumeration": "darkTag",
54
+ "markdownImage": "darkEntity",
55
+ "markdownImageText": "darkTag",
56
+ "markdownCodeBlock": "darkFg",
57
+ "syntaxComment": "darkComment",
58
+ "syntaxKeyword": "darkKeyword",
59
+ "syntaxFunction": "darkFunc",
60
+ "syntaxVariable": "darkEntity",
61
+ "syntaxString": "darkString",
62
+ "syntaxNumber": "darkConstant",
63
+ "syntaxType": "darkSpecial",
64
+ "syntaxOperator": "darkOperator",
65
+ "syntaxPunctuation": "darkFg"
66
+ },
67
+ "name": "Ayu",
68
+ "$schema": "../../../schema/house-theme.schema.json"
69
+ }