Refactor utilities to utils for consistency

This commit is contained in:
Saoud Rizwan
2024-08-03 15:47:41 -04:00
parent b32f91b0ee
commit fa1068d92d
19 changed files with 15 additions and 15 deletions

View File

@@ -0,0 +1,62 @@
import { ClaudeMessage } from "@shared/ExtensionMessage"
/**
* Combines API request start and finish messages in an array of ClaudeMessages.
*
* This function looks for pairs of 'api_req_started' and 'api_req_finished' messages.
* When it finds a pair, it combines them into a single 'api_req_combined' message.
* The JSON data in the text fields of both messages are merged.
*
* @param messages - An array of ClaudeMessage objects to process.
* @returns A new array of ClaudeMessage objects with API requests combined.
*
* @example
* const messages = [
* { type: "say", say: "api_req_started", text: '{"request":"GET /api/data"}', ts: 1000 },
* { type: "say", say: "api_req_finished", text: '{"cost":0.005}', ts: 1001 }
* ];
* const result = combineApiRequests(messages);
* // Result: [{ type: "say", say: "api_req_started", text: '{"request":"GET /api/data","cost":0.005}', ts: 1000 }]
*/
export function combineApiRequests(messages: ClaudeMessage[]): ClaudeMessage[] {
const combinedApiRequests: ClaudeMessage[] = []
for (let i = 0; i < messages.length; i++) {
if (messages[i].type === "say" && messages[i].say === "api_req_started") {
let startedRequest = JSON.parse(messages[i].text || "{}")
let j = i + 1
while (j < messages.length) {
if (messages[j].type === "say" && messages[j].say === "api_req_finished") {
let finishedRequest = JSON.parse(messages[j].text || "{}")
let combinedRequest = { ...startedRequest, ...finishedRequest }
combinedApiRequests.push({
...messages[i],
text: JSON.stringify(combinedRequest),
})
i = j // Skip to the api_req_finished message
break
}
j++
}
if (j === messages.length) {
// If no matching api_req_finished found, keep the original api_req_started
combinedApiRequests.push(messages[i])
}
}
}
// Replace original api_req_started and remove api_req_finished
return messages
.filter((msg) => !(msg.type === "say" && msg.say === "api_req_finished"))
.map((msg) => {
if (msg.type === "say" && msg.say === "api_req_started") {
const combinedRequest = combinedApiRequests.find((req) => req.ts === msg.ts)
return combinedRequest || msg
}
return msg
})
}

View File

@@ -0,0 +1,69 @@
import { ClaudeMessage } from "@shared/ExtensionMessage"
/**
* Combines sequences of command and command_output messages in an array of ClaudeMessages.
*
* This function processes an array of ClaudeMessage objects, looking for sequences
* where a 'command' message is followed by one or more 'command_output' messages.
* When such a sequence is found, it combines them into a single message, merging
* their text contents.
*
* @param messages - An array of ClaudeMessage objects to process.
* @returns A new array of ClaudeMessage objects with command sequences combined.
*
* @example
* const messages: ClaudeMessage[] = [
* { type: 'ask', ask: 'command', text: 'ls', ts: 1625097600000 },
* { type: 'ask', ask: 'command_output', text: 'file1.txt', ts: 1625097601000 },
* { type: 'ask', ask: 'command_output', text: 'file2.txt', ts: 1625097602000 }
* ];
* const result = simpleCombineCommandSequences(messages);
* // Result: [{ type: 'ask', ask: 'command', text: 'ls\nfile1.txt\nfile2.txt', ts: 1625097600000 }]
*/
export function combineCommandSequences(messages: ClaudeMessage[]): ClaudeMessage[] {
const combinedCommands: ClaudeMessage[] = []
// First pass: combine commands with their outputs
for (let i = 0; i < messages.length; i++) {
if (messages[i].type === "ask" && messages[i].ask === "command") {
let combinedText = messages[i].text || ""
let didAddOutput = false
let j = i + 1
while (j < messages.length) {
if (messages[j].type === "ask" && messages[j].ask === "command") {
// Stop if we encounter the next command
break
}
if (messages[j].ask === "command_output" || messages[j].say === "command_output") {
if (!didAddOutput) {
// Add a newline before the first output
combinedText += `\n${COMMAND_OUTPUT_STRING}`
didAddOutput = true
}
combinedText += "\n" + (messages[j].text || "")
}
j++
}
combinedCommands.push({
...messages[i],
text: combinedText,
})
i = j - 1 // Move to the index just before the next command or end of array
}
}
// Second pass: remove command_outputs and replace original commands with combined ones
return messages
.filter((msg) => !(msg.ask === "command_output" || msg.say === "command_output"))
.map((msg) => {
if (msg.type === "ask" && msg.ask === "command") {
const combinedCommand = combinedCommands.find((cmd) => cmd.ts === msg.ts)
return combinedCommand || msg
}
return msg
})
}
export const COMMAND_OUTPUT_STRING = "Output:"

View File

@@ -0,0 +1,55 @@
import { ClaudeMessage } from "@shared/ExtensionMessage"
interface ApiMetrics {
totalTokensIn: number
totalTokensOut: number
totalCost: number
}
/**
* Calculates API metrics from an array of ClaudeMessages.
*
* This function processes 'api_req_started' messages that have been combined with their
* corresponding 'api_req_finished' messages by the combineApiRequests function.
* It extracts and sums up the tokensIn, tokensOut, and cost from these messages.
*
* @param messages - An array of ClaudeMessage objects to process.
* @returns An ApiMetrics object containing totalTokensIn, totalTokensOut, and totalCost.
*
* @example
* const messages = [
* { type: "say", say: "api_req_started", text: '{"request":"GET /api/data","tokensIn":10,"tokensOut":20,"cost":0.005}', ts: 1000 }
* ];
* const { totalTokensIn, totalTokensOut, totalCost } = getApiMetrics(messages);
* // Result: { totalTokensIn: 10, totalTokensOut: 20, totalCost: 0.005 }
*/
export function getApiMetrics(messages: ClaudeMessage[]): ApiMetrics {
const result: ApiMetrics = {
totalTokensIn: 0,
totalTokensOut: 0,
totalCost: 0,
}
messages.forEach((message) => {
if (message.type === "say" && message.say === "api_req_started" && message.text) {
try {
const parsedData = JSON.parse(message.text)
const { tokensIn, tokensOut, cost } = parsedData
if (typeof tokensIn === "number") {
result.totalTokensIn += tokensIn
}
if (typeof tokensOut === "number") {
result.totalTokensOut += tokensOut
}
if (typeof cost === "number") {
result.totalCost += cost
}
} catch (error) {
console.error("Error parsing JSON:", error)
}
}
})
return result
}

View File

@@ -0,0 +1,89 @@
const extensionToLanguage: { [key: string]: string } = {
// Web technologies
html: "html",
htm: "html",
css: "css",
js: "javascript",
jsx: "jsx",
ts: "typescript",
tsx: "tsx",
// Backend languages
py: "python",
rb: "ruby",
php: "php",
java: "java",
cs: "csharp",
go: "go",
rs: "rust",
scala: "scala",
kt: "kotlin",
swift: "swift",
// Markup and data
json: "json",
xml: "xml",
yaml: "yaml",
yml: "yaml",
md: "markdown",
csv: "csv",
// Shell and scripting
sh: "bash",
bash: "bash",
zsh: "bash",
ps1: "powershell",
// Configuration
toml: "toml",
ini: "ini",
cfg: "ini",
conf: "ini",
// Other
sql: "sql",
graphql: "graphql",
gql: "graphql",
tex: "latex",
svg: "svg",
txt: "text",
// C-family languages
c: "c",
cpp: "cpp",
h: "c",
hpp: "cpp",
// Functional languages
hs: "haskell",
lhs: "haskell",
elm: "elm",
clj: "clojure",
cljs: "clojure",
erl: "erlang",
ex: "elixir",
exs: "elixir",
// Mobile development
dart: "dart",
m: "objectivec",
mm: "objectivec",
// Game development
lua: "lua",
gd: "gdscript", // Godot
unity: "csharp", // Unity (using C#)
// Data science and ML
r: "r",
jl: "julia",
ipynb: "jupyter", // Jupyter notebooks
}
// Example usage:
// console.log(getLanguageFromPath('/path/to/file.js')); // Output: javascript
export function getLanguageFromPath(path: string): string | undefined {
const extension = path.split(".").pop()?.toLowerCase() || ""
return extensionToLanguage[extension]
}

View File

@@ -0,0 +1,89 @@
import * as defaultThemes from "react-syntax-highlighter/dist/esm/styles/prism"
import * as generatedThemes from "./vscode-themes"
/*
VSCode extension webviews have a notoriously difficult time syntax highlighting with styles from the user's theme. We dont have access to css variables like --vscode-function-color that map to all the token styles react-syntax-highlighter expects. Fortunately, react-syntax-highlighter comes with many built-in themes that we can map to popular VSCode themes. We can also use the few editor css variables exposed to use like --vscode-editor-background (see CodeBlock.tsx), which 99% of the time results in syntax highlighting identical to how the user's editor looks. This approach avoids the overhead of using VSCode's Monaco editor and the monaco-vscode-textmate-theme-converter as some other extensions do, and allows us to take advantage of all the benefits of react-syntax-highlighter.
For themes that don't have a 1:1 match with react-syntax-highlighter built-in themes, we can use Claude to generate style objects based on the results from the "Developer: Generate Color Theme From Current Settings" command.
https://github.com/microsoft/vscode/issues/56356
*/
// See https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_STYLES_PRISM.MD for available styles react-syntax-highlighter provides
const defaultSyntaxHighlighterThemes: { [key: string]: string } = {
// Vscode built-in
"Default Dark Modern": "vscDarkPlus",
"Dark+": "vscDarkPlus",
"Default Dark+": "vscDarkPlus",
"Dark (Visual Studio)": "vscDarkPlus",
"Visual Studio Dark": "vscDarkPlus",
"Dark High Contrast": "vscDarkPlus",
"Default High Contrast": "vscDarkPlus",
"Light High Contrast": "vs",
"Default High Contrast Light": "vs", // FIXME: some text renders white
"Default Light Modern": "vs",
"Light+": "vs",
"Default Light+": "vs",
"Light (Visual Studio)": "vs",
"Visual Studio Light": "vs",
// Third party
Anysphere: "nightOwl",
Abyss: "materialOceanic",
"Kimbie Dark": "cb",
Monokai: "darcula",
"Monokai Dimmed": "darcula",
"Solarized Dark": "solarizedDarkAtom",
"Solarized Light": "solarizedlight",
"Quiet Light": "solarizedlight",
"Tomorrow Night Blue": "lucario",
Dracula: "dracula",
"Dracula Theme": "dracula",
"Dracula Theme Soft": "dracula",
"Night Owl": "nightOwl",
"Material Theme": "materialDark",
"Material Theme Lighter": "materialLight",
"Material Theme Lighter High Contrast": "materialLight",
"One Dark Pro": "oneDark",
"One Dark Pro Darker": "oneDark",
"One Dark Pro Flat": "oneDark",
"One Dark Pro Mix": "oneDark",
"One Light": "oneLight",
"Winter is Coming": "nord",
"Atom One Dark": "oneDark",
"SynthWave '84": "synthwave84",
}
// Themes that don't have an already provided 1:1 syntax highlighter style
// These style objects are built with Claude using the results from "Developer: Generate Color Theme From Current Settings" command
const generatedSyntaxHighlighterThemes: { [key: string]: string } = {
"Github Dark": "githubDark",
"GitHub Dark Colorblind (Beta)": "githubDark",
"GitHub Dark Colorblind": "githubDark",
"GitHub Dark Default": "githubDark",
"GitHub Dark Dimmed": "githubDark",
"GitHub Dark High Contrast": "githubDark",
"Github Light": "githubLight",
"GitHub Light Colorblind (Beta)": "githubLight",
"GitHub Light Colorblind": "githubLight",
"GitHub Light Default": "githubLight",
"GitHub Light High Contrast": "githubLight",
}
export type SyntaxHighlighterStyle = { [key: string]: React.CSSProperties }
export function getSyntaxHighlighterStyleFromTheme(themeName: string): SyntaxHighlighterStyle | undefined {
const defaultSyntaxHighlighterTheme = Object.entries(defaultSyntaxHighlighterThemes).find(([key]) =>
key.toLowerCase().startsWith(themeName.toLowerCase())
)?.[1]
if (defaultSyntaxHighlighterTheme && defaultSyntaxHighlighterTheme in defaultThemes) {
return defaultThemes[defaultSyntaxHighlighterTheme as keyof typeof defaultThemes]
} else {
const generatedSyntaxHighlighterTheme = Object.entries(generatedSyntaxHighlighterThemes).find(([key]) =>
key.toLowerCase().startsWith(themeName.toLowerCase())
)?.[1]
if (generatedSyntaxHighlighterTheme && generatedSyntaxHighlighterTheme in generatedThemes) {
return generatedThemes[generatedSyntaxHighlighterTheme as keyof typeof generatedThemes]
}
}
}

View File

@@ -0,0 +1,355 @@
import { ClaudeMessage } from "@shared/ExtensionMessage";
export const mockMessages: ClaudeMessage[] = [
{
ts: Date.now() - 3600000,
type: "say",
say: "task",
text: "Create a React component for a todo list application",
},
{
ts: Date.now() - 3500000,
type: "say",
say: "api_req_started",
text: JSON.stringify({
request: {
text: "Create a React component for a todo list application",
type: "text",
},
tokensIn: 10,
tokensOut: 250,
cost: 0.0002,
}),
},
{
ts: Date.now() - 3300000,
type: "say",
say: "text",
text: "Here's a basic React component for a todo list application:",
},
{
ts: Date.now() - 3200000,
type: "ask",
ask: "tool",
text: JSON.stringify({
tool: "newFileCreated",
path: "/src/components/TodoList.tsx",
content: `import React, { useState } from 'react';
interface Todo {
id: number;
text: string;
completed: boolean;
}
const TodoList: React.FC = () => {
const [todos, setTodos] = useState<Todo[]>([]);
const [inputValue, setInputValue] = useState('');
const addTodo = () => {
if (inputValue.trim() !== '') {
setTodos([...todos, { id: Date.now(), text: inputValue, completed: false }]);
setInputValue('');
}
};
const toggleTodo = (id: number) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
return (
<div>
<h1>Todo List</h1>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Add a new todo"
/>
<button onClick={addTodo}>Add</button>
<ul>
{todos.map(todo => (
<li
key={todo.id}
onClick={() => toggleTodo(todo.id)}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
</div>
);
};
export default TodoList;`,
}),
},
{
ts: Date.now() - 3100000,
type: "say",
say: "text",
text: "I've created a new file 'TodoList.tsx' in the '/src/components/' directory. This component includes basic functionality for adding and toggling todos. You can further customize and style it as needed.",
},
{
ts: Date.now() - 3000000,
type: "ask",
ask: "followup",
text: "Do you want me to explain the code or add any additional features to the todo list?",
},
{
ts: Date.now() - 2900000,
type: "say",
say: "text",
text: "Let's add a feature to delete todos from the list.",
},
{
ts: Date.now() - 2800000,
type: "say",
say: "api_req_started",
text: JSON.stringify({
request: {
text: "Add a feature to delete todos from the list",
type: "text",
},
tokensIn: 8,
tokensOut: 180,
cost: 0.0003,
}),
},
{
ts: Date.now() - 2600000,
type: "ask",
ask: "tool",
text: JSON.stringify({
tool: "editedExistingFile",
path: "/src/components/TodoList.tsx",
diff: `+
+
import React, { useState } from "react"
interface Todo {
id: number
text: string
completed: boolean
}
const TodoList: React.FC = () => {
const [todos, setTodos] = useState<Todo[]>([])
const [inputValue, setInputValue] = useState("")
const addTodo = () => {
if (inputValue.trim() !== "") {
setTodos([...todos, { id: Date.now(), text: inputValue, completed: false }])
setInputValue("")
}
}
const toggleTodo = (id: number) => {
setTodos(todos.map((todo) => (todo.id === id ? { ...todo, completed: !todo.completed } : todo)))
}
return (
<div>
<h1>Todo List</h1>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Add a new todo"
/>
- <button onClick={addTodo}>Add</button>
- <ul>
- {todos.map((todo) => (
- <li
- key={todo.id}
- onClick={() => toggleTodo(todo.id)}
- style={{ textDecoration: todo.completed ? "line-through" : "none" }}>
- {todo.text}
- </li>
- ))}
- </ul>
- </div>
-
+
+
)
}
export default TodoList
+
+
`,
}),
},
{
ts: Date.now() - 2500000,
type: "say",
say: "text",
text: "I've updated the TodoList component to include a delete feature. Each todo item now has a 'Delete' button that removes the todo from the list when clicked.",
},
{
ts: Date.now() - 2400000,
type: "ask",
ask: "command",
text: "npm run test\n\nOutput:\nPASS src/__tests__/TodoList.test.tsx\n TodoList Component\n ✓ renders without crashing (23 ms)\n ✓ adds a new todo when the add button is clicked (34 ms)\n ✓ toggles a todo when clicked (45 ms)\n ✓ deletes a todo when the delete button is clicked (28 ms)\n\nTest Suites: 1 passed, 1 total\nTests: 4 passed, 4 total\nSnapshots: 0 total\nTime: 1.234 s\nRan all test suites.",
},
{
ts: Date.now() - 2300000,
type: "say",
say: "text",
text: "Great! The tests for the TodoList component have passed. All functionalities, including the new delete feature, are working as expected.",
},
{
ts: Date.now() - 2200000,
type: "ask",
ask: "request_limit_reached",
text: "You've reached the maximum number of requests for this task. Would you like to continue or start a new task?",
},
{
ts: Date.now() - 2100000,
type: "say",
say: "text",
text: "Let's start a new task. What would you like to work on next?",
},
{
ts: Date.now() - 2000000,
type: "say",
say: "task",
text: "Create a simple API using Express.js",
},
{
ts: Date.now() - 1900000,
type: "say",
say: "api_req_started",
text: JSON.stringify({
request: {
text: "Create a simple API using Express.js",
type: "text",
},
tokensIn: 7,
tokensOut: 220,
cost: 0.0002,
}),
},
{
ts: Date.now() - 1700000,
type: "ask",
ask: "tool",
text: JSON.stringify({
tool: "newFileCreated",
path: "/src/app.js",
content: `const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
let items = [];
app.get('/items', (req, res) => {
res.json(items);
});
app.post('/items', (req, res) => {
const newItem = req.body;
items.push(newItem);
res.status(201).json(newItem);
});
app.get('/items/:id', (req, res) => {
const item = items.find(i => i.id === parseInt(req.params.id));
if (item) {
res.json(item);
} else {
res.status(404).send('Item not found');
}
});
app.listen(port, () => {
console.log(\`API running on http://localhost:\${port}\`);
});`,
}),
},
{
ts: Date.now() - 1600000,
type: "say",
say: "text",
text: "I've created a simple Express.js API with endpoints for getting all items, adding a new item, and getting a specific item by ID. The API is set up to run on port 3000.",
},
{
ts: Date.now() - 1500000,
type: "ask",
ask: "command",
text: "npm install express\n\nOutput:\nadded 57 packages, and audited 58 packages in 3s\n\n7 packages are looking for funding\n run `npm fund` for details\n\nfound 0 vulnerabilities",
},
{
ts: Date.now() - 1400000,
type: "say",
say: "text",
text: "Express has been successfully installed. You can now run the API using 'node app.js' in the terminal.",
},
{
ts: Date.now() - 1300000,
type: "ask",
ask: "completion_result",
text: "The API has been successfully created and set up. Is there anything else you'd like me to do with this API?",
},
{
ts: Date.now() - 1200000,
type: "say",
say: "error",
text: "An error occurred while trying to start the server: EADDRINUSE: address already in use :::3000",
},
{
ts: Date.now() - 1100000,
type: "say",
say: "text",
text: "It seems that port 3000 is already in use. Let's modify the code to use a different port.",
},
{
ts: Date.now() - 1000000,
type: "ask",
ask: "tool",
text: JSON.stringify({
tool: "editedExistingFile",
path: "/src/app.js",
diff: `@@ -1,6 +1,6 @@
const express = require('express');
const app = express();
-const port = 3000;
+const port = process.env.PORT || 3001;
app.use(express.json());
`,
}),
},
{
ts: Date.now() - 900000,
type: "say",
say: "text",
text: "I've updated the code to use port 3001 if port 3000 is not available. You can now try running the server again.",
},
{
ts: Date.now() - 800000,
type: "ask",
ask: "command",
text: "node app.js\n\nOutput:\nAPI running on http://localhost:3001",
},
{
ts: Date.now() - 700000,
type: "say",
say: "text",
text: "Great! The API is now running successfully on port 3001.",
},
{
ts: Date.now() - 600000,
type: "ask",
ask: "completion_result",
text: "The API has been created, set up, and is now running successfully. Is there anything else you'd like me to do?",
},
]

View File

@@ -0,0 +1,34 @@
import { ApiConfiguration } from "@shared/api"
export function validateApiConfiguration(apiConfiguration?: ApiConfiguration): string | undefined {
if (apiConfiguration) {
switch (apiConfiguration.apiProvider) {
case "anthropic":
if (!apiConfiguration.apiKey) {
return "You must provide a valid API key or choose a different provider."
}
break
case "bedrock":
if (!apiConfiguration.awsAccessKey || !apiConfiguration.awsSecretKey || !apiConfiguration.awsRegion) {
return "You must provide a valid AWS access key, secret key, and region."
}
break
case "openrouter":
if (!apiConfiguration.openRouterApiKey) {
return "You must provide a valid API key or choose a different provider."
}
break
}
}
return undefined
}
export function validateMaxRequestsPerTask(maxRequestsPerTask?: string): string | undefined {
if (maxRequestsPerTask && maxRequestsPerTask.trim()) {
const num = Number(maxRequestsPerTask)
if (isNaN(num) || num < 3 || num > 100) {
return "Maximum requests must be between 3 and 100"
}
}
return undefined
}

View File

@@ -0,0 +1,503 @@
const theme: { [key: string]: React.CSSProperties } = {
'code[class*="language-"]': {
color: "#e1e4e8",
background: "#24292e",
textShadow: "0 1px rgba(0, 0, 0, 0.3)",
fontFamily: '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
direction: "ltr",
textAlign: "left",
whiteSpace: "pre",
wordSpacing: "normal",
wordBreak: "normal",
lineHeight: "1.5",
MozTabSize: "2",
OTabSize: "2",
tabSize: "2",
WebkitHyphens: "none",
MozHyphens: "none",
msHyphens: "none",
hyphens: "none",
},
'pre[class*="language-"]': {
color: "#e1e4e8",
background: "#24292e",
textShadow: "0 1px rgba(0, 0, 0, 0.3)",
fontFamily: '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
direction: "ltr",
textAlign: "left",
whiteSpace: "pre",
wordSpacing: "normal",
wordBreak: "normal",
lineHeight: "1.5",
MozTabSize: "2",
OTabSize: "2",
tabSize: "2",
WebkitHyphens: "none",
MozHyphens: "none",
msHyphens: "none",
hyphens: "none",
padding: "1em",
margin: "0.5em 0",
overflow: "auto",
borderRadius: "0.3em",
},
'code[class*="language-"]::-moz-selection': {
background: "#3392ff44",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"] *::-moz-selection': {
background: "#3392ff44",
color: "inherit",
textShadow: "none",
},
'pre[class*="language-"] *::-moz-selection': {
background: "#3392ff44",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"]::selection': {
background: "#3392ff44",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"] *::selection': {
background: "#3392ff44",
color: "inherit",
textShadow: "none",
},
'pre[class*="language-"] *::selection': {
background: "#3392ff44",
color: "inherit",
textShadow: "none",
},
':not(pre) > code[class*="language-"]': {
background: "#24292e",
padding: "0.1em",
borderRadius: "0.3em",
whiteSpace: "normal",
},
comment: {
color: "#6A737D",
fontStyle: "italic",
},
prolog: {
color: "#6A737D",
},
cdata: {
color: "#6A737D",
},
doctype: {
color: "#e1e4e8",
},
punctuation: {
color: "#e1e4e8",
},
entity: {
color: "#e1e4e8",
cursor: "help",
},
"attr-name": {
color: "#79B8FF",
},
"class-name": {
color: "#B392F0",
},
boolean: {
color: "#79B8FF",
},
constant: {
color: "#79B8FF",
},
number: {
color: "#79B8FF",
},
atrule: {
color: "#79B8FF",
},
keyword: {
color: "#F97583",
},
property: {
color: "#79B8FF",
},
tag: {
color: "#85E89D",
},
symbol: {
color: "#79B8FF",
},
deleted: {
color: "#FDAEB7",
background: "#86181D",
},
important: {
color: "#F97583",
},
selector: {
color: "#85E89D",
},
string: {
color: "#9ECBFF",
},
char: {
color: "#9ECBFF",
},
builtin: {
color: "#79B8FF",
},
inserted: {
color: "#85E89D",
background: "#144620",
},
regex: {
color: "#DBEDFF",
},
"attr-value": {
color: "#9ECBFF",
},
"attr-value > .token.punctuation": {
color: "#9ECBFF",
},
variable: {
color: "#FFAB70",
},
operator: {
color: "#F97583",
},
function: {
color: "#B392F0",
},
url: {
color: "#79B8FF",
},
"attr-value > .token.punctuation.attr-equals": {
color: "#e1e4e8",
},
"special-attr > .token.attr-value > .token.value.css": {
color: "#e1e4e8",
},
".language-css .token.selector": {
color: "#85E89D",
},
".language-css .token.property": {
color: "#79B8FF",
},
".language-css .token.function": {
color: "#79B8FF",
},
".language-css .token.url > .token.function": {
color: "#79B8FF",
},
".language-css .token.url > .token.string.url": {
color: "#9ECBFF",
},
".language-css .token.important": {
color: "#F97583",
},
".language-css .token.atrule .token.rule": {
color: "#F97583",
},
".language-javascript .token.operator": {
color: "#F97583",
},
".language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation":
{
color: "#FDAEB7",
},
".language-json .token.operator": {
color: "#e1e4e8",
},
".language-json .token.null.keyword": {
color: "#79B8FF",
},
".language-markdown .token.url": {
color: "#e1e4e8",
},
".language-markdown .token.url > .token.operator": {
color: "#e1e4e8",
},
".language-markdown .token.url-reference.url > .token.string": {
color: "#e1e4e8",
},
".language-markdown .token.url > .token.content": {
color: "#79B8FF",
},
".language-markdown .token.url > .token.url": {
color: "#79B8FF",
},
".language-markdown .token.url-reference.url": {
color: "#79B8FF",
},
".language-markdown .token.blockquote.punctuation": {
color: "#6A737D",
fontStyle: "italic",
},
".language-markdown .token.hr.punctuation": {
color: "#6A737D",
fontStyle: "italic",
},
".language-markdown .token.code-snippet": {
color: "#9ECBFF",
},
".language-markdown .token.bold .token.content": {
color: "#79B8FF",
},
".language-markdown .token.italic .token.content": {
color: "#B392F0",
},
".language-markdown .token.strike .token.content": {
color: "#FDAEB7",
},
".language-markdown .token.strike .token.punctuation": {
color: "#FDAEB7",
},
".language-markdown .token.list.punctuation": {
color: "#FDAEB7",
},
".language-markdown .token.title.important > .token.punctuation": {
color: "#FDAEB7",
},
bold: {
fontWeight: "bold",
},
italic: {
fontStyle: "italic",
},
namespace: {
opacity: "0.8",
},
"token.tab:not(:empty):before": {
color: "#6A737D",
},
"token.cr:before": {
color: "#6A737D",
},
"token.lf:before": {
color: "#6A737D",
},
"token.space:before": {
color: "#6A737D",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item": {
marginRight: "0.4em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button": {
background: "#2f363d",
color: "#959da5",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a": {
background: "#2f363d",
color: "#959da5",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span": {
background: "#2f363d",
color: "#959da5",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover": {
background: "#444d56",
color: "#e1e4e8",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus": {
background: "#444d56",
color: "#e1e4e8",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover": {
background: "#444d56",
color: "#e1e4e8",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus": {
background: "#444d56",
color: "#e1e4e8",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover": {
background: "#444d56",
color: "#e1e4e8",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus": {
background: "#444d56",
color: "#e1e4e8",
},
".line-highlight.line-highlight": {
background: "#2b3036",
},
".line-highlight.line-highlight:before": {
background: "#2f363d",
color: "#e1e4e8",
padding: "0.1em 0.6em",
borderRadius: "0.3em",
boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
},
".line-highlight.line-highlight[data-end]:after": {
background: "#2f363d",
color: "#e1e4e8",
padding: "0.1em 0.6em",
borderRadius: "0.3em",
boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
},
"pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before": {
backgroundColor: "#2b3036",
},
".line-numbers.line-numbers .line-numbers-rows": {
borderRightColor: "#444d56",
},
".command-line .command-line-prompt": {
borderRightColor: "#444d56",
},
".line-numbers .line-numbers-rows > span:before": {
color: "#444d56",
},
".command-line .command-line-prompt > span:before": {
color: "#444d56",
},
".rainbow-braces .token.token.punctuation.brace-level-1": {
color: "#FDAEB7",
},
".rainbow-braces .token.token.punctuation.brace-level-5": {
color: "#FDAEB7",
},
".rainbow-braces .token.token.punctuation.brace-level-9": {
color: "#FDAEB7",
},
".rainbow-braces .token.token.punctuation.brace-level-2": {
color: "#9ECBFF",
},
".rainbow-braces .token.token.punctuation.brace-level-6": {
color: "#9ECBFF",
},
".rainbow-braces .token.token.punctuation.brace-level-10": {
color: "#9ECBFF",
},
".rainbow-braces .token.token.punctuation.brace-level-3": {
color: "#79B8FF",
},
".rainbow-braces .token.token.punctuation.brace-level-7": {
color: "#79B8FF",
},
".rainbow-braces .token.token.punctuation.brace-level-11": {
color: "#79B8FF",
},
".rainbow-braces .token.token.punctuation.brace-level-4": {
color: "#B392F0",
},
".rainbow-braces .token.token.punctuation.brace-level-8": {
color: "#B392F0",
},
".rainbow-braces .token.token.punctuation.brace-level-12": {
color: "#B392F0",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)": {
backgroundColor: "#86181D",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)": {
backgroundColor: "#86181D",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection": {
backgroundColor: "#86181D",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection": {
backgroundColor: "#86181D",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection": {
backgroundColor: "#86181D",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection": {
backgroundColor: "#86181D",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection": {
backgroundColor: "#86181D",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection": {
backgroundColor: "#86181D",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection": {
backgroundColor: "#86181D",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection": {
backgroundColor: "#86181D",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)": {
backgroundColor: "#144620",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)": {
backgroundColor: "#144620",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection": {
backgroundColor: "#144620",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection": {
backgroundColor: "#144620",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection": {
backgroundColor: "#144620",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection": {
backgroundColor: "#144620",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection": {
backgroundColor: "#144620",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection": {
backgroundColor: "#144620",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection": {
backgroundColor: "#144620",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection": {
backgroundColor: "#144620",
},
".prism-previewer.prism-previewer:before": {
borderColor: "#1b1f23",
},
".prism-previewer-gradient.prism-previewer-gradient div": {
borderColor: "#1b1f23",
borderRadius: "0.3em",
},
".prism-previewer-color.prism-previewer-color:before": {
borderRadius: "0.3em",
},
".prism-previewer-easing.prism-previewer-easing:before": {
borderRadius: "0.3em",
},
".prism-previewer.prism-previewer:after": {
borderTopColor: "#1b1f23",
},
".prism-previewer-flipped.prism-previewer-flipped.after": {
borderBottomColor: "#1b1f23",
},
".prism-previewer-angle.prism-previewer-angle:before": {
background: "#1f2428",
},
".prism-previewer-time.prism-previewer-time:before": {
background: "#1f2428",
},
".prism-previewer-easing.prism-previewer-easing": {
background: "#1f2428",
},
".prism-previewer-angle.prism-previewer-angle circle": {
stroke: "#e1e4e8",
strokeOpacity: "1",
},
".prism-previewer-time.prism-previewer-time circle": {
stroke: "#e1e4e8",
strokeOpacity: "1",
},
".prism-previewer-easing.prism-previewer-easing circle": {
stroke: "#e1e4e8",
fill: "transparent",
},
".prism-previewer-easing.prism-previewer-easing path": {
stroke: "#e1e4e8",
},
".prism-previewer-easing.prism-previewer-easing line": {
stroke: "#e1e4e8",
},
}
export default theme

View File

@@ -0,0 +1,506 @@
const theme: { [key: string]: React.CSSProperties } = {
'code[class*="language-"]': {
background: "#ffffff",
color: "#24292e",
textShadow: "0 1px rgba(0, 0, 0, 0.3)",
fontFamily: '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
direction: "ltr",
textAlign: "left",
whiteSpace: "pre",
wordSpacing: "normal",
wordBreak: "normal",
lineHeight: "1.5",
MozTabSize: "2",
OTabSize: "2",
tabSize: "2",
WebkitHyphens: "none",
MozHyphens: "none",
msHyphens: "none",
hyphens: "none",
},
'pre[class*="language-"]': {
background: "#ffffff",
color: "#24292e",
textShadow: "0 1px rgba(0, 0, 0, 0.3)",
fontFamily: '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
direction: "ltr",
textAlign: "left",
whiteSpace: "pre",
wordSpacing: "normal",
wordBreak: "normal",
lineHeight: "1.5",
MozTabSize: "2",
OTabSize: "2",
tabSize: "2",
WebkitHyphens: "none",
MozHyphens: "none",
msHyphens: "none",
hyphens: "none",
padding: "1em",
margin: "0.5em 0",
overflow: "auto",
borderRadius: "0.3em",
},
'code[class*="language-"]::-moz-selection': {
background: "#0366d625",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"] *::-moz-selection': {
background: "#0366d625",
color: "inherit",
textShadow: "none",
},
'pre[class*="language-"] *::-moz-selection': {
background: "#0366d625",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"]::selection': {
background: "#0366d625",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"] *::selection': {
background: "#0366d625",
color: "inherit",
textShadow: "none",
},
'pre[class*="language-"] *::selection': {
background: "#0366d625",
color: "inherit",
textShadow: "none",
},
':not(pre) > code[class*="language-"]': {
padding: "0.2em 0.3em",
borderRadius: "0.3em",
whiteSpace: "normal",
},
comment: {
color: "#6A737D",
fontStyle: "italic",
},
prolog: {
color: "#6A737D",
},
cdata: {
color: "#6A737D",
},
doctype: {
color: "#24292e",
},
punctuation: {
color: "#24292e",
},
entity: {
color: "#24292e",
cursor: "help",
},
"attr-name": {
color: "#6F42C1",
},
"class-name": {
color: "#6F42C1",
},
boolean: {
color: "#005CC5",
},
constant: {
color: "#005CC5",
},
number: {
color: "#005CC5",
},
atrule: {
color: "#005CC5",
},
keyword: {
color: "#D73A49",
},
property: {
color: "#005CC5",
},
tag: {
color: "#22863A",
},
symbol: {
color: "#005CC5",
},
deleted: {
color: "#B31D28",
background: "#FFEEF0",
},
important: {
color: "#D73A49",
},
selector: {
color: "#22863A",
},
string: {
color: "#032F62",
},
char: {
color: "#032F62",
},
builtin: {
color: "#005CC5",
},
inserted: {
color: "#22863A",
background: "#F0FFF4",
},
regex: {
color: "#032F62",
},
"attr-value": {
color: "#032F62",
},
"attr-value > .token.punctuation": {
color: "#032F62",
},
variable: {
color: "#E36209",
},
operator: {
color: "#D73A49",
},
function: {
color: "#6F42C1",
},
url: {
color: "#005CC5",
},
"attr-value > .token.punctuation.attr-equals": {
color: "#24292e",
},
"special-attr > .token.attr-value > .token.value.css": {
color: "#24292e",
},
".language-css .token.selector": {
color: "#22863A",
},
".language-css .token.property": {
color: "#005CC5",
},
".language-css .token.function": {
color: "#005CC5",
},
".language-css .token.url > .token.function": {
color: "#005CC5",
},
".language-css .token.url > .token.string.url": {
color: "#032F62",
},
".language-css .token.important": {
color: "#D73A49",
},
".language-css .token.atrule .token.rule": {
color: "#D73A49",
},
".language-javascript .token.operator": {
color: "#D73A49",
},
".language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation":
{
color: "#B31D28",
},
".language-json .token.operator": {
color: "#24292e",
},
".language-json .token.null.keyword": {
color: "#005CC5",
},
".language-markdown .token.url": {
color: "#24292e",
},
".language-markdown .token.url > .token.operator": {
color: "#24292e",
},
".language-markdown .token.url-reference.url > .token.string": {
color: "#24292e",
},
".language-markdown .token.url > .token.content": {
color: "#005CC5",
},
".language-markdown .token.url > .token.url": {
color: "#005CC5",
},
".language-markdown .token.url-reference.url": {
color: "#005CC5",
},
".language-markdown .token.blockquote.punctuation": {
color: "#6A737D",
fontStyle: "italic",
},
".language-markdown .token.hr.punctuation": {
color: "#6A737D",
fontStyle: "italic",
},
".language-markdown .token.code-snippet": {
color: "#032F62",
},
".language-markdown .token.bold .token.content": {
color: "#005CC5",
},
".language-markdown .token.italic .token.content": {
color: "#6F42C1",
},
".language-markdown .token.strike .token.content": {
color: "#B31D28",
},
".language-markdown .token.strike .token.punctuation": {
color: "#B31D28",
},
".language-markdown .token.list.punctuation": {
color: "#B31D28",
},
".language-markdown .token.title.important > .token.punctuation": {
color: "#B31D28",
},
bold: {
fontWeight: "bold",
},
italic: {
fontStyle: "italic",
},
namespace: {
opacity: "0.8",
},
"token.tab:not(:empty):before": {
color: "#24292e33",
textShadow: "none",
},
"token.cr:before": {
color: "#24292e33",
textShadow: "none",
},
"token.lf:before": {
color: "#24292e33",
textShadow: "none",
},
"token.space:before": {
color: "#24292e33",
textShadow: "none",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item": {
marginRight: "0.4em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button": {
background: "#f6f8fa",
color: "#24292e",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a": {
background: "#f6f8fa",
color: "#24292e",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span": {
background: "#f6f8fa",
color: "#24292e",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover": {
background: "#e1e4e8",
color: "#2f363d",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus": {
background: "#e1e4e8",
color: "#2f363d",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover": {
background: "#e1e4e8",
color: "#2f363d",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus": {
background: "#e1e4e8",
color: "#2f363d",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover": {
background: "#e1e4e8",
color: "#2f363d",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus": {
background: "#e1e4e8",
color: "#2f363d",
},
".line-highlight.line-highlight": {
background: "#f6f8fa",
},
".line-highlight.line-highlight:before": {
background: "#f6f8fa",
color: "#24292e",
padding: "0.1em 0.6em",
borderRadius: "0.3em",
boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
},
".line-highlight.line-highlight[data-end]:after": {
background: "#f6f8fa",
color: "#24292e",
padding: "0.1em 0.6em",
borderRadius: "0.3em",
boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
},
"pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before": {
backgroundColor: "#f6f8fa",
},
".line-numbers.line-numbers .line-numbers-rows": {
borderRightColor: "#e1e4e8",
},
".command-line .command-line-prompt": {
borderRightColor: "#e1e4e8",
},
".line-numbers .line-numbers-rows > span:before": {
color: "#1b1f234d",
},
".command-line .command-line-prompt > span:before": {
color: "#1b1f234d",
},
".rainbow-braces .token.token.punctuation.brace-level-1": {
color: "#B31D28",
},
".rainbow-braces .token.token.punctuation.brace-level-5": {
color: "#B31D28",
},
".rainbow-braces .token.token.punctuation.brace-level-9": {
color: "#B31D28",
},
".rainbow-braces .token.token.punctuation.brace-level-2": {
color: "#22863A",
},
".rainbow-braces .token.token.punctuation.brace-level-6": {
color: "#22863A",
},
".rainbow-braces .token.token.punctuation.brace-level-10": {
color: "#22863A",
},
".rainbow-braces .token.token.punctuation.brace-level-3": {
color: "#005CC5",
},
".rainbow-braces .token.token.punctuation.brace-level-7": {
color: "#005CC5",
},
".rainbow-braces .token.token.punctuation.brace-level-11": {
color: "#005CC5",
},
".rainbow-braces .token.token.punctuation.brace-level-4": {
color: "#6F42C1",
},
".rainbow-braces .token.token.punctuation.brace-level-8": {
color: "#6F42C1",
},
".rainbow-braces .token.token.punctuation.brace-level-12": {
color: "#6F42C1",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)": {
backgroundColor: "#FFEEF0",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)": {
backgroundColor: "#FFEEF0",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection": {
backgroundColor: "#FFEEF0",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection": {
backgroundColor: "#FFEEF0",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection": {
backgroundColor: "#FFEEF0",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection": {
backgroundColor: "#FFEEF0",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection": {
backgroundColor: "#FFEEF0",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection": {
backgroundColor: "#FFEEF0",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection": {
backgroundColor: "#FFEEF0",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection": {
backgroundColor: "#FFEEF0",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)": {
backgroundColor: "#F0FFF4",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)": {
backgroundColor: "#F0FFF4",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection": {
backgroundColor: "#F0FFF4",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection": {
backgroundColor: "#F0FFF4",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection": {
backgroundColor: "#F0FFF4",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection": {
backgroundColor: "#F0FFF4",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection": {
backgroundColor: "#F0FFF4",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection": {
backgroundColor: "#F0FFF4",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection": {
backgroundColor: "#F0FFF4",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection": {
backgroundColor: "#F0FFF4",
},
".prism-previewer.prism-previewer:before": {
borderColor: "#ffffff",
},
".prism-previewer-gradient.prism-previewer-gradient div": {
borderColor: "#ffffff",
borderRadius: "0.3em",
},
".prism-previewer-color.prism-previewer-color:before": {
borderRadius: "0.3em",
},
".prism-previewer-easing.prism-previewer-easing:before": {
borderRadius: "0.3em",
},
".prism-previewer.prism-previewer:after": {
borderTopColor: "#ffffff",
},
".prism-previewer-flipped.prism-previewer-flipped.after": {
borderBottomColor: "#ffffff",
},
".prism-previewer-angle.prism-previewer-angle:before": {
background: "#f6f8fa",
},
".prism-previewer-time.prism-previewer-time:before": {
background: "#f6f8fa",
},
".prism-previewer-easing.prism-previewer-easing": {
background: "#f6f8fa",
},
".prism-previewer-angle.prism-previewer-angle circle": {
stroke: "#24292e",
strokeOpacity: "1",
},
".prism-previewer-time.prism-previewer-time circle": {
stroke: "#24292e",
strokeOpacity: "1",
},
".prism-previewer-easing.prism-previewer-easing circle": {
stroke: "#24292e",
fill: "transparent",
},
".prism-previewer-easing.prism-previewer-easing path": {
stroke: "#24292e",
},
".prism-previewer-easing.prism-previewer-easing line": {
stroke: "#24292e",
},
}
export default theme

View File

@@ -0,0 +1,2 @@
export { default as githubLight } from "./github-light"
export { default as githubDark } from "./github-dark"

View File

@@ -0,0 +1,503 @@
const theme: { [key: string]: React.CSSProperties } = {
'code[class*="language-"]': {
background: "hsl(220, 13%, 18%)",
color: "hsl(220, 14%, 71%)",
textShadow: "0 1px rgba(0, 0, 0, 0.3)",
fontFamily: '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
direction: "ltr",
textAlign: "left",
whiteSpace: "pre",
wordSpacing: "normal",
wordBreak: "normal",
lineHeight: "1.5",
MozTabSize: "2",
OTabSize: "2",
tabSize: "2",
WebkitHyphens: "none",
MozHyphens: "none",
msHyphens: "none",
hyphens: "none",
},
'pre[class*="language-"]': {
background: "hsl(220, 13%, 18%)",
color: "hsl(220, 14%, 71%)",
textShadow: "0 1px rgba(0, 0, 0, 0.3)",
fontFamily: '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
direction: "ltr",
textAlign: "left",
whiteSpace: "pre",
wordSpacing: "normal",
wordBreak: "normal",
lineHeight: "1.5",
MozTabSize: "2",
OTabSize: "2",
tabSize: "2",
WebkitHyphens: "none",
MozHyphens: "none",
msHyphens: "none",
hyphens: "none",
padding: "1em",
margin: "0.5em 0",
overflow: "auto",
borderRadius: "0.3em",
},
'code[class*="language-"]::-moz-selection': {
background: "hsl(220, 13%, 28%)",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"] *::-moz-selection': {
background: "hsl(220, 13%, 28%)",
color: "inherit",
textShadow: "none",
},
'pre[class*="language-"] *::-moz-selection': {
background: "hsl(220, 13%, 28%)",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"]::selection': {
background: "hsl(220, 13%, 28%)",
color: "inherit",
textShadow: "none",
},
'code[class*="language-"] *::selection': {
background: "hsl(220, 13%, 28%)",
color: "inherit",
textShadow: "none",
},
'pre[class*="language-"] *::selection': {
background: "hsl(220, 13%, 28%)",
color: "inherit",
textShadow: "none",
},
':not(pre) > code[class*="language-"]': {
padding: "0.2em 0.3em",
borderRadius: "0.3em",
whiteSpace: "normal",
},
comment: {
color: "hsl(220, 10%, 40%)",
fontStyle: "italic",
},
prolog: {
color: "hsl(220, 10%, 40%)",
},
cdata: {
color: "hsl(220, 10%, 40%)",
},
doctype: {
color: "hsl(220, 14%, 71%)",
},
punctuation: {
color: "hsl(220, 14%, 71%)",
},
entity: {
color: "hsl(220, 14%, 71%)",
cursor: "help",
},
"attr-name": {
color: "hsl(29, 54%, 61%)",
},
"class-name": {
color: "hsl(29, 54%, 61%)",
},
boolean: {
color: "hsl(29, 54%, 61%)",
},
constant: {
color: "hsl(29, 54%, 61%)",
},
number: {
color: "hsl(29, 54%, 61%)",
},
atrule: {
color: "hsl(29, 54%, 61%)",
},
keyword: {
color: "hsl(286, 60%, 67%)",
},
property: {
color: "hsl(355, 65%, 65%)",
},
tag: {
color: "hsl(355, 65%, 65%)",
},
symbol: {
color: "hsl(355, 65%, 65%)",
},
deleted: {
color: "hsl(355, 65%, 65%)",
},
important: {
color: "hsl(355, 65%, 65%)",
},
selector: {
color: "hsl(95, 38%, 62%)",
},
string: {
color: "hsl(95, 38%, 62%)",
},
char: {
color: "hsl(95, 38%, 62%)",
},
builtin: {
color: "hsl(95, 38%, 62%)",
},
inserted: {
color: "hsl(95, 38%, 62%)",
},
regex: {
color: "hsl(95, 38%, 62%)",
},
"attr-value": {
color: "hsl(95, 38%, 62%)",
},
"attr-value > .token.punctuation": {
color: "hsl(95, 38%, 62%)",
},
variable: {
color: "hsl(207, 82%, 66%)",
},
operator: {
color: "hsl(207, 82%, 66%)",
},
function: {
color: "hsl(207, 82%, 66%)",
},
url: {
color: "hsl(187, 47%, 55%)",
},
"attr-value > .token.punctuation.attr-equals": {
color: "hsl(220, 14%, 71%)",
},
"special-attr > .token.attr-value > .token.value.css": {
color: "hsl(220, 14%, 71%)",
},
".language-css .token.selector": {
color: "hsl(355, 65%, 65%)",
},
".language-css .token.property": {
color: "hsl(220, 14%, 71%)",
},
".language-css .token.function": {
color: "hsl(187, 47%, 55%)",
},
".language-css .token.url > .token.function": {
color: "hsl(187, 47%, 55%)",
},
".language-css .token.url > .token.string.url": {
color: "hsl(95, 38%, 62%)",
},
".language-css .token.important": {
color: "hsl(286, 60%, 67%)",
},
".language-css .token.atrule .token.rule": {
color: "hsl(286, 60%, 67%)",
},
".language-javascript .token.operator": {
color: "hsl(286, 60%, 67%)",
},
".language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation":
{
color: "hsl(5, 48%, 51%)",
},
".language-json .token.operator": {
color: "hsl(220, 14%, 71%)",
},
".language-json .token.null.keyword": {
color: "hsl(29, 54%, 61%)",
},
".language-markdown .token.url": {
color: "hsl(220, 14%, 71%)",
},
".language-markdown .token.url > .token.operator": {
color: "hsl(220, 14%, 71%)",
},
".language-markdown .token.url-reference.url > .token.string": {
color: "hsl(220, 14%, 71%)",
},
".language-markdown .token.url > .token.content": {
color: "hsl(207, 82%, 66%)",
},
".language-markdown .token.url > .token.url": {
color: "hsl(187, 47%, 55%)",
},
".language-markdown .token.url-reference.url": {
color: "hsl(187, 47%, 55%)",
},
".language-markdown .token.blockquote.punctuation": {
color: "hsl(220, 10%, 40%)",
fontStyle: "italic",
},
".language-markdown .token.hr.punctuation": {
color: "hsl(220, 10%, 40%)",
fontStyle: "italic",
},
".language-markdown .token.code-snippet": {
color: "hsl(95, 38%, 62%)",
},
".language-markdown .token.bold .token.content": {
color: "hsl(29, 54%, 61%)",
},
".language-markdown .token.italic .token.content": {
color: "hsl(286, 60%, 67%)",
},
".language-markdown .token.strike .token.content": {
color: "hsl(355, 65%, 65%)",
},
".language-markdown .token.strike .token.punctuation": {
color: "hsl(355, 65%, 65%)",
},
".language-markdown .token.list.punctuation": {
color: "hsl(355, 65%, 65%)",
},
".language-markdown .token.title.important > .token.punctuation": {
color: "hsl(355, 65%, 65%)",
},
bold: {
fontWeight: "bold",
},
italic: {
fontStyle: "italic",
},
namespace: {
opacity: "0.8",
},
"token.tab:not(:empty):before": {
color: "hsla(220, 14%, 71%, 0.15)",
textShadow: "none",
},
"token.cr:before": {
color: "hsla(220, 14%, 71%, 0.15)",
textShadow: "none",
},
"token.lf:before": {
color: "hsla(220, 14%, 71%, 0.15)",
textShadow: "none",
},
"token.space:before": {
color: "hsla(220, 14%, 71%, 0.15)",
textShadow: "none",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item": {
marginRight: "0.4em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button": {
background: "hsl(220, 13%, 26%)",
color: "hsl(220, 9%, 55%)",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a": {
background: "hsl(220, 13%, 26%)",
color: "hsl(220, 9%, 55%)",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span": {
background: "hsl(220, 13%, 26%)",
color: "hsl(220, 9%, 55%)",
padding: "0.1em 0.4em",
borderRadius: "0.3em",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover": {
background: "hsl(220, 13%, 28%)",
color: "hsl(220, 14%, 71%)",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus": {
background: "hsl(220, 13%, 28%)",
color: "hsl(220, 14%, 71%)",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover": {
background: "hsl(220, 13%, 28%)",
color: "hsl(220, 14%, 71%)",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus": {
background: "hsl(220, 13%, 28%)",
color: "hsl(220, 14%, 71%)",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover": {
background: "hsl(220, 13%, 28%)",
color: "hsl(220, 14%, 71%)",
},
"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus": {
background: "hsl(220, 13%, 28%)",
color: "hsl(220, 14%, 71%)",
},
".line-highlight.line-highlight": {
background: "hsla(220, 100%, 80%, 0.04)",
},
".line-highlight.line-highlight:before": {
background: "hsl(220, 13%, 26%)",
color: "hsl(220, 14%, 71%)",
padding: "0.1em 0.6em",
borderRadius: "0.3em",
boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
},
".line-highlight.line-highlight[data-end]:after": {
background: "hsl(220, 13%, 26%)",
color: "hsl(220, 14%, 71%)",
padding: "0.1em 0.6em",
borderRadius: "0.3em",
boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
},
"pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before": {
backgroundColor: "hsla(220, 100%, 80%, 0.04)",
},
".line-numbers.line-numbers .line-numbers-rows": {
borderRightColor: "hsla(220, 14%, 71%, 0.15)",
},
".command-line .command-line-prompt": {
borderRightColor: "hsla(220, 14%, 71%, 0.15)",
},
".line-numbers .line-numbers-rows > span:before": {
color: "hsl(220, 14%, 45%)",
},
".command-line .command-line-prompt > span:before": {
color: "hsl(220, 14%, 45%)",
},
".rainbow-braces .token.token.punctuation.brace-level-1": {
color: "hsl(355, 65%, 65%)",
},
".rainbow-braces .token.token.punctuation.brace-level-5": {
color: "hsl(355, 65%, 65%)",
},
".rainbow-braces .token.token.punctuation.brace-level-9": {
color: "hsl(355, 65%, 65%)",
},
".rainbow-braces .token.token.punctuation.brace-level-2": {
color: "hsl(95, 38%, 62%)",
},
".rainbow-braces .token.token.punctuation.brace-level-6": {
color: "hsl(95, 38%, 62%)",
},
".rainbow-braces .token.token.punctuation.brace-level-10": {
color: "hsl(95, 38%, 62%)",
},
".rainbow-braces .token.token.punctuation.brace-level-3": {
color: "hsl(207, 82%, 66%)",
},
".rainbow-braces .token.token.punctuation.brace-level-7": {
color: "hsl(207, 82%, 66%)",
},
".rainbow-braces .token.token.punctuation.brace-level-11": {
color: "hsl(207, 82%, 66%)",
},
".rainbow-braces .token.token.punctuation.brace-level-4": {
color: "hsl(286, 60%, 67%)",
},
".rainbow-braces .token.token.punctuation.brace-level-8": {
color: "hsl(286, 60%, 67%)",
},
".rainbow-braces .token.token.punctuation.brace-level-12": {
color: "hsl(286, 60%, 67%)",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)": {
backgroundColor: "hsla(353, 100%, 66%, 0.15)",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)": {
backgroundColor: "hsla(353, 100%, 66%, 0.15)",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection": {
backgroundColor: "hsla(353, 95%, 66%, 0.25)",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)": {
backgroundColor: "hsla(137, 100%, 55%, 0.15)",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)": {
backgroundColor: "hsla(137, 100%, 55%, 0.15)",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection": {
backgroundColor: "hsla(135, 73%, 55%, 0.25)",
},
".prism-previewer.prism-previewer:before": {
borderColor: "hsl(224, 13%, 17%)",
},
".prism-previewer-gradient.prism-previewer-gradient div": {
borderColor: "hsl(224, 13%, 17%)",
borderRadius: "0.3em",
},
".prism-previewer-color.prism-previewer-color:before": {
borderRadius: "0.3em",
},
".prism-previewer-easing.prism-previewer-easing:before": {
borderRadius: "0.3em",
},
".prism-previewer.prism-previewer:after": {
borderTopColor: "hsl(224, 13%, 17%)",
},
".prism-previewer-flipped.prism-previewer-flipped.after": {
borderBottomColor: "hsl(224, 13%, 17%)",
},
".prism-previewer-angle.prism-previewer-angle:before": {
background: "hsl(219, 13%, 22%)",
},
".prism-previewer-time.prism-previewer-time:before": {
background: "hsl(219, 13%, 22%)",
},
".prism-previewer-easing.prism-previewer-easing": {
background: "hsl(219, 13%, 22%)",
},
".prism-previewer-angle.prism-previewer-angle circle": {
stroke: "hsl(220, 14%, 71%)",
strokeOpacity: "1",
},
".prism-previewer-time.prism-previewer-time circle": {
stroke: "hsl(220, 14%, 71%)",
strokeOpacity: "1",
},
".prism-previewer-easing.prism-previewer-easing circle": {
stroke: "hsl(220, 14%, 71%)",
fill: "transparent",
},
".prism-previewer-easing.prism-previewer-easing path": {
stroke: "hsl(220, 14%, 71%)",
},
".prism-previewer-easing.prism-previewer-easing line": {
stroke: "hsl(220, 14%, 71%)",
},
}
export default theme

View File

@@ -0,0 +1,79 @@
import { WebviewMessage } from "@shared/WebviewMessage"
import type { WebviewApi } from "vscode-webview"
/**
* A utility wrapper around the acquireVsCodeApi() function, which enables
* message passing and state management between the webview and extension
* contexts.
*
* This utility also enables webview code to be run in a web browser-based
* dev server by using native web browser features that mock the functionality
* enabled by acquireVsCodeApi.
*/
class VSCodeAPIWrapper {
private readonly vsCodeApi: WebviewApi<unknown> | undefined
constructor() {
// Check if the acquireVsCodeApi function exists in the current development
// context (i.e. VS Code development window or web browser)
if (typeof acquireVsCodeApi === "function") {
this.vsCodeApi = acquireVsCodeApi()
}
}
/**
* Post a message (i.e. send arbitrary data) to the owner of the webview.
*
* @remarks When running webview code inside a web browser, postMessage will instead
* log the given message to the console.
*
* @param message Abitrary data (must be JSON serializable) to send to the extension context.
*/
public postMessage(message: WebviewMessage) {
if (this.vsCodeApi) {
this.vsCodeApi.postMessage(message)
} else {
console.log(message)
}
}
/**
* Get the persistent state stored for this webview.
*
* @remarks When running webview source code inside a web browser, getState will retrieve state
* from local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
*
* @return The current state or `undefined` if no state has been set.
*/
public getState(): unknown | undefined {
if (this.vsCodeApi) {
return this.vsCodeApi.getState()
} else {
const state = localStorage.getItem("vscodeState")
return state ? JSON.parse(state) : undefined
}
}
/**
* Set the persistent state stored for this webview.
*
* @remarks When running webview source code inside a web browser, setState will set the given
* state using local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
*
* @param newState New persisted state. This must be a JSON serializable object. Can be retrieved
* using {@link getState}.
*
* @return The new state.
*/
public setState<T extends unknown | undefined>(newState: T): T {
if (this.vsCodeApi) {
return this.vsCodeApi.setState(newState)
} else {
localStorage.setItem("vscodeState", JSON.stringify(newState))
return newState
}
}
}
// Exports class singleton to prevent multiple invocations of acquireVsCodeApi.
export const vscode = new VSCodeAPIWrapper()