mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-24 15:26:27 +00:00
Add code highlighting (#2195)
* Add highlighting * Adds it to mdNoImages as well * Revert "Adds it to mdNoImages as well" This reverts commit2f8e3bb0cc
. * Revert "Add highlighting" This reverts commit80bcddd4df
. * Prevent yarn.lock from massively updating * Add code themes locally --------- Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
parent
ca456fdd1b
commit
2b5068187c
|
@ -1,5 +1,6 @@
|
||||||
src/shared/translations
|
src/shared/translations
|
||||||
lemmy-translations
|
lemmy-translations
|
||||||
src/assets/css/themes/*.css
|
src/assets/css/themes/*.css
|
||||||
|
src/assets/css/code-themes/*.css
|
||||||
stats.json
|
stats.json
|
||||||
dist
|
dist
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
"markdown-it-container": "^3.0.0",
|
"markdown-it-container": "^3.0.0",
|
||||||
"markdown-it-emoji": "^2.0.2",
|
"markdown-it-emoji": "^2.0.2",
|
||||||
"markdown-it-footnote": "^3.0.3",
|
"markdown-it-footnote": "^3.0.3",
|
||||||
|
"markdown-it-highlightjs": "^4.0.1",
|
||||||
"markdown-it-html5-embed": "^1.0.0",
|
"markdown-it-html5-embed": "^1.0.0",
|
||||||
"markdown-it-ruby": "^0.1.1",
|
"markdown-it-ruby": "^0.1.1",
|
||||||
"markdown-it-sub": "^1.0.0",
|
"markdown-it-sub": "^1.0.0",
|
||||||
|
|
1
src/assets/css/code-themes/atom-one-dark.css
Normal file
1
src/assets/css/code-themes/atom-one-dark.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
|
1
src/assets/css/code-themes/atom-one-light.css
Normal file
1
src/assets/css/code-themes/atom-one-light.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#383a42;background:#fafafa}.hljs-comment,.hljs-quote{color:#a0a1a7;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e45649}.hljs-literal{color:#0184bb}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#50a14f}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#4078f2}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#c18401}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
|
35
src/server/handlers/code-theme-handler.ts
Normal file
35
src/server/handlers/code-theme-handler.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import type { Request, Response } from "express";
|
||||||
|
import { existsSync } from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const extraThemesFolder =
|
||||||
|
process.env["LEMMY_UI_EXTRA_THEMES_FOLDER"] || "./extra_themes";
|
||||||
|
|
||||||
|
export default async (req: Request, res: Response) => {
|
||||||
|
res.contentType("text/css");
|
||||||
|
|
||||||
|
const theme = req.params.name;
|
||||||
|
|
||||||
|
if (!theme.endsWith(".css")) {
|
||||||
|
return res.status(400).send("Theme must be a css file");
|
||||||
|
}
|
||||||
|
|
||||||
|
const customTheme = path.resolve(extraThemesFolder, theme);
|
||||||
|
|
||||||
|
if (existsSync(customTheme)) {
|
||||||
|
return res.sendFile(customTheme);
|
||||||
|
} else {
|
||||||
|
const internalTheme = path.resolve(
|
||||||
|
`./dist/assets/css/code-themes/${theme}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// If the theme doesn't exist, just send atom-one-light
|
||||||
|
if (existsSync(internalTheme)) {
|
||||||
|
return res.sendFile(internalTheme);
|
||||||
|
} else {
|
||||||
|
return res.sendFile(
|
||||||
|
path.resolve("./dist/assets/css/code-themes/atom-one-light.css"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -11,6 +11,7 @@ import ServiceWorkerHandler from "./handlers/service-worker-handler";
|
||||||
import ThemeHandler from "./handlers/theme-handler";
|
import ThemeHandler from "./handlers/theme-handler";
|
||||||
import ThemesListHandler from "./handlers/themes-list-handler";
|
import ThemesListHandler from "./handlers/themes-list-handler";
|
||||||
import { setCacheControl, setDefaultCsp } from "./middleware";
|
import { setCacheControl, setDefaultCsp } from "./middleware";
|
||||||
|
import CodeThemeHandler from "./handlers/code-theme-handler";
|
||||||
|
|
||||||
const server = express();
|
const server = express();
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ server.get("/robots.txt", RobotsHandler);
|
||||||
server.get("/service-worker.js", ServiceWorkerHandler);
|
server.get("/service-worker.js", ServiceWorkerHandler);
|
||||||
server.get("/manifest.webmanifest", ManifestHandler);
|
server.get("/manifest.webmanifest", ManifestHandler);
|
||||||
server.get("/css/themes/:name", ThemeHandler);
|
server.get("/css/themes/:name", ThemeHandler);
|
||||||
|
server.get("/css/code-themes/:name", CodeThemeHandler);
|
||||||
server.get("/css/themelist", ThemesListHandler);
|
server.get("/css/themelist", ThemesListHandler);
|
||||||
server.get("/*", CatchAllHandler);
|
server.get("/*", CatchAllHandler);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { Navbar } from "./navbar";
|
||||||
import "./styles.scss";
|
import "./styles.scss";
|
||||||
import { Theme } from "./theme";
|
import { Theme } from "./theme";
|
||||||
import AnonymousGuard from "../common/anonymous-guard";
|
import AnonymousGuard from "../common/anonymous-guard";
|
||||||
|
import { CodeTheme } from "./code-theme";
|
||||||
|
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
user?: MyUserInfo;
|
user?: MyUserInfo;
|
||||||
|
@ -55,7 +56,10 @@ export class App extends Component<AppProps, any> {
|
||||||
{I18NextService.i18n.t("jump_to_content", "Jump to content")}
|
{I18NextService.i18n.t("jump_to_content", "Jump to content")}
|
||||||
</button>
|
</button>
|
||||||
{siteView && (
|
{siteView && (
|
||||||
<Theme defaultTheme={siteView.local_site.default_theme} />
|
<>
|
||||||
|
<Theme defaultTheme={siteView.local_site.default_theme} />
|
||||||
|
<CodeTheme />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<Navbar siteRes={siteRes} />
|
<Navbar siteRes={siteRes} />
|
||||||
<div className="mt-4 p-0 fl-1">
|
<div className="mt-4 p-0 fl-1">
|
||||||
|
|
22
src/shared/components/app/code-theme.tsx
Normal file
22
src/shared/components/app/code-theme.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { Component } from "inferno";
|
||||||
|
|
||||||
|
export class CodeTheme extends Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
type="text/css"
|
||||||
|
href={`/css/code-themes/atom-one-light.css`}
|
||||||
|
media="(prefers-color-scheme: light)"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
type="text/css"
|
||||||
|
href={`/css/code-themes/atom-one-dark.css`}
|
||||||
|
media="(prefers-color-scheme: no-preference), (prefers-color-scheme: dark)"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import markdown_it_html5_embed from "markdown-it-html5-embed";
|
||||||
import markdown_it_ruby from "markdown-it-ruby";
|
import markdown_it_ruby from "markdown-it-ruby";
|
||||||
import markdown_it_sub from "markdown-it-sub";
|
import markdown_it_sub from "markdown-it-sub";
|
||||||
import markdown_it_sup from "markdown-it-sup";
|
import markdown_it_sup from "markdown-it-sup";
|
||||||
|
import markdown_it_highlightjs from "markdown-it-highlightjs";
|
||||||
import Renderer from "markdown-it/lib/renderer";
|
import Renderer from "markdown-it/lib/renderer";
|
||||||
import Token from "markdown-it/lib/token";
|
import Token from "markdown-it/lib/token";
|
||||||
import { instanceLinkRegex, relTags } from "./config";
|
import { instanceLinkRegex, relTags } from "./config";
|
||||||
|
@ -170,6 +171,7 @@ export function setupMarkdown() {
|
||||||
.use(markdown_it_footnote)
|
.use(markdown_it_footnote)
|
||||||
.use(markdown_it_html5_embed, html5EmbedConfig)
|
.use(markdown_it_html5_embed, html5EmbedConfig)
|
||||||
.use(markdown_it_container, "spoiler", spoilerConfig)
|
.use(markdown_it_container, "spoiler", spoilerConfig)
|
||||||
|
.use(markdown_it_highlightjs, { inline: true })
|
||||||
.use(markdown_it_ruby)
|
.use(markdown_it_ruby)
|
||||||
.use(localInstanceLinkParser)
|
.use(localInstanceLinkParser)
|
||||||
.use(markdown_it_bidi);
|
.use(markdown_it_bidi);
|
||||||
|
@ -183,6 +185,7 @@ export function setupMarkdown() {
|
||||||
.use(markdown_it_footnote)
|
.use(markdown_it_footnote)
|
||||||
.use(markdown_it_html5_embed, html5EmbedConfig)
|
.use(markdown_it_html5_embed, html5EmbedConfig)
|
||||||
.use(markdown_it_container, "spoiler", spoilerConfig)
|
.use(markdown_it_container, "spoiler", spoilerConfig)
|
||||||
|
.use(markdown_it_highlightjs, { inline: true })
|
||||||
.use(localInstanceLinkParser)
|
.use(localInstanceLinkParser)
|
||||||
.use(markdown_it_bidi)
|
.use(markdown_it_bidi)
|
||||||
// .use(markdown_it_emoji, {
|
// .use(markdown_it_emoji, {
|
||||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -5020,6 +5020,11 @@ has@^1.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.1"
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
|
highlight.js@^11.5.1:
|
||||||
|
version "11.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.9.0.tgz#04ab9ee43b52a41a047432c8103e2158a1b8b5b0"
|
||||||
|
integrity sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==
|
||||||
|
|
||||||
history@^5.3.0:
|
history@^5.3.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
|
resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
|
||||||
|
@ -6422,6 +6427,13 @@ markdown-it-footnote@^3.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz#e0e4c0d67390a4c5f0c75f73be605c7c190ca4d8"
|
resolved "https://registry.yarnpkg.com/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz#e0e4c0d67390a4c5f0c75f73be605c7c190ca4d8"
|
||||||
integrity sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==
|
integrity sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==
|
||||||
|
|
||||||
|
markdown-it-highlightjs@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/markdown-it-highlightjs/-/markdown-it-highlightjs-4.0.1.tgz#6b8eb6a3b971ed592db1ff160cfa5ce9f2e44232"
|
||||||
|
integrity sha512-EPXwFEN6P5nqR3G4KjT20r20xbGYKMMA/360hhSYFmeoGXTE6hsLtJAiB/8ID8slVH4CWHHEL7GX0YenyIstVQ==
|
||||||
|
dependencies:
|
||||||
|
highlight.js "^11.5.1"
|
||||||
|
|
||||||
markdown-it-html5-embed@^1.0.0:
|
markdown-it-html5-embed@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/markdown-it-html5-embed/-/markdown-it-html5-embed-1.0.0.tgz#f36bedca1eb12ce4df2d53b5ec72f62ba5e094b3"
|
resolved "https://registry.yarnpkg.com/markdown-it-html5-embed/-/markdown-it-html5-embed-1.0.0.tgz#f36bedca1eb12ce4df2d53b5ec72f62ba5e094b3"
|
||||||
|
|
Loading…
Reference in a new issue