opentui-markdown-render 0.0.0-stage → 0.2.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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +27 -0
  3. package/README.md +223 -2
  4. package/bin/otmd.tsx +99 -0
  5. package/native/Cargo.lock +3708 -0
  6. package/native/Cargo.toml +28 -0
  7. package/native/build.rs +3 -0
  8. package/native/src/lib.rs +880 -0
  9. package/package.json +67 -4
  10. package/prebuilds/linux-x64-gnu/opentui_markdown_render.node +4 -0
  11. package/src/app.tsx +180 -0
  12. package/src/cli.ts +63 -0
  13. package/src/config/index.ts +46 -0
  14. package/src/config/load.ts +337 -0
  15. package/src/config/resolve.ts +36 -0
  16. package/src/config/theme.ts +110 -0
  17. package/src/config/types.ts +105 -0
  18. package/src/core/document.ts +44 -0
  19. package/src/core/frame.ts +144 -0
  20. package/src/core/image.ts +9 -0
  21. package/src/core/index.ts +6 -0
  22. package/src/core/layout.ts +27 -0
  23. package/src/core/math.ts +170 -0
  24. package/src/core/parse.ts +208 -0
  25. package/src/core/tables.ts +58 -0
  26. package/src/graphics.ts +85 -0
  27. package/src/headings.ts +77 -0
  28. package/src/index.ts +107 -0
  29. package/src/math/index.ts +86 -0
  30. package/src/math/native.ts +39 -0
  31. package/src/math/renderer.ts +84 -0
  32. package/src/math/validate.ts +44 -0
  33. package/src/media.tsx +267 -0
  34. package/src/merman/class/dagre-layout.ts +171 -0
  35. package/src/merman/class/diagram.ts +8 -0
  36. package/src/merman/class/drawing.ts +343 -0
  37. package/src/merman/class/labels.ts +38 -0
  38. package/src/merman/class/layout.ts +531 -0
  39. package/src/merman/class/parser.ts +308 -0
  40. package/src/merman/class/render-grid.ts +18 -0
  41. package/src/merman/class/style.ts +27 -0
  42. package/src/merman/class/types.ts +57 -0
  43. package/src/merman/core/canvas.ts +228 -0
  44. package/src/merman/core/color/style.ts +56 -0
  45. package/src/merman/core/drawing.ts +307 -0
  46. package/src/merman/core/geometry.ts +347 -0
  47. package/src/merman/core/mermaid.ts +38 -0
  48. package/src/merman/core/render-grid.ts +51 -0
  49. package/src/merman/core/spatial.ts +243 -0
  50. package/src/merman/core/text-lines.ts +32 -0
  51. package/src/merman/core/text.ts +44 -0
  52. package/src/merman/detect.ts +19 -0
  53. package/src/merman/diagnostics.ts +16 -0
  54. package/src/merman/diagram.ts +268 -0
  55. package/src/merman/flowchart/drawing.ts +433 -0
  56. package/src/merman/flowchart/labels.ts +144 -0
  57. package/src/merman/flowchart/layout.ts +1057 -0
  58. package/src/merman/flowchart/options.ts +12 -0
  59. package/src/merman/flowchart/parser.ts +477 -0
  60. package/src/merman/flowchart/render.ts +10 -0
  61. package/src/merman/flowchart/routing.ts +1429 -0
  62. package/src/merman/flowchart/style.ts +79 -0
  63. package/src/merman/flowchart/types.ts +63 -0
  64. package/src/merman/gantt/diagram.ts +8 -0
  65. package/src/merman/gantt/drawing.ts +193 -0
  66. package/src/merman/gantt/parser.ts +198 -0
  67. package/src/merman/gantt/render-grid.ts +17 -0
  68. package/src/merman/gantt/style.ts +36 -0
  69. package/src/merman/gantt/types.ts +45 -0
  70. package/src/merman/gitgraph/diagram.ts +8 -0
  71. package/src/merman/gitgraph/drawing.ts +234 -0
  72. package/src/merman/gitgraph/parser.ts +234 -0
  73. package/src/merman/gitgraph/render-grid.ts +17 -0
  74. package/src/merman/gitgraph/style.ts +37 -0
  75. package/src/merman/gitgraph/types.ts +36 -0
  76. package/src/merman/palette.ts +60 -0
  77. package/src/merman/sequence/diagram.ts +8 -0
  78. package/src/merman/sequence/drawing.ts +288 -0
  79. package/src/merman/sequence/options.ts +8 -0
  80. package/src/merman/sequence/parser.ts +303 -0
  81. package/src/merman/sequence/placement.ts +692 -0
  82. package/src/merman/sequence/render-grid.ts +22 -0
  83. package/src/merman/sequence/style.ts +81 -0
  84. package/src/merman/sequence/types.ts +74 -0
  85. package/src/merman/state/diagram.ts +8 -0
  86. package/src/merman/state/drawing.ts +363 -0
  87. package/src/merman/state/endpoint.ts +15 -0
  88. package/src/merman/state/layout.ts +1134 -0
  89. package/src/merman/state/note.ts +59 -0
  90. package/src/merman/state/options.ts +11 -0
  91. package/src/merman/state/parser.ts +245 -0
  92. package/src/merman/state/render-grid.ts +22 -0
  93. package/src/merman/state/routing.ts +1522 -0
  94. package/src/merman/state/search.ts +103 -0
  95. package/src/merman/state/style.ts +52 -0
  96. package/src/merman/state/types.ts +63 -0
  97. package/src/merman/state/visible-model.ts +77 -0
  98. package/src/merman/timeline/diagram.ts +8 -0
  99. package/src/merman/timeline/drawing.ts +109 -0
  100. package/src/merman/timeline/parser.ts +119 -0
  101. package/src/merman/timeline/render-grid.ts +17 -0
  102. package/src/merman/timeline/style.ts +36 -0
  103. package/src/merman/timeline/types.ts +31 -0
  104. package/src/merman.ts +3 -0
  105. package/src/statusline.tsx +183 -0
  106. package/src/theme/colors.ts +11 -0
  107. package/src/theme/defaults.ts +190 -0
  108. package/src/theme/index.ts +7 -0
  109. package/src/theme/load.ts +39 -0
  110. package/src/theme/resolve.ts +167 -0
  111. package/src/theme/syntax.ts +96 -0
  112. package/src/theme/types.ts +151 -0
  113. package/src/view/code.tsx +27 -0
  114. package/src/view/document-slots.ts +111 -0
  115. package/src/view/document-table.tsx +98 -0
  116. package/src/view/document.tsx +195 -0
  117. package/src/view/frame.tsx +83 -0
  118. package/src/view/inline-flow.tsx +113 -0
  119. package/src/view/inline-layout.ts +149 -0
  120. package/src/view/inline-math.ts +42 -0
  121. package/src/view/inline-style.ts +103 -0
  122. package/src/view/math.tsx +85 -0
  123. package/src/view/mermaid.tsx +128 -0
  124. package/src/view/table.ts +100 -0
  125. package/themes/dark.json +32 -0
  126. package/themes/example.jsonc +98 -0
  127. package/themes/light.json +32 -0
  128. package/themes/solarized-dark.json +32 -0
  129. package/themes/solarized-light.json +32 -0
@@ -0,0 +1,128 @@
1
+ import { createEffect, createMemo, Show, type Accessor } from "solid-js"
2
+ import { type MouseEvent, type TextRenderable } from "@opentui/core"
3
+ import { measureMermaidDiagram, type PreparedDiagram } from "../merman/diagram"
4
+ import { detectMermaidDiagram } from "../merman/detect"
5
+ import { MermaidSyntaxError } from "../merman/diagnostics"
6
+ import { DiagramCanvasSizeError } from "../merman/core/canvas"
7
+ import { resolveOpenCodeDiagramPalette } from "../merman/palette"
8
+ import type { Theme } from "../theme/types"
9
+ import type { MermaidConfig } from "../config/types"
10
+ import { defaultHeadingStyles, type HeadingStyles } from "../headings"
11
+ import { CodeBlock } from "./code"
12
+
13
+ export type MermaidDiagramViewProps = {
14
+ source: string
15
+ theme: Theme
16
+ columns: number
17
+ mermaidOptions?: MermaidConfig
18
+ headings?: HeadingStyles
19
+ onDiagnostic?: (diagnostic: { level: "error"; message: string }) => void
20
+ }
21
+
22
+ function DiagramText(props: { prepared: Accessor<PreparedDiagram> }) {
23
+ let ref: TextRenderable | undefined
24
+ let dragX: number | undefined
25
+ createEffect(() => {
26
+ if (!ref) return
27
+ const prepared = props.prepared()
28
+ ref.content = prepared.text
29
+ ref.height = prepared.height
30
+ ref.width = "100%"
31
+ ref.wrapMode = "none"
32
+ ref.selectable = false
33
+ ref.marginTop = 1
34
+ })
35
+ return <text ref={(renderable) => {
36
+ ref = renderable
37
+ if (!ref) return
38
+ ref.onMouseDown = (event: MouseEvent) => {
39
+ if (event.button !== 0) return
40
+ ref?.ctx.clearSelection()
41
+ dragX = event.x
42
+ event.preventDefault()
43
+ event.stopPropagation()
44
+ }
45
+ ref.onMouseDrag = (event: MouseEvent) => {
46
+ if (dragX === undefined) return
47
+ const dx = event.x - dragX
48
+ dragX = event.x
49
+ if (ref && dx) ref.scrollX -= dx
50
+ event.preventDefault()
51
+ event.stopPropagation()
52
+ }
53
+ ref.onMouseDragEnd = () => { dragX = undefined }
54
+ ref.onMouseUp = () => { dragX = undefined }
55
+ ref.onMouseScroll = (event: MouseEvent) => {
56
+ const direction = event.scroll?.direction
57
+ if (direction !== "left" && direction !== "right") return
58
+ event.preventDefault()
59
+ event.stopPropagation()
60
+ }
61
+ }} />
62
+ }
63
+
64
+ export function MermaidDiagramView(props: MermaidDiagramViewProps) {
65
+ let lastGood: PreparedDiagram | undefined
66
+ const prepared = createMemo(() => {
67
+ const source = props.source
68
+ const kind = detectMermaidDiagram(source)
69
+ if (kind && lastGood && lastGood.kind !== kind) lastGood = undefined
70
+ const options = {
71
+ compact: props.mermaidOptions?.compact,
72
+ classLayout: props.mermaidOptions?.classLayout,
73
+ layoutMaxWidth: Math.min(props.mermaidOptions?.layoutMaxWidth ?? 120, Math.max(1, props.columns)),
74
+ colors: resolveOpenCodeDiagramPalette(props.theme),
75
+ palette: props.theme.palette,
76
+ }
77
+ const restore = () => {
78
+ if (!lastGood) return undefined
79
+ try {
80
+ // Reprepare with the current width and palette, never display an old
81
+ // StyledText raster carrying stale colors or geometry.
82
+ return measureMermaidDiagram(lastGood.source, options)
83
+ } catch {
84
+ return undefined
85
+ }
86
+ }
87
+ try {
88
+ const result = measureMermaidDiagram(source, options)
89
+ if (result && result.height > 0) {
90
+ lastGood = result
91
+ return result
92
+ }
93
+ if (lastGood && (!kind || lastGood.kind === kind)) {
94
+ return restore()
95
+ }
96
+ } catch (error) {
97
+ if (error instanceof MermaidSyntaxError && lastGood && lastGood.kind === kind) {
98
+ return restore()
99
+ }
100
+ if (error instanceof MermaidSyntaxError && kind) {
101
+ const lines = source.split("\n")
102
+ if (error.lineNumber > 2 && !lines.slice(error.lineNumber).some((line) => line.trim())) {
103
+ try {
104
+ const result = measureMermaidDiagram(lines.slice(0, error.lineNumber - 1).join("\n"), options)
105
+ if (result?.height) {
106
+ lastGood = result
107
+ return result
108
+ }
109
+ } catch (prefixError) {
110
+ if (!(prefixError instanceof MermaidSyntaxError || prefixError instanceof DiagramCanvasSizeError)) {
111
+ props.onDiagnostic?.({ level: "error", message: prefixError instanceof Error ? prefixError.message : String(prefixError) })
112
+ }
113
+ }
114
+ }
115
+ }
116
+ if (!(error instanceof MermaidSyntaxError || error instanceof DiagramCanvasSizeError)) {
117
+ props.onDiagnostic?.({ level: "error", message: error instanceof Error ? error.message : String(error) })
118
+ }
119
+ }
120
+ return undefined
121
+ })
122
+ return <box width="100%" flexDirection="column" flexShrink={0}>
123
+ <Show when={prepared()} fallback={<CodeBlock content={props.source} language="mermaid"
124
+ theme={props.theme} headings={props.headings ?? defaultHeadingStyles} />}>
125
+ {(value) => <DiagramText prepared={value} />}
126
+ </Show>
127
+ </box>
128
+ }
@@ -0,0 +1,100 @@
1
+ import {
2
+ BoxRenderable,
3
+ TextTableRenderable,
4
+ type MouseEvent,
5
+ type RenderContext,
6
+ } from "@opentui/core"
7
+
8
+ // In content mode a table keeps its natural columns even when its layout box is
9
+ // narrower, so its drawn width can be larger than `table.width`. The layout
10
+ // itself knows the drawn width; fall back to the box when the field is gone.
11
+ function tableWidth(table: TextTableRenderable): number {
12
+ const layout = (
13
+ table as unknown as { computeLayout?: (maxWidth?: number) => { tableWidth?: number } | undefined }
14
+ ).computeLayout?.(undefined)
15
+ const width = layout?.tableWidth
16
+ if (typeof width === "number" && Number.isFinite(width) && width > 0) return Math.round(width)
17
+ return Number.isFinite(table.width) ? Math.round(table.width) : 0
18
+ }
19
+
20
+ // OpenTUI's table draws itself into the bounds it is given, so a table wider
21
+ // than the document is clipped by the terminal. The wrapper keeps the table at
22
+ // its natural width and moves it sideways, the same way a Mermaid diagram is
23
+ // panned. A table that actually needs the scroller gives up cell selection:
24
+ // otherwise a drag would select text instead of panning.
25
+ export class ScrollableTableRenderable extends BoxRenderable {
26
+ protected readonly table: TextTableRenderable
27
+ protected offset = 0
28
+ protected panEnabled = true
29
+ private dragX: number | undefined
30
+
31
+ constructor(ctx: RenderContext, table: TextTableRenderable) {
32
+ super(ctx, {
33
+ width: "100%",
34
+ flexDirection: "row",
35
+ flexShrink: 0,
36
+ overflow: "hidden",
37
+ })
38
+ this.table = table
39
+ table.flexShrink = 0
40
+ this.add(table)
41
+ this.onMouseDown = (event: MouseEvent) => {
42
+ if (event.button !== 0) return
43
+ this.dragX = event.x
44
+ }
45
+ this.onMouseDrag = (event: MouseEvent) => {
46
+ if (this.dragX === undefined || !this.panEnabled) return
47
+ const dx = event.x - this.dragX
48
+ this.dragX = event.x
49
+ if (!dx || !this.overflows()) return
50
+ event.preventDefault()
51
+ event.stopPropagation()
52
+ this.scrollBy(-dx)
53
+ }
54
+ this.onMouseDragEnd = () => {
55
+ this.dragX = undefined
56
+ }
57
+ this.onMouseUp = () => {
58
+ this.dragX = undefined
59
+ }
60
+ // A vertical wheel is left to the host: the document scroll box owns it.
61
+ this.onMouseScroll = (event: MouseEvent) => {
62
+ const direction = event.scroll?.direction
63
+ if (!this.panEnabled || (direction !== "left" && direction !== "right")) return
64
+ if (!this.overflows()) return
65
+ event.preventDefault()
66
+ event.stopPropagation()
67
+ this.scrollBy(direction === "left" ? -2 : 2)
68
+ }
69
+ }
70
+
71
+ // A table that fits keeps cell selection; only a table that has to scroll
72
+ // gives its drag to the scroller.
73
+ protected override onResize(width: number, _height: number) {
74
+ super.onResize(width, _height)
75
+ this.syncOverflowState(width)
76
+ }
77
+
78
+ protected syncOverflowState(width = this.width) {
79
+ // A Solid custom renderable receives props before Yoga assigns its first
80
+ // width. Measuring the table at that point can poison the layout cache.
81
+ if (!Number.isFinite(width) || width <= 0) return
82
+ const viewport = Math.round(width)
83
+ const max = Math.max(0, tableWidth(this.table) - viewport)
84
+ this.offset = this.panEnabled ? Math.min(this.offset, max) : 0
85
+ this.table.marginLeft = -this.offset
86
+ this.table.selectable = !this.panEnabled || max === 0
87
+ }
88
+
89
+ private overflows(width = this.width) {
90
+ const viewportWidth = Number.isFinite(width) ? Math.round(width) : 0
91
+ return tableWidth(this.table) > viewportWidth
92
+ }
93
+
94
+ private scrollBy(delta: number) {
95
+ const viewportWidth = Number.isFinite(this.width) ? Math.round(this.width) : 0
96
+ const max = Math.max(0, tableWidth(this.table) - viewportWidth)
97
+ this.offset = Math.max(0, Math.min(max, this.offset + delta))
98
+ this.table.marginLeft = -this.offset
99
+ }
100
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "mode": "dark",
3
+ "accent": "#58a6ff",
4
+ "categorical": ["#58a6ff", "#d2a8ff", "#3fb950", "#d29922", "#f85149", "#ffa657"],
5
+ "text": {
6
+ "base": "#e6edf3",
7
+ "muted": "#8b949e",
8
+ "feedback": { "error": "#f85149", "warning": "#d29922", "success": "#3fb950", "info": "#58a6ff" },
9
+ "action": { "primary": { "focused": "#58a6ff" } }
10
+ },
11
+ "background": { "base": "#0d1117" },
12
+ "border": { "base": "#30363d" },
13
+ "frame": { "border": "#30363d", "title": "#8b949e" },
14
+ "markdown": {
15
+ "text": "#e6edf3", "heading": "#d2a8ff",
16
+ "heading1": "#58a6ff", "heading2": "#d2a8ff", "heading3": "#d2a8ff",
17
+ "heading4": "#8b949e", "heading5": "#8b949e", "heading6": "#8b949e",
18
+ "link": "#58a6ff", "linkText": "#58a6ff", "code": "#ffa657",
19
+ "blockQuote": "#8b949e", "emphasis": "#e6edf3", "strong": "#e6edf3",
20
+ "horizontalRule": "#30363d", "listItem": "#e6edf3", "listEnumeration": "#e6edf3",
21
+ "image": "#58a6ff", "imageText": "#58a6ff", "codeBlock": "#e6edf3"
22
+ },
23
+ "syntax": {
24
+ "comment": "#8b949e", "keyword": "#ff7b72", "function": "#d2a8ff",
25
+ "variable": "#ffa657", "string": "#a5d6ff", "number": "#79c0ff",
26
+ "type": "#ffa657", "operator": "#ff7b72", "punctuation": "#c9d1d9"
27
+ },
28
+ "diff": {
29
+ "text": { "added": "#3fb950", "removed": "#f85149", "context": "#8b949e" },
30
+ "background": { "added": "#12261e", "removed": "#25171c", "context": "#161b22" }
31
+ }
32
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ // The semantic mode controls contrast-sensitive derived colours.
3
+ "mode": "dark",
4
+
5
+ // Optional fixed Mermaid diagram palette. Omit it to derive diagram colours.
6
+ "palette": [
7
+ "#58a6ff", "#d2a8ff", "#3fb950", "#d29922", "#f85149", "#ffa657"
8
+ ],
9
+
10
+ // Main accent and the categorical colours used by diagrams and UI elements.
11
+ "accent": "#58a6ff",
12
+ "categorical": ["#58a6ff", "#d2a8ff", "#3fb950", "#d29922", "#f85149", "#ffa657"],
13
+
14
+ "text": {
15
+ "base": "#e6edf3",
16
+ "muted": "#8b949e",
17
+ "feedback": {
18
+ "error": "#f85149",
19
+ "warning": "#d29922",
20
+ "success": "#3fb950",
21
+ "info": "#58a6ff"
22
+ },
23
+ "action": {
24
+ "primary": {
25
+ "focused": "#58a6ff"
26
+ }
27
+ }
28
+ },
29
+
30
+ "background": {
31
+ "base": "#0d1117"
32
+ },
33
+ "border": {
34
+ "base": "#30363d"
35
+ },
36
+
37
+ // Frame and statusline are optional in the resolved API; these examples show
38
+ // the complete file shape and can be adjusted independently.
39
+ "frame": {
40
+ "border": "#30363d",
41
+ "title": "#8b949e"
42
+ },
43
+ "statusline": {
44
+ "background": "#161b22",
45
+ "foreground": "#e6edf3",
46
+ "title": "#58a6ff",
47
+ "muted": "#8b949e",
48
+ "border": "#58a6ff"
49
+ },
50
+
51
+ "markdown": {
52
+ "text": "#e6edf3",
53
+ "heading": "#d2a8ff",
54
+ "heading1": "#58a6ff",
55
+ "heading2": "#d2a8ff",
56
+ "heading3": "#d2a8ff",
57
+ "heading4": "#8b949e",
58
+ "heading5": "#8b949e",
59
+ "heading6": "#8b949e",
60
+ "link": "#58a6ff",
61
+ "linkText": "#58a6ff",
62
+ "code": "#ffa657",
63
+ "blockQuote": "#8b949e",
64
+ "emphasis": "#e6edf3",
65
+ "strong": "#e6edf3",
66
+ "horizontalRule": "#30363d",
67
+ "listItem": "#e6edf3",
68
+ "listEnumeration": "#e6edf3",
69
+ "image": "#58a6ff",
70
+ "imageText": "#58a6ff",
71
+ "codeBlock": "#e6edf3"
72
+ },
73
+
74
+ "syntax": {
75
+ "comment": "#8b949e",
76
+ "keyword": "#ff7b72",
77
+ "function": "#d2a8ff",
78
+ "variable": "#ffa657",
79
+ "string": "#a5d6ff",
80
+ "number": "#79c0ff",
81
+ "type": "#ffa657",
82
+ "operator": "#ff7b72",
83
+ "punctuation": "#c9d1d9"
84
+ },
85
+
86
+ "diff": {
87
+ "text": {
88
+ "added": "#3fb950",
89
+ "removed": "#f85149",
90
+ "context": "#8b949e"
91
+ },
92
+ "background": {
93
+ "added": "#12261e",
94
+ "removed": "#25171c",
95
+ "context": "#161b22"
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "mode": "light",
3
+ "accent": "#0969da",
4
+ "categorical": ["#0969da", "#8250df", "#1a7f37", "#9a6700", "#cf222e", "#bc4c00"],
5
+ "text": {
6
+ "base": "#1f2328",
7
+ "muted": "#59636e",
8
+ "feedback": { "error": "#cf222e", "warning": "#9a6700", "success": "#1a7f37", "info": "#0969da" },
9
+ "action": { "primary": { "focused": "#0969da" } }
10
+ },
11
+ "background": { "base": "#ffffff" },
12
+ "border": { "base": "#8c959f" },
13
+ "frame": { "border": "#8c959f", "title": "#59636e" },
14
+ "markdown": {
15
+ "text": "#1f2328", "heading": "#8250df",
16
+ "heading1": "#0969da", "heading2": "#8250df", "heading3": "#8250df",
17
+ "heading4": "#6f42c1", "heading5": "#3d444d", "heading6": "#3d444d",
18
+ "link": "#0969da", "linkText": "#0969da", "code": "#953800",
19
+ "blockQuote": "#59636e", "emphasis": "#1f2328", "strong": "#1f2328",
20
+ "horizontalRule": "#d1d9e0", "listItem": "#1f2328", "listEnumeration": "#1f2328",
21
+ "image": "#0969da", "imageText": "#0969da", "codeBlock": "#1f2328"
22
+ },
23
+ "syntax": {
24
+ "comment": "#59636e", "keyword": "#cf222e", "function": "#8250df",
25
+ "variable": "#1f2328", "string": "#0a3069", "number": "#0550ae",
26
+ "type": "#0550ae", "operator": "#0550ae", "punctuation": "#1f2328"
27
+ },
28
+ "diff": {
29
+ "text": { "added": "#1a7f37", "removed": "#cf222e", "context": "#59636e" },
30
+ "background": { "added": "#dafbe1", "removed": "#ffebe9", "context": "#f6f8fa" }
31
+ }
32
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "mode": "dark",
3
+ "palette": ["#002b36", "#073642", "#586e75", "#657b83", "#839496", "#93a1a1", "#eee8d5", "#fdf6e3", "#b58900", "#cb4b16", "#dc322f", "#d33682", "#6c71c4", "#268bd2", "#2aa198", "#859900"],
4
+ "accent": "#268bd2",
5
+ "categorical": ["#268bd2", "#6c71c4", "#859900", "#b58900", "#dc322f", "#cb4b16"],
6
+ "text": {
7
+ "base": "#93a1a1", "muted": "#839496",
8
+ "feedback": { "error": "#dc322f", "warning": "#b58900", "success": "#859900", "info": "#268bd2" },
9
+ "action": { "primary": { "focused": "#268bd2" } }
10
+ },
11
+ "background": { "base": "#002b36" },
12
+ "border": { "base": "#586e75" },
13
+ "frame": { "border": "#586e75", "title": "#93a1a1" },
14
+ "markdown": {
15
+ "text": "#93a1a1", "heading": "#268bd2",
16
+ "heading1": "#268bd2", "heading2": "#268bd2", "heading3": "#268bd2",
17
+ "heading4": "#268bd2", "heading5": "#268bd2", "heading6": "#268bd2",
18
+ "link": "#268bd2", "linkText": "#268bd2", "code": "#cb4b16",
19
+ "blockQuote": "#839496", "emphasis": "#93a1a1", "strong": "#93a1a1",
20
+ "horizontalRule": "#586e75", "listItem": "#93a1a1", "listEnumeration": "#93a1a1",
21
+ "image": "#268bd2", "imageText": "#268bd2", "codeBlock": "#93a1a1"
22
+ },
23
+ "syntax": {
24
+ "comment": "#839496", "keyword": "#dc322f", "function": "#6c71c4",
25
+ "variable": "#93a1a1", "string": "#2aa198", "number": "#d33682",
26
+ "type": "#b58900", "operator": "#268bd2", "punctuation": "#93a1a1"
27
+ },
28
+ "diff": {
29
+ "text": { "added": "#859900", "removed": "#dc322f", "context": "#839496" },
30
+ "background": { "added": "#073642", "removed": "#073642", "context": "#073642" }
31
+ }
32
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "mode": "light",
3
+ "palette": ["#002b36", "#073642", "#586e75", "#657b83", "#839496", "#93a1a1", "#eee8d5", "#fdf6e3", "#b58900", "#cb4b16", "#dc322f", "#d33682", "#6c71c4", "#268bd2", "#2aa198", "#859900"],
4
+ "accent": "#268bd2",
5
+ "categorical": ["#268bd2", "#6c71c4", "#859900", "#b58900", "#dc322f", "#cb4b16"],
6
+ "text": {
7
+ "base": "#586e75", "muted": "#657b83",
8
+ "feedback": { "error": "#dc322f", "warning": "#b58900", "success": "#859900", "info": "#268bd2" },
9
+ "action": { "primary": { "focused": "#268bd2" } }
10
+ },
11
+ "background": { "base": "#fdf6e3" },
12
+ "border": { "base": "#657b83" },
13
+ "frame": { "border": "#657b83", "title": "#586e75" },
14
+ "markdown": {
15
+ "text": "#586e75", "heading": "#268bd2",
16
+ "heading1": "#268bd2", "heading2": "#268bd2", "heading3": "#268bd2",
17
+ "heading4": "#268bd2", "heading5": "#268bd2", "heading6": "#268bd2",
18
+ "link": "#268bd2", "linkText": "#268bd2", "code": "#cb4b16",
19
+ "blockQuote": "#657b83", "emphasis": "#586e75", "strong": "#586e75",
20
+ "horizontalRule": "#657b83", "listItem": "#586e75", "listEnumeration": "#586e75",
21
+ "image": "#268bd2", "imageText": "#268bd2", "codeBlock": "#586e75"
22
+ },
23
+ "syntax": {
24
+ "comment": "#657b83", "keyword": "#dc322f", "function": "#6c71c4",
25
+ "variable": "#586e75", "string": "#2aa198", "number": "#d33682",
26
+ "type": "#b58900", "operator": "#268bd2", "punctuation": "#586e75"
27
+ },
28
+ "diff": {
29
+ "text": { "added": "#859900", "removed": "#dc322f", "context": "#657b83" },
30
+ "background": { "added": "#eee8d5", "removed": "#eee8d5", "context": "#eee8d5" }
31
+ }
32
+ }