style: Update code syntax highlighting colors

This commit is contained in:
Gauthier Daniels 2025-04-20 21:32:16 +02:00
parent 8418ca4a74
commit 602669a9c0
5 changed files with 174 additions and 559 deletions

View File

@ -8,320 +8,16 @@ import {
on,
splitProps,
} from "solid-js";
import { clipboard } from "solid-heroicons/solid";
import { Icon } from "solid-heroicons";
import * as Prismjs from "prismjs";
import toast from "solid-toast";
import clsx from "clsx";
/**
* @see https://prismjs.com/#supported-languages
*/
export const Language = {
JAVASCRIPT: "javascript",
HTML: "html",
CSS: "css",
MARKUP: "markup",
XML: "xml",
SVG: "svg",
ABAP: "abap",
ABNF: "abnf",
ACTION_SCRIPT: "actionscript",
ADA: "ada",
AGDA: "agda",
AL: "al",
ANTLR4: "antlr4",
G4: "g4",
APACHE_CONFIGURATION: "apacheconf",
APEX: "apex",
APL: "apl",
APPLESCRIPT: "applescript",
AQL: "aql",
ARDUINO: "arduino",
ARFF: "arff",
ARM_ASSEMBLY: "armasm",
ARTURO: "arturo",
ASCIIDOC: "asciidoc",
ASP_NET: "aspnet",
ASSEMBLY_6502: "asm6502",
ASSEMBLY_ATMEL_AVR: "asmatmel",
AUTO_HOTKEY: "autohotkey",
AUTO_IT: "autoit",
AVI_SYNTH: "avisynth",
AVRO_IDL: "avro-idl",
AWK: "awk",
BASH: "bash",
BASIC: "basic",
BATCH: "batch",
BBCODE: "bbcode",
BBJ: "bbj",
BICEP: "bicep",
BIRB: "birb",
BISON: "bison",
BNF: "bnf",
BQN: "bqn",
BRAINFUCK: "brainfuck",
BRIGHT_SCRIPT: "brightscript",
BRO: "bro",
BSL: "bsl",
C: "c",
CSHARP: "csharp",
CPP: "cpp",
CF_SCRIPT: "cfscript",
CHAI_SCRIPT: "chaiscript",
CIL: "cil",
CILK_C: "cilkc",
CILK_CPP: "cilkcpp",
CLOJURE: "clojure",
CMAKE: "cmake",
COBOL: "cobol",
COFFEE_SCRIPT: "coffeescript",
CONCURNAS: "concurnas",
CONTENT_SECURITY_POLICY: "csp",
COOKLANG: "cooklang",
Coq: "coq",
CRYSTAL: "crystal",
CSS_EXTRAS: "css-extras",
CSV: "csv",
CUE: "cue",
CYPHER: "cypher",
D: "d",
DART: "dart",
DATA_WEAVE: "dataweave",
DAX: "dax",
DHALL: "dhall",
DIFF: "diff",
DJANGO: "django",
JINJA2: "jinja2",
DNS_ZONE_FILE: "dns-zone-file",
DOCKER: "docker",
DOT: "dot",
EBNF: "ebnf",
EDITOR_CONFIG: "editorconfig",
EIFFEL: "eiffel",
EJS: "ejs",
ELIXIR: "elixir",
ELM: "elm",
EMBEDDED_LUA_TEMPLATING: "etlua",
ERB: "erb",
ERLANG: "erlang",
EXCEL_FORMULA: "excel-formula",
FSHARP: "fsharp",
FACTOR: "factor",
FALSE: "false",
FIRESTORE_SECURITY_RULES: "firestore-security-rules",
FLOW: "flow",
FORTRAN: "fortran",
FREEMARKER_TEMPLATE_LANGUAGE: "ftl",
GAMEMAKER_LANGUAGE: "gml",
GAP: "gap",
GCODE: "gcode",
GD_SCRIPT: "gdscript",
GEDCOM: "gedcom",
GETTEXT: "gettext",
GHERKIN: "gherkin",
GIT: "git",
GLSL: "glsl",
GN: "gn",
GNU_LINKER_SCRIPT: "linker-script",
GO: "go",
GO_MODULE: "go-module",
GRADLE: "gradle",
GRAPHQL: "graphql",
GROOVY: "groovy",
HAML: "haml",
HANDLEBARS: "handlebars",
HASKELL: "haskell",
HAXE: "haxe",
HCL: "hcl",
HLSL: "hlsl",
HOON: "hoon",
HTTP: "http",
HTTP_PUBLIC_KEY_PINS: "hpkp",
HTTP_STRICT_TRANSPORT_SECURITY: "hsts",
ICHIGOJAM: "ichigojam",
ICON: "icon",
ICU_MESSAGE_FORMAT: "icu-message-format",
IDRIS: "idris",
IGNORE: "ignore",
INFORM_7: "inform7",
INI: "ini",
IO: "io",
J: "j",
JAVA: "java",
JAVADOC: "javadoc",
JAVADOC_LIKE: "javadoclike",
JAVA_STACK_TRACE: "javastacktrace",
JEXL: "jexl",
JOLIE: "jolie",
JQ: "jq",
JSDOC: "jsdoc",
JS_EXTRAS: "js-extras",
JSON: "json",
JSON5: "json5",
JSONP: "jsonp",
JS_STACK_TRACE: "jsstacktrace",
JS_TEMPLATES: "js-templates",
JULIA: "julia",
KEEPALIVED_CONFIGURE: "keepalived",
KEYMAN: "keyman",
KOTLIN: "kotlin",
KUMIR: "kumir",
KUSTO: "kusto",
LATEX: "latex",
LATTE: "latte",
LESS: "less",
LILYPOND: "lilypond",
LIQUID: "liquid",
LISP: "lisp",
LIVESCRIPT: "livescript",
LLVM: "llvm",
LOG: "log",
LOLCODE: "lolcode",
LUA: "lua",
MAGMA: "magma",
MAKEFILE: "makefile",
MARKDOWN: "markdown",
MARKUP_TEMPLATING: "markup-templating",
MATA: "mata",
MATLAB: "matlab",
MAXSCRIPT: "maxscript",
MEL: "mel",
MERMAID: "mermaid",
METAFONT: "metafont",
MIZAR: "mizar",
MONGODB: "mongodb",
MONKEY: "monkey",
MOONSCRIPT: "moonscript",
N1QL: "n1ql",
N4JS: "n4js",
NAND_TO_TETRIS_HDL: "nand2tetris",
NANINOVEL_SCRIPT: "naniscript",
NASM: "nasm",
NEON: "neon",
NEVOD: "nevod",
NGINX: "nginx",
NIM: "nim",
NIX: "nix",
NSIS: "nsis",
OBJECTIVE_C: "objectivec",
OCAML: "ocaml",
ODIN: "odin",
OPENCL: "opencl",
OPENQASM: "openqasm",
OZ: "oz",
PARI_GP: "parigp",
PARSER: "parser",
PASCAL: "pascal",
PASCALIGO: "pascaligo",
PATROL_SCRIPTING_LANGUAGE: "psl",
PC_AXIS: "pcaxis",
PEOPLECODE: "peoplecode",
PERL: "perl",
PHP: "php",
PHP_DOC: "phpdoc",
PHP_EXTRAS: "php-extras",
PLANT_UML: "plant-uml",
PL_SQL: "plsql",
POWERQUERY: "powerquery",
POWERSHELL: "powershell",
PROCESSING: "processing",
PROLOG: "prolog",
PROMQL: "promql",
PROPERTIES: "properties",
PROTOBUF: "protobuf",
PUG: "pug",
PUPPET: "puppet",
PURE: "pure",
PUREBASIC: "purebasic",
PURESCRIPT: "purescript",
PYTHON: "python",
QSHARP: "qsharp",
Q: "q",
QML: "qml",
QORE: "qore",
R: "r",
RACKET: "racket",
RAZOR: "razor",
REACT_JSX: "jsx",
REACT_TSX: "tsx",
REASON: "reason",
REGEX: "regex",
REGO: "rego",
RENPY: "renpy",
RESCRIPT: "rescript",
REST: "rest",
RIP: "rip",
ROBOCONF: "roboconf",
ROBOT_FRAMEWORK: "robotframework",
RUBY: "ruby",
RUST: "rust",
SAS: "sas",
SASS: "sass",
SCSS: "scss",
SCALA: "scala",
SCHEME: "scheme",
SHELL_SESSION: "shell-session",
SMALI: "smali",
SMALLTALK: "smalltalk",
SMARTY: "smarty",
SML: "sml",
SOLIDITY: "solidity",
SOLUTION_FILE: "solution-file",
SOY: "soy",
SPARQL: "sparql",
SPLUNK_SPL: "splunk-spl",
SQF: "sqf",
SQL: "sql",
SQUIRREL: "squirrel",
STAN: "stan",
STATA_ADO: "stata",
STRUCTURED_TEXT: "iecst",
STYLUS: "stylus",
SUPERCOLLIDER: "supercollider",
SWIFT: "swift",
SYSTEMD: "systemd",
T4_TEMPLATING: "t4-templating",
T4_CSHARP: "t4-cs",
T4_VB: "t4-vb",
TAP: "tap",
TCL: "tcl",
TEMPLATE_TOOLKIT_2: "tt2",
TEXTILE: "textile",
TOML: "toml",
TREMOR: "tremor",
TURTLE: "turtle",
TWIG: "twig",
TYPESCRIPT: "typescript",
TYPOSCRIPT: "typoscript",
UNREALSCRIPT: "unrealscript",
UO_RAZOR_SCRIPT: "uorazor",
URI: "uri",
V: "v",
VALA: "vala",
VB_NET: "vbnet",
VELOCITY: "velocity",
VERILOG: "verilog",
VHDL: "vhdl",
VIM: "vim",
VISUAL_BASIC: "visual-basic",
WARP_SCRIPT: "warpscript",
WEB_ASSEMBLY: "wasm",
WEB_IDL: "web-idl",
WGSL: "wgsl",
WIKI: "wiki",
WOLFRAM: "wolfram",
WREN: "wren",
XEORA: "xeora",
XML_DOC: "xml-doc",
XOJO: "xojo",
XQUERY: "xquery",
YAML: "yaml",
YANG: "yang",
ZIG: "zig",
} as const;
export type Language = (typeof Language)[keyof typeof Language];
type Props = {
language: string;
class?: string;
dark?: boolean;
withLineNumbers?: boolean;
} & ComponentProps<"code">;
@ -354,13 +50,42 @@ export const Highlight: ParentComponent<Props> = (_props) => {
}),
);
const handleCopyToClipboard = () => {
if (props.innerHTML) {
navigator.clipboard.writeText(props.innerHTML);
} else if (props.children) {
navigator.clipboard.writeText(props.children.toString());
}
toast.success("Copié dans le presse-papier", {
duration: 2000,
position: "top-right",
});
};
return (
<div
class={clsx(
"rounded-xl shadow-lg flex items-start px-4 py-2 w-full",
"group relative flex items-start px-4 py-2 w-full",
props.class,
)}
>
<button
class="absolute cursor-pointer top-0 right-2 text-slate-500 bg-slate-200/10 rounded-md hover:bg-linear-to-r hover:from-violet-400/30 hover:via-violet-400 hover:to-violet-400/30 p-px hover:text-violet-300"
type="button"
onClick={handleCopyToClipboard}
>
<span
class={clsx(
props.dark ? "hover:bg-slate-800" : "hover:bg-white",
"p-2 block rounded-md",
)}
>
<span class="sr-only">Copier l'extrait de code</span>
<Icon path={clipboard} class="w-5 h-5" />
</span>
</button>
{props.withLineNumbers && props.children?.toString() && (
<div
aria-hidden="true"

View File

@ -1,4 +1,4 @@
import type { JSX, Accessor, Setter } from "solid-js";
import type { JSX } from "solid-js";
import { For, createSignal } from "solid-js";
import { Highlight } from "./Highlight";
@ -24,6 +24,7 @@ type SnippetProps = {
children?: JSX.Element;
class?: string;
snippets: SnippetTab[];
dark?: boolean;
};
export function Snippet(props: SnippetProps) {
@ -40,7 +41,8 @@ export function Snippet(props: SnippetProps) {
return (
<div
class={clsx(
"relative rounded-2xl bg-[#0A101F]/80 ring-1 ring-white/10 backdrop-blur-sm",
"relative rounded-2xl ring-1 ring-white/10 backdrop-blur-sm",
props.dark ? "bg-[#0A101F]/80" : "bg-slate-50",
props.class,
)}
>
@ -48,6 +50,7 @@ export function Snippet(props: SnippetProps) {
<div class="absolute right-20 -bottom-px left-11 h-px bg-linear-to-r from-purple-400/0 via-purple-400 to-purple-400/0" />
<div class="pt-4 pl-4">
<TrafficLightsIcon class="h-2.5 w-auto stroke-slate-500/30" />
<div class="mt-4 flex space-x-2 text-xs">
<For each={props.snippets}>
{(tab) => (
@ -56,7 +59,12 @@ export function Snippet(props: SnippetProps) {
"flex h-6 rounded-full",
{ "cursor-pointer": tab.codeLanguage && !isActive(tab) },
isActive(tab)
? "bg-linear-to-r from-violet-400/30 via-violet-400 to-violet-400/30 p-px font-medium text-violet-300"
? clsx(
"bg-linear-to-r from-violet-400/30 via-violet-400 to-violet-400/30 p-px font-medium",
props.dark ? "text-violet-300" : "text-violet-600",
)
: props.dark
? "text-slate-400"
: "text-slate-500",
)}
>
@ -64,7 +72,9 @@ export function Snippet(props: SnippetProps) {
type="button"
class={clsx(
"flex items-center rounded-full px-2.5",
isActive(tab) && "bg-slate-800",
isActive(tab) && props.dark
? "bg-slate-800"
: "bg-violet-100",
)}
disabled={!tab.codeLanguage}
onClick={() => selectTab(tab.name)}
@ -79,7 +89,10 @@ export function Snippet(props: SnippetProps) {
{selectedTab() && (
<div class="mt-6">
<Highlight
class="dark !pt-0 !px-1"
class={clsx(
"!pt-0 !px-1 max-h-96 overflow-auto",
props.dark && "dark text-white",
)}
language={selectedTab().codeLanguage}
withLineNumbers
>

View File

@ -1,195 +1,80 @@
code[class*="language-"],
pre[class*="language-"] {
color: #383a42;
background: none;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection,
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
background: #DDE3EA;
text-shadow: none;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
:not(pre) > code[class*="language-"] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #a0a1a7;
}
.token.plain-text,
.token.punctuation {
color: #383a42;
}
.token.selector,
.token.tag {
color: #e45649;
}
.token.property,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.attr-name,
.token.deleted {
color: #e1aa76;
}
.token.string,
.token.char,
.token.attr-value,
.token.builtin,
.token.inserted {
color: #50a14f;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #46a6b2;
}
.token.function {
color: #4078f2;
}
.token.atrule,
.token.keyword,
.token.regex,
.token.important,
.token.variable {
color: #a626a4;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
.token.comment {
font-style: italic;
}
.token.entity {
cursor: help;
}
pre.line-numbers {
position: relative;
padding-left: 3.8em;
counter-reset: linenumber;
}
pre.line-numbers > code {
position: relative;
}
.line-numbers .line-numbers-rows {
position: absolute;
pointer-events: none;
top: 0;
font-size: 100%;
left: -3.8em;
width: 3em;
letter-spacing: -1px;
border-right: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.line-numbers-rows > span {
pointer-events: none;
display: block;
counter-increment: linenumber;
}
.line-numbers-rows > span:before {
content: counter(linenumber);
color: #b5b9c2;
display: block;
padding-right: 0.8em;
text-align: right;
}
code.language-css,
pre.languagecss {
color: #E45649;
}
code.language-javascript,
pre.languagejavascript {
color: #E45649;
}
code.language-js,
pre.languagejs {
color: #E45649;
}
code.language-jsx,
pre.languagejsx {
color: #E45649;
}
code.language-sass,
pre.languagesass {
color: #E45649;
}
code.language-scss,
pre.languagescss {
color: #E45649;
}
code.language-ts,
pre.languagets {
color: #E45649;
}
code.language-tsx,
pre.languagetsx {
color: #E45649;
}
code.language-typescript,
pre.languagetypescript {
color: #E45649;
}
.dark pre[class*="language-"] {
color: var(--color-slate-50);
}
.dark .token.module {
color: var(--color-pink-400)!important;
}
.dark .token.module,
.dark .token.attr-name,
.dark .token.keyword,
.dark .token.rule,
.dark .token.pseudo-class,
.dark .token.important {
color: var(--color-slate-300);
color: #CB5FDE;
}
.dark .token.comment,
.dark .token.operator,
.dark .token.combinator {
color: var(--color-slate-400);
}
.dark .token.punctuation,
.dark .token.attr-equals {
color: var(--color-slate-500);
}
.dark .token.attr-value,
.dark .token.class,
.dark .token.string,
.dark .token.property {
color: var(--color-sky-300);
.dark .token.string {
color: #89CA6C;
}
.dark .token.property,
.dark .token.tag {
color: #E3596F;
}
.dark .token.function-variable {
color: #61AFEF;
}
/** Light mode */
.token.attr-value,
.token.class,
.token.string {
color: #50A14F;
}
.token.function-variable,
.token.generic-function,
.token.function {
color: #4078F2;
}
.token.module,
.token.attr-name,
.token.keyword,
.token.rule,
.token.pseudo-class,
.token.important {
color: #A626A4;
}
.token.property,
.token.tag {
color: #E55649;
}
.token.generic,
.token.class-name {
color: #C18401;
}
.token.comment,
.token.combinator {
color: #A0A1A7;
}
.token.operator,
.token.builtin {
color: #0184BC;
}

View File

@ -1,31 +1,25 @@
import { Highlight } from "@/components/Highlight";
import Tabs from "@/components/Tabs";
import { Snippet } from "@/components/Snippet";
export default {
reactTodolist: () => {
return (
<Tabs defaultSelectedTab="app">
<Tabs.Item value="app" label="App.tsx">
<Highlight language="tsx" withLineNumbers>
{`import TodoList from "./TodoList";
const reactTodoListSnippets = [
{
name: "App.tsx",
codeLanguage: "tsx",
code: `import TodoList from "./TodoList";
import React from "react";
const App = () => {
return (
<div>
<h1>TodoList</h1>
<TodoList />
</div>
);
};`}
</Highlight>
</Tabs.Item>
<Tabs.Item value="todolist" label="TodoList.tsx">
{`
\`\`\`tsx showLineNumbers
import TodoListItem from "./TodoListItem";
};`,
},
{
name: "TodoList.tsx",
codeLanguage: "tsx",
code: `import TodoListItem from "./TodoListItem";
import React from "react";
const TodoList = () => {
@ -66,15 +60,12 @@ const App = () => {
);
};
export default TodoList;
\`\`\`
`}
</Tabs.Item>
<Tabs.Item value="todolistitem" label="TodoListItem.tsx">
{`
\`\`\`tsx showLineNumbers
import React from "react";
export default TodoList;`,
},
{
name: "TodoListItem.tsx",
codeLanguage: "tsx",
code: `import React from "react";
interface TodoListItemProps {
item: string;
@ -84,11 +75,12 @@ const App = () => {
return <span>{props.item}</span>;
};
export default TodoListItem;
\`\`\`
`}
</Tabs.Item>
</Tabs>
);
export default TodoListItem;`,
},
];
export default {
reactTodolist: () => {
return <Snippet snippets={reactTodoListSnippets} />;
},
};

View File

@ -97,7 +97,7 @@ export function HeroSection() {
<div class="absolute inset-0 rounded-2xl bg-linear-to-tr from-violet-300 via-violet-300/70 to-purple-300 opacity-10 blur-lg" />
<div class="absolute inset-0 rounded-2xl bg-linear-to-tr from-violet-300 via-violet-300/70 to-purple-300 opacity-10" />
<Snippet class="min-h-64" snippets={snippets} />
<Snippet class="min-h-64" dark snippets={snippets} />
</div>
</div>
</div>