diff --git a/package.json b/package.json index ba4cfdf..d98a3d5 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,14 @@ "inferno-i18next": "github:nimbusec-oss/inferno-i18next#semver:^7.4.2", "inferno-router": "^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", "qrcode": "^1.5.3", "run-node-webpack-plugin": "^1.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6cb73b8..ee17784 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,7 +55,7 @@ importers: version: 3.0.6 daisyui: specifier: ^4.6.0 - version: 4.6.0(postcss@8.4.38) + version: 4.6.0(postcss@8.4.40) express: specifier: ~4.18.2 version: 4.18.2 @@ -87,8 +87,29 @@ importers: specifier: ^8.2.2 version: 8.2.3 markdown-it: - specifier: ^14.0.0 - version: 14.0.0 + specifier: ^14.1.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: specifier: ^3.3.2 version: 3.3.2 @@ -2357,8 +2378,29 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - markdown-it@14.0.0: - resolution: {integrity: sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==} + markdown-it-bidi@0.1.0: + 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 mdurl@2.0.0: @@ -3369,8 +3411,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - uc.micro@2.0.0: - resolution: {integrity: sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==} + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -5125,12 +5167,12 @@ snapshots: culori@3.3.0: {} - daisyui@4.6.0(postcss@8.4.38): + daisyui@4.6.0(postcss@8.4.40): dependencies: css-selector-tokenizer: 0.8.0 culori: 3.3.0 picocolors: 1.0.0 - postcss-js: 4.0.1(postcss@8.4.38) + postcss-js: 4.0.1(postcss@8.4.40) transitivePeerDependencies: - postcss @@ -5952,7 +5994,7 @@ snapshots: linkify-it@5.0.0: dependencies: - uc.micro: 2.0.0 + uc.micro: 2.1.0 lint-staged@15.2.7: dependencies: @@ -6020,14 +6062,28 @@ snapshots: dependencies: 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: argparse: 2.0.1 entities: 4.5.0 linkify-it: 5.0.0 mdurl: 2.0.0 punycode.js: 2.3.1 - uc.micro: 2.0.0 + uc.micro: 2.1.0 mdurl@2.0.0: {} @@ -6288,11 +6344,6 @@ snapshots: read-cache: 1.0.0 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): dependencies: camelcase-css: 2.0.1 @@ -6868,7 +6919,7 @@ snapshots: typescript@5.4.5: {} - uc.micro@2.0.0: {} + uc.micro@2.1.0: {} undici-types@5.26.5: {} diff --git a/src/shared/utils.ts b/src/shared/utils.ts index 031b3d1..b109bea 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -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", { maximumFractionDigits: 1, @@ -15,11 +21,47 @@ export function isBrowser() { 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 `
${summary} \n`; + } else { + // closing tag + return "
\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, linkify: 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) { return { __html: md.render(text) };