Adding markdown spoiler support.

- Fixes #350
This commit is contained in:
Dessalines 2024-08-07 09:52:47 -04:00
parent a37d216008
commit f8ee91fab3
3 changed files with 122 additions and 22 deletions

View file

@ -46,7 +46,14 @@
"inferno-i18next": "github:nimbusec-oss/inferno-i18next#semver:^7.4.2", "inferno-i18next": "github:nimbusec-oss/inferno-i18next#semver:^7.4.2",
"inferno-router": "^8.2.2", "inferno-router": "^8.2.2",
"inferno-server": "^8.2.2", "inferno-server": "^8.2.2",
"markdown-it": "^14.0.0", "markdown-it": "^14.1.0",
"markdown-it-bidi": "^0.1.0",
"markdown-it-container": "^4.0.0",
"markdown-it-emoji": "^3.0.0",
"markdown-it-footnote": "^4.0.0",
"markdown-it-ruby": "^0.1.1",
"markdown-it-sub": "^2.0.0",
"markdown-it-sup": "^2.0.0",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"run-node-webpack-plugin": "^1.3.0", "run-node-webpack-plugin": "^1.3.0",

View file

@ -55,7 +55,7 @@ importers:
version: 3.0.6 version: 3.0.6
daisyui: daisyui:
specifier: ^4.6.0 specifier: ^4.6.0
version: 4.6.0(postcss@8.4.38) version: 4.6.0(postcss@8.4.40)
express: express:
specifier: ~4.18.2 specifier: ~4.18.2
version: 4.18.2 version: 4.18.2
@ -87,8 +87,29 @@ importers:
specifier: ^8.2.2 specifier: ^8.2.2
version: 8.2.3 version: 8.2.3
markdown-it: markdown-it:
specifier: ^14.0.0 specifier: ^14.1.0
version: 14.0.0 version: 14.1.0
markdown-it-bidi:
specifier: ^0.1.0
version: 0.1.0
markdown-it-container:
specifier: ^4.0.0
version: 4.0.0
markdown-it-emoji:
specifier: ^3.0.0
version: 3.0.0
markdown-it-footnote:
specifier: ^4.0.0
version: 4.0.0
markdown-it-ruby:
specifier: ^0.1.1
version: 0.1.1
markdown-it-sub:
specifier: ^2.0.0
version: 2.0.0
markdown-it-sup:
specifier: ^2.0.0
version: 2.0.0
node-fetch: node-fetch:
specifier: ^3.3.2 specifier: ^3.3.2
version: 3.3.2 version: 3.3.2
@ -2357,8 +2378,29 @@ packages:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'} engines: {node: '>=10'}
markdown-it@14.0.0: markdown-it-bidi@0.1.0:
resolution: {integrity: sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==} resolution: {integrity: sha512-4GloQnF+PiILh6wkLAIeSxCLo9qUW7LcKj/08GyCpvo0LLC6YEhrZBvM9RkMkieGG7i4uIRE/F5jmU14DgR8Wg==}
markdown-it-container@4.0.0:
resolution: {integrity: sha512-HaNccxUH0l7BNGYbFbjmGpf5aLHAMTinqRZQAEQbMr2cdD3z91Q6kIo1oUn1CQndkT03jat6ckrdRYuwwqLlQw==}
markdown-it-emoji@3.0.0:
resolution: {integrity: sha512-+rUD93bXHubA4arpEZO3q80so0qgoFJEKRkRbjKX8RTdca89v2kfyF+xR3i2sQTwql9tpPZPOQN5B+PunspXRg==}
markdown-it-footnote@4.0.0:
resolution: {integrity: sha512-WYJ7urf+khJYl3DqofQpYfEYkZKbmXmwxQV8c8mO/hGIhgZ1wOe7R4HLFNwqx7TjILbnC98fuyeSsin19JdFcQ==}
markdown-it-ruby@0.1.1:
resolution: {integrity: sha512-ct8t/Drt7scv20VdaQtOhpBOC2SDICaW8E/WQS8kY2eUdu0eoDwW8ugXcCy8Vku4Y5CuA5qrewlHpwaFsJxbpQ==}
markdown-it-sub@2.0.0:
resolution: {integrity: sha512-iCBKgwCkfQBRg2vApy9vx1C1Tu6D8XYo8NvevI3OlwzBRmiMtsJ2sXupBgEA7PPxiDwNni3qIUkhZ6j5wofDUA==}
markdown-it-sup@2.0.0:
resolution: {integrity: sha512-5VgmdKlkBd8sgXuoDoxMpiU+BiEt3I49GItBzzw7Mxq9CxvnhE/k09HFli09zgfFDRixDQDfDxi0mgBCXtaTvA==}
markdown-it@14.1.0:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true hasBin: true
mdurl@2.0.0: mdurl@2.0.0:
@ -3369,8 +3411,8 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
uc.micro@2.0.0: uc.micro@2.1.0:
resolution: {integrity: sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==} resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
undici-types@5.26.5: undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
@ -5125,12 +5167,12 @@ snapshots:
culori@3.3.0: {} culori@3.3.0: {}
daisyui@4.6.0(postcss@8.4.38): daisyui@4.6.0(postcss@8.4.40):
dependencies: dependencies:
css-selector-tokenizer: 0.8.0 css-selector-tokenizer: 0.8.0
culori: 3.3.0 culori: 3.3.0
picocolors: 1.0.0 picocolors: 1.0.0
postcss-js: 4.0.1(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.40)
transitivePeerDependencies: transitivePeerDependencies:
- postcss - postcss
@ -5952,7 +5994,7 @@ snapshots:
linkify-it@5.0.0: linkify-it@5.0.0:
dependencies: dependencies:
uc.micro: 2.0.0 uc.micro: 2.1.0
lint-staged@15.2.7: lint-staged@15.2.7:
dependencies: dependencies:
@ -6020,14 +6062,28 @@ snapshots:
dependencies: dependencies:
yallist: 4.0.0 yallist: 4.0.0
markdown-it@14.0.0: markdown-it-bidi@0.1.0: {}
markdown-it-container@4.0.0: {}
markdown-it-emoji@3.0.0: {}
markdown-it-footnote@4.0.0: {}
markdown-it-ruby@0.1.1: {}
markdown-it-sub@2.0.0: {}
markdown-it-sup@2.0.0: {}
markdown-it@14.1.0:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
entities: 4.5.0 entities: 4.5.0
linkify-it: 5.0.0 linkify-it: 5.0.0
mdurl: 2.0.0 mdurl: 2.0.0
punycode.js: 2.3.1 punycode.js: 2.3.1
uc.micro: 2.0.0 uc.micro: 2.1.0
mdurl@2.0.0: {} mdurl@2.0.0: {}
@ -6288,11 +6344,6 @@ snapshots:
read-cache: 1.0.0 read-cache: 1.0.0
resolve: 1.22.8 resolve: 1.22.8
postcss-js@4.0.1(postcss@8.4.38):
dependencies:
camelcase-css: 2.0.1
postcss: 8.4.38
postcss-js@4.0.1(postcss@8.4.40): postcss-js@4.0.1(postcss@8.4.40):
dependencies: dependencies:
camelcase-css: 2.0.1 camelcase-css: 2.0.1
@ -6868,7 +6919,7 @@ snapshots:
typescript@5.4.5: {} typescript@5.4.5: {}
uc.micro@2.0.0: {} uc.micro@2.1.0: {}
undici-types@5.26.5: {} undici-types@5.26.5: {}

View file

@ -1,4 +1,10 @@
import markdown_it from "markdown-it"; import { default as MarkdownIt } from "markdown-it";
import markdown_it_container from "markdown-it-container";
import markdown_it_bidi from "markdown-it-bidi";
import markdown_it_footnote from "markdown-it-footnote";
import markdown_it_ruby from "markdown-it-ruby";
import markdown_it_sub from "markdown-it-sub";
import markdown_it_sup from "markdown-it-sup";
let SHORTNUM_SI_FORMAT = new Intl.NumberFormat("en-US", { let SHORTNUM_SI_FORMAT = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 1, maximumFractionDigits: 1,
@ -15,11 +21,47 @@ export function isBrowser() {
return typeof window !== "undefined"; return typeof window !== "undefined";
} }
export const md = new markdown_it({ const spoilerConfig = {
validate: (params: string) => {
return params.trim().match(/^spoiler\s+(.*)$/);
},
render: (tokens: any, idx: any) => {
const m = tokens[idx].info.trim().match(/^spoiler\s+(.*)$/);
if (tokens[idx].nesting === 1) {
// opening tag
const summary = mdToHtmlInline(md.utils.escapeHtml(m[1])).__html;
return `<details><summary> ${summary} </summary>\n`;
} else {
// closing tag
return "</details>\n";
}
},
};
// Zero disables all rules.
// Only explicitly allow a limited set of rules safe for use in post titles.
export const mdLimited: MarkdownIt = new MarkdownIt("zero").enable([
"emphasis",
"backticks",
"strikethrough",
]);
export function mdToHtmlInline(text: string) {
return { __html: mdLimited.renderInline(text) };
}
export const md = new MarkdownIt({
html: true, html: true,
linkify: true, linkify: true,
typographer: true, typographer: true,
}); })
.use(markdown_it_sub)
.use(markdown_it_sup)
.use(markdown_it_footnote)
.use(markdown_it_container, "spoiler", spoilerConfig)
.use(markdown_it_ruby)
.use(markdown_it_bidi);
export function mdToHtml(text: string) { export function mdToHtml(text: string) {
return { __html: md.render(text) }; return { __html: md.render(text) };