From bd4ce16b675998fbd10cb95e772887407f18062b Mon Sep 17 00:00:00 2001 From: GauthierWebDev Date: Sat, 19 Apr 2025 19:19:13 +0200 Subject: [PATCH] feat: Add Prism.js support and configure languages --- app/bun.lock | 22 +++ app/components/Highlight.tsx | 361 ++++++++++++++++++++++++++++++++++ app/fastify-entry.ts | 24 +-- app/layouts/LayoutDefault.tsx | 4 +- app/layouts/prism.css | 55 ++++++ app/layouts/style.css | 6 + app/layouts/tailwind.css | 45 +++++ app/package.json | 6 +- app/pages/+Head.tsx | 33 ++-- app/partials/HeroSection.tsx | 20 +- app/vite.config.ts | 13 ++ biome.json | 26 +-- 12 files changed, 556 insertions(+), 59 deletions(-) create mode 100644 app/components/Highlight.tsx create mode 100644 app/layouts/prism.css diff --git a/app/bun.lock b/app/bun.lock index 83ec662..a2bd847 100644 --- a/app/bun.lock +++ b/app/bun.lock @@ -7,10 +7,12 @@ "@fastify/static": "^8.1.1", "@mdx-js/rollup": "^3.1.0", "@sindresorhus/slugify": "^2.2.1", + "@tailwindcss/typography": "^0.5.16", "@universal-middleware/core": "^0.4.7", "@universal-middleware/fastify": "^0.5.16", "clsx": "^2.1.1", "fastify": "^5.3.0", + "prismjs": "^1.30.0", "solid-heroicons": "^3.2.4", "solid-highlight": "^0.1.26", "solid-js": "^1.9.5", @@ -21,12 +23,14 @@ "terracotta": "^1.0.6", "vike": "^0.4.228", "vike-solid": "^0.7.9", + "vite-plugin-prismjs": "^0.0.11", }, "devDependencies": { "@biomejs/biome": "1.9.4", "@eslint/js": "^9.24.0", "@tailwindcss/vite": "^4.1.3", "@types/node": "^18.19.86", + "@types/prismjs": "^1.26.5", "cross-env": "^7.0.3", "eslint": "^9.24.0", "eslint-config-prettier": "^10.1.2", @@ -304,6 +308,8 @@ "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+7S63t5zhYjslUGb8NcgLpFXD+Kq1F/zt5Xv5qTv7HaFTG/DHyHD9GA6ieNAxhgyA4IcKa/zy7Xx4Oad2/wuhw=="], + "@tailwindcss/typography": ["@tailwindcss/typography@0.5.16", "", { "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA=="], + "@tailwindcss/vite": ["@tailwindcss/vite@4.1.4", "", { "dependencies": { "@tailwindcss/node": "4.1.4", "@tailwindcss/oxide": "4.1.4", "tailwindcss": "4.1.4" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-4UQeMrONbvrsXKXXp/uxmdEN5JIJ9RkH7YVzs6AMxC/KC1+Np7WZBaNIco7TEjlkthqxZbt8pU/ipD+hKjm80A=="], "@ts-morph/common": ["@ts-morph/common@0.20.0", "", { "dependencies": { "fast-glob": "^3.2.12", "minimatch": "^7.4.3", "mkdirp": "^2.1.6", "path-browserify": "^1.0.1" } }, "sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q=="], @@ -334,6 +340,8 @@ "@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="], + "@types/prismjs": ["@types/prismjs@1.26.5", "", {}, "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.30.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.30.1", "@typescript-eslint/type-utils": "8.30.1", "@typescript-eslint/utils": "8.30.1", "@typescript-eslint/visitor-keys": "8.30.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q=="], @@ -384,6 +392,8 @@ "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.39.7", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2", "validate-html-nesting": "^1.2.1" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-8GzVmFla7jaTNWW8W+lTMl9YGva4/06CtwJjySnkYtt8G1v9weCzc2SuF1DfrudcCNb2Doetc1FRg33swBYZCA=="], + "babel-plugin-prismjs": ["babel-plugin-prismjs@2.1.0", "", { "peerDependencies": { "prismjs": "^1.18.0" } }, "sha512-ehzSKYfeAz4U78zi/sfwsjDPlq0LvDKxNefcZTJ/iKBu+plsHsLqZhUeGf1+82LAcA35UZGbU6ksEx2Utphc/g=="], + "babel-preset-solid": ["babel-preset-solid@1.9.5", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.39.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-85I3osODJ1LvZbv8wFozROV1vXq32BubqHXAGu73A//TRs3NLI1OFP83AQBUTSQHwgZQmARjHlJciym3we+V+w=="], "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], @@ -442,6 +452,8 @@ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], @@ -686,6 +698,10 @@ "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + "lodash.castarray": ["lodash.castarray@4.4.0", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="], + + "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], @@ -832,6 +848,8 @@ "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + "postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="], + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], @@ -1028,6 +1046,8 @@ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "validate-html-nesting": ["validate-html-nesting@1.2.2", "", {}, "sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], @@ -1040,6 +1060,8 @@ "vite": ["vite@6.3.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.3", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.12" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg=="], + "vite-plugin-prismjs": ["vite-plugin-prismjs@0.0.11", "", { "dependencies": { "@babel/core": "^7.15.5", "babel-plugin-prismjs": "^2.1.0" } }, "sha512-20NBQxg/zH+3FTrlU6BQTob720xkuXNYtrx7psAQ4E6pMcRDeLEK77QU9kXURU587+f2To7ASH1JVTGbXVV/vQ=="], + "vite-plugin-solid": ["vite-plugin-solid@2.11.6", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-Sl5CTqJTGyEeOsmdH6BOgalIZlwH3t4/y0RQuFLMGnvWMBvxb4+lq7x3BSiAw6etf0QexfNJW7HSOO/Qf7pigg=="], "vitefu": ["vitefu@1.0.6", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA=="], diff --git a/app/components/Highlight.tsx b/app/components/Highlight.tsx new file mode 100644 index 0000000..a453d07 --- /dev/null +++ b/app/components/Highlight.tsx @@ -0,0 +1,361 @@ +import type { JSX, ComponentProps, ParentComponent } from "solid-js"; + +import { createEffect, createMemo, mergeProps, on, splitProps } from "solid-js"; +import * as Prismjs from "prismjs"; + +/** + * @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; +} & ( + | (ComponentProps<"code"> & { code?: never }) + | (Omit & { code: string }) +); + +export const Highlight: ParentComponent = (_props) => { + const props = mergeProps({ language: "javascript" }, _props); + const [, rest] = splitProps(props, [ + "language", + "children", + "class", + "innerHTML", + ]); + + const languageClass = createMemo(() => `language-${props.language}`); + const highlightedCode = createMemo(() => { + const childrenString = props.children?.toString(); + if (!childrenString) { + return; + } + const grammar = Prismjs.languages[props.language]; + if (!grammar) { + return; + } + const result = Prismjs.highlight(childrenString, grammar, props.language); + return result; + }); + + createEffect( + on([languageClass, highlightedCode], () => { + Prismjs.highlightAll(); + }), + ); + + return ( +
+			
+				{props.code || props.children}
+			
+		
+ ); +}; diff --git a/app/fastify-entry.ts b/app/fastify-entry.ts index ef2017a..1cc6c5d 100755 --- a/app/fastify-entry.ts +++ b/app/fastify-entry.ts @@ -1,9 +1,9 @@ -import { fileURLToPath } from "node:url"; -import { dirname } from "node:path"; - import { createHandler } from "@universal-middleware/fastify"; import { telefuncHandler } from "./server/telefunc-handler"; import { vikeHandler } from "./server/vike-handler"; +import { createDevMiddleware } from "vike/server"; +import { fileURLToPath } from "node:url"; +import { dirname } from "node:path"; import { config } from "./config"; import Fastify from "fastify"; @@ -27,17 +27,13 @@ async function startServer() { wildcard: false, }); } else { - // Instantiate Vite's development server and integrate its middleware to our server. - // ⚠️ We should instantiate it *only* in development. (It isn't needed in production - // and would unnecessarily bloat our server in production.) - const vite = await import("vite"); - const viteDevMiddleware = ( - await vite.createServer({ - root, - server: { middlewareMode: true, hmr: { port: config.HMR_PORT } }, - }) - ).middlewares; - app.use(viteDevMiddleware); + const { devMiddleware } = await createDevMiddleware({ + root, + viteConfig: { + server: { hmr: { port: config.HMR_PORT } }, + }, + }); + app.use(devMiddleware); } app.post<{ Body: string }>("/_telefunc", createHandler(telefuncHandler)()); diff --git a/app/layouts/LayoutDefault.tsx b/app/layouts/LayoutDefault.tsx index d37bcda..9a77f50 100755 --- a/app/layouts/LayoutDefault.tsx +++ b/app/layouts/LayoutDefault.tsx @@ -13,10 +13,10 @@ import { Logo } from "@/components/Logo"; import { Toaster } from "solid-toast"; import clsx from "clsx"; -import "./style.css"; +// import "./style.css"; import "./tailwind.css"; // import "./prism.css"; -import "unfonts.css"; +// import "unfonts.css"; // const Search = clientOnly(() => import("@/components/Search").then((module) => module.Search)); diff --git a/app/layouts/prism.css b/app/layouts/prism.css new file mode 100644 index 0000000..0b4c69a --- /dev/null +++ b/app/layouts/prism.css @@ -0,0 +1,55 @@ +pre[class*="language-"] { + color: var(--color-slate-50); +} + +.token.tag, +.token.class-name, +.token.selector, +.token.selector .class, +.token.selector.class, +.token.function { + color: var(--color-pink-400); +} + +.token.attr-name, +.token.keyword, +.token.rule, +.token.pseudo-class, +.token.important { + color: var(--color-slate-300); +} + +.token.module { + color: var(--color-pink-400); +} + +.token.attr-value, +.token.class, +.token.string, +.token.property { + color: var(--color-sky-300); +} + +.token.punctuation, +.token.attr-equals { + color: var(--color-slate-500); +} + +.token.unit, +.language-css .token.function { + color: var(--color-teal-200); +} + +.token.comment, +.token.operator, +.token.combinator { + color: var(--color-slate-400); +} + +.prism-code { + margin: 0; +} + +.prism-code + .prism-code { + margin-bottom: 1rem; +} diff --git a/app/layouts/style.css b/app/layouts/style.css index c5a3d28..483a6de 100755 --- a/app/layouts/style.css +++ b/app/layouts/style.css @@ -27,3 +27,9 @@ body { body.page-is-transitioning #page-content { opacity: 0; } + +#root { + height: 100%; + width: 100%; + display: flex; +} diff --git a/app/layouts/tailwind.css b/app/layouts/tailwind.css index 44f8c8f..7393f0a 100755 --- a/app/layouts/tailwind.css +++ b/app/layouts/tailwind.css @@ -1,2 +1,47 @@ +@import "./prism.css"; @import "./style.css"; @import "tailwindcss"; + +@plugin '@tailwindcss/typography'; + +@theme { + --text-*: initial; + --text-xs: 0.75rem; + --text-xs--line-height: 1rem; + --text-sm: 0.875rem; + --text-sm--line-height: 1.5rem; + --text-base: 1rem; + --text-base--line-height: 2rem; + --text-lg: 1.125rem; + --text-lg--line-height: 1.75rem; + --text-xl: 1.25rem; + --text-xl--line-height: 2rem; + --text-2xl: 1.5rem; + --text-2xl--line-height: 2.5rem; + --text-3xl: 2rem; + --text-3xl--line-height: 2.5rem; + --text-4xl: 2.5rem; + --text-4xl--line-height: 3rem; + --text-5xl: 3rem; + --text-5xl--line-height: 3.5rem; + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --text-7xl: 4.5rem; + --text-7xl--line-height: 1; + --text-8xl: 6rem; + --text-8xl--line-height: 1; + --text-9xl: 8rem; + --text-9xl--line-height: 1; + + --font-sans: "Inter"; + --font-display: "Lexend"; + --font-display--font-feature-settings: "ss01"; + + --container-8xl: 88rem; +} + +@layer base { + [inert] ::-webkit-scrollbar { + display: none; + } +} \ No newline at end of file diff --git a/app/package.json b/app/package.json index 999a862..200b979 100755 --- a/app/package.json +++ b/app/package.json @@ -12,10 +12,12 @@ "@fastify/static": "^8.1.1", "@mdx-js/rollup": "^3.1.0", "@sindresorhus/slugify": "^2.2.1", + "@tailwindcss/typography": "^0.5.16", "@universal-middleware/core": "^0.4.7", "@universal-middleware/fastify": "^0.5.16", "clsx": "^2.1.1", "fastify": "^5.3.0", + "prismjs": "^1.30.0", "solid-heroicons": "^3.2.4", "solid-highlight": "^0.1.26", "solid-js": "^1.9.5", @@ -25,13 +27,15 @@ "telefunc": "^0.2.3", "terracotta": "^1.0.6", "vike": "^0.4.228", - "vike-solid": "^0.7.9" + "vike-solid": "^0.7.9", + "vite-plugin-prismjs": "^0.0.11" }, "devDependencies": { "@biomejs/biome": "1.9.4", "@eslint/js": "^9.24.0", "@tailwindcss/vite": "^4.1.3", "@types/node": "^18.19.86", + "@types/prismjs": "^1.26.5", "cross-env": "^7.0.3", "eslint": "^9.24.0", "eslint-config-prettier": "^10.1.2", diff --git a/app/pages/+Head.tsx b/app/pages/+Head.tsx index c6de5bb..e980318 100755 --- a/app/pages/+Head.tsx +++ b/app/pages/+Head.tsx @@ -3,19 +3,30 @@ // https://vike.dev/Head export default function HeadDefault() { - return ( - <> -