From ca6f8ed09c3b2fd840d93b118fcf35883a983a6c Mon Sep 17 00:00:00 2001 From: qwqcode Date: Thu, 30 May 2024 19:39:03 +0800 Subject: [PATCH] fix(plugin_katex): fix event issue causing katex integration failure (#897) --- docs/docs/.vitepress/theme/Artalk.vue | 3 + docs/docs/package.json | 1 + pnpm-lock.yaml | 36 +++++++++++ ui/artalk-sidebar/src/pages/settings.vue | 2 + ui/artalk/src/plugins/markdown.ts | 6 +- ui/plugin-auth/artalk-plugin-shim.d.ts | 10 +-- ui/plugin-auth/main.tsx | 10 +-- ui/plugin-auth/package.json | 1 + ui/plugin-katex/README.md | 2 +- ui/plugin-katex/index.html | 28 --------- ui/plugin-katex/main.ts | 79 ----------------------- ui/plugin-katex/package.json | 23 ++++++- ui/plugin-katex/src/main.ts | 80 ++++++++++++++++++++++++ ui/plugin-katex/tsconfig.json | 3 +- ui/plugin-katex/vite.config.ts | 23 ++----- 15 files changed, 159 insertions(+), 148 deletions(-) delete mode 100644 ui/plugin-katex/index.html delete mode 100644 ui/plugin-katex/main.ts create mode 100644 ui/plugin-katex/src/main.ts diff --git a/docs/docs/.vitepress/theme/Artalk.vue b/docs/docs/.vitepress/theme/Artalk.vue index a0ed84a23..71232e521 100644 --- a/docs/docs/.vitepress/theme/Artalk.vue +++ b/docs/docs/.vitepress/theme/Artalk.vue @@ -6,6 +6,7 @@ import { watch, nextTick, ref, onMounted, onUnmounted } from 'vue' import { useData, useRouter } from 'vitepress' import Artalk from 'artalk' +import { ArtalkKatexPlugin } from '@artalk/plugin-katex' import 'artalk/dist/Artalk.css' const el = ref(null) @@ -36,6 +37,8 @@ onUnmounted(() => { }) function initArtalk(conf: any) { + Artalk.use(ArtalkKatexPlugin) + artalk = Artalk.init({ el: el.value, emoticons: '/assets/emoticons/default.json', diff --git a/docs/docs/package.json b/docs/docs/package.json index 7ed1b6c0a..f15818cbe 100644 --- a/docs/docs/package.json +++ b/docs/docs/package.json @@ -21,6 +21,7 @@ "vitepress": "1.1.4" }, "dependencies": { + "@artalk/plugin-katex": "^0.1.7", "vue": "^3.4.26" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 777aef2af..824daa58e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ importers: docs/docs: dependencies: + '@artalk/plugin-katex': + specifier: ^0.1.7 + version: 0.1.7 vue: specifier: ^3.4.26 version: 3.4.26(typescript@5.4.5) @@ -311,6 +314,9 @@ importers: specifier: ^1.8.17 version: 1.8.17 devDependencies: + '@artalk/plugin-kit': + specifier: workspace:^ + version: link:../plugin-kit vite-plugin-css-injected-by-js: specifier: ^3.5.1 version: 3.5.1(vite@5.2.11(@types/node@20.12.8)(sass@1.76.0)(terser@5.31.0)) @@ -327,6 +333,9 @@ importers: specifier: ^0.16.10 version: 0.16.10 devDependencies: + '@artalk/plugin-kit': + specifier: workspace:^ + version: link:../plugin-kit '@types/katex': specifier: 0.16.7 version: 0.16.7 @@ -448,6 +457,12 @@ packages: '@antfu/utils@0.7.7': resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==} + '@artalk/plugin-katex@0.1.7': + resolution: {integrity: sha512-2TaEmSx4EPOAcffeRnbME2P4fmzbKd6nbO4sL6Ol/Xweg1hDptmWS4ecpSYrYs0X0NyUIyzptTsnhmJG3TSWNQ==} + + '@artalk/plugin-kit@1.0.0': + resolution: {integrity: sha512-MSOgI9k2yfvKkvf8mrUWOy17FLRigMNtsZlRtdwTwAsFizm7dk9TaOc9b5qLGyCkDMpREtCXvnbDxCyp7716rA==} + '@babel/code-frame@7.24.2': resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} engines: {node: '>=6.9.0'} @@ -1841,6 +1856,9 @@ packages: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} + artalk@2.8.6: + resolution: {integrity: sha512-Wt6x9F6A9l7Bw6y8tZayheHkJJ2tF0T3yZVxtqHTpDgZOKlOI91UzBvZ2bSjScayy7JH9ZSAkTC/qVDODeUhbA==} + assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} @@ -4812,6 +4830,17 @@ snapshots: '@antfu/utils@0.7.7': {} + '@artalk/plugin-katex@0.1.7': + dependencies: + '@artalk/plugin-kit': 1.0.0 + artalk: 2.8.6 + katex: 0.16.10 + + '@artalk/plugin-kit@1.0.0': + dependencies: + artalk: 2.8.6 + picocolors: 1.0.1 + '@babel/code-frame@7.24.2': dependencies: '@babel/highlight': 7.24.2 @@ -6370,6 +6399,13 @@ snapshots: is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 + artalk@2.8.6: + dependencies: + abortcontroller-polyfill: 1.7.5 + hanabi: 0.4.0 + insane: 2.6.2 + marked: 12.0.2 + assertion-error@1.1.0: {} assignment@2.0.0: {} diff --git a/ui/artalk-sidebar/src/pages/settings.vue b/ui/artalk-sidebar/src/pages/settings.vue index ea1034be4..f5a3e83d3 100644 --- a/ui/artalk-sidebar/src/pages/settings.vue +++ b/ui/artalk-sidebar/src/pages/settings.vue @@ -162,6 +162,8 @@ function save() { border-bottom: 1px solid var(--at-color-border); outline: none; background: transparent; + -webkit-appearance: none; + border-radius: 0; &:focus { border-bottom-color: var(--at-color-main); diff --git a/ui/artalk/src/plugins/markdown.ts b/ui/artalk/src/plugins/markdown.ts index d864ef417..ea10f5a4b 100644 --- a/ui/artalk/src/plugins/markdown.ts +++ b/ui/artalk/src/plugins/markdown.ts @@ -2,12 +2,14 @@ import type { ArtalkPlugin } from '@/types' import * as marked from '@/lib/marked' export const Markdown: ArtalkPlugin = (ctx) => { - ctx.watchConf(['markedReplacers', 'imgLazyLoad', 'markedOptions'], (conf) => { + ctx.watchConf(['imgLazyLoad', 'markedOptions'], (conf) => { marked.initMarked({ markedOptions: ctx.getConf().markedOptions, imgLazyLoad: ctx.getConf().imgLazyLoad, }) + }) - if (conf.markedReplacers) marked.setReplacers(conf.markedReplacers) + ctx.watchConf(['markedReplacers'], (conf) => { + conf.markedReplacers && marked.setReplacers(conf.markedReplacers) }) } diff --git a/ui/plugin-auth/artalk-plugin-shim.d.ts b/ui/plugin-auth/artalk-plugin-shim.d.ts index 696c7df46..51a02b019 100644 --- a/ui/plugin-auth/artalk-plugin-shim.d.ts +++ b/ui/plugin-auth/artalk-plugin-shim.d.ts @@ -1,9 +1 @@ -import type { ArtalkPlugin } from 'artalk' - -export {} - -declare global { - interface Window { - ArtalkPlugins?: { [name: string]: ArtalkPlugin } - } -} +/// diff --git a/ui/plugin-auth/main.tsx b/ui/plugin-auth/main.tsx index 5c346712d..067f04968 100644 --- a/ui/plugin-auth/main.tsx +++ b/ui/plugin-auth/main.tsx @@ -1,6 +1,6 @@ /* @refresh reload */ import './style.scss' -import Artalk, { ArtalkPlugin } from 'artalk' +import { ArtalkPlugin } from 'artalk' import { DialogMain } from './DialogMain' import { createLayer } from './lib/layer' import { RenderEditorUser } from './EditorUser' @@ -56,13 +56,9 @@ export const ArtalkAuthPlugin: ArtalkPlugin = (ctx) => { }) } -if ((window as any)?.Artalk) { - ;(window as any).Artalk.use(ArtalkAuthPlugin) -} else if (Artalk) { - Artalk.use(ArtalkAuthPlugin) -} - +// Mount plugin to browser window global if (window) { !window.ArtalkPlugins && (window.ArtalkPlugins = {}) window.ArtalkPlugins.Auth = ArtalkAuthPlugin + window.Artalk?.use(ArtalkAuthPlugin) } diff --git a/ui/plugin-auth/package.json b/ui/plugin-auth/package.json index 0d17334a0..49f052da8 100644 --- a/ui/plugin-auth/package.json +++ b/ui/plugin-auth/package.json @@ -34,6 +34,7 @@ "solid-js": "^1.8.17" }, "devDependencies": { + "@artalk/plugin-kit": "workspace:^", "vite-plugin-css-injected-by-js": "^3.5.1", "vite-plugin-solid": "^2.10.2" } diff --git a/ui/plugin-katex/README.md b/ui/plugin-katex/README.md index 00fbf1208..f97d8adaa 100644 --- a/ui/plugin-katex/README.md +++ b/ui/plugin-katex/README.md @@ -1,3 +1,3 @@ # @artalk/plugin-katex -食用方法参考:[官方文档](https://artalk.js.org/guide/frontend/latex.html) +使用方法参考:[官方文档](https://artalk.js.org/guide/frontend/latex.html) diff --git a/ui/plugin-katex/index.html b/ui/plugin-katex/index.html deleted file mode 100644 index 6b4f63a0a..000000000 --- a/ui/plugin-katex/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - plugin-katex - - - - -
- - - - diff --git a/ui/plugin-katex/main.ts b/ui/plugin-katex/main.ts deleted file mode 100644 index 723408089..000000000 --- a/ui/plugin-katex/main.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable guard-for-in */ -/* eslint-disable no-restricted-syntax */ -import Artalk from 'artalk' -import katex from 'katex' - -// @link https://github.com/markedjs/marked/issues/1538#issuecomment-575838181 -Artalk.use((ctx) => { - const markedInstance = ctx.getMarked() - if (!markedInstance) { - console.error('[artalk-plugin-katex] no marked instance found') - return - } - - let i = 0 - const nextID = () => `__atk_katex_id_${i++}__` - const mathExpressions: { - [key: string]: { type: 'block' | 'inline'; expression: string } - } = {} - - function replaceMathWithIds(text: string) { - // Allowing newlines inside of `$$...$$` - text = text.replace(/\$\$([\s\S]+?)\$\$/g, (_match, expression) => { - const id = nextID() - mathExpressions[id] = { type: 'block', expression } - return id - }) - - // Not allowing newlines or space inside of `$...$` - text = text.replace(/\$([^\n]+?)\$/g, (_match, expression) => { - const id = nextID() - mathExpressions[id] = { type: 'inline', expression } - return id - }) - - return text - } - - // Marked render - const renderer = new markedInstance.Renderer() as any - - const orgListitem = renderer.listitem - const orgParagraph = renderer.paragraph - const orgTablecell = renderer.tablecell - const orgCodespan = renderer.codespan - const orgText = renderer.text - - renderer.listitem = (text: string, task: boolean, checked: boolean) => - orgListitem(replaceMathWithIds(text), task, checked) - renderer.paragraph = (text: string) => orgParagraph(replaceMathWithIds(text)) - renderer.tablecell = (content: string, flags: any) => - orgTablecell(replaceMathWithIds(content), flags) - renderer.codespan = (code: string) => orgCodespan(replaceMathWithIds(code)) - renderer.text = (text: string) => orgText(replaceMathWithIds(text)) // Inline level, maybe unneeded - - ctx.updateConf({ - markedReplacers: [ - (text) => { - text = text.replace(/(__atk_katex_id_\d+__)/g, (_match, capture) => { - const v = mathExpressions[capture] - const type = v.type - let expression = v.expression - - // replace
tag to \n - expression = expression.replace(//gm, '\n') - - return katex.renderToString(expression, { - displayMode: type === 'block', - }) - }) - - return text - }, - ], - }) - - markedInstance.use({ - renderer, - }) -}) diff --git a/ui/plugin-katex/package.json b/ui/plugin-katex/package.json index eebd22174..862c9ba76 100644 --- a/ui/plugin-katex/package.json +++ b/ui/plugin-katex/package.json @@ -1,10 +1,16 @@ { "name": "@artalk/plugin-katex", - "version": "0.1.6", + "version": "0.1.7", + "minAppVersion": "2.8.6", "license": "MIT", "description": "The katex plugin for artalk", + "type": "module", "main": "./dist/artalk-plugin-katex.js", - "module": "./dist/artalk-plugin-katex.es.js", + "module": "./dist/artalk-plugin-katex.mjs", + "types": "./dist/artalk-plugin-katex.d.ts", + "files": [ + "dist" + ], "scripts": { "dev": "vite", "build": "vite build", @@ -17,6 +23,19 @@ "katex": "^0.16.10" }, "devDependencies": { + "@artalk/plugin-kit": "workspace:^", "@types/katex": "0.16.7" + }, + "exports": { + ".": { + "require": { + "types": "./dist/artalk-plugin-katex.d.cts", + "default": "./dist/artalk-plugin-katex.cjs" + }, + "default": { + "types": "./dist/artalk-plugin-katex.d.ts", + "default": "./dist/artalk-plugin-katex.mjs" + } + } } } diff --git a/ui/plugin-katex/src/main.ts b/ui/plugin-katex/src/main.ts new file mode 100644 index 000000000..c18b6e1c6 --- /dev/null +++ b/ui/plugin-katex/src/main.ts @@ -0,0 +1,80 @@ +import { ArtalkPlugin } from 'artalk' +import katex from 'katex' +import 'katex/dist/katex.min.css' + +export const ArtalkKatexPlugin: ArtalkPlugin = (ctx) => { + ctx.on('mounted', () => { + // @see https://github.com/markedjs/marked/issues/1538#issuecomment-575838181 + const markedInstance = ctx.getMarked() // must be called after `mounted` event + if (!markedInstance) { + console.error('[artalk-plugin-katex] no marked instance found') + return + } + + let i = 0 + const nextID = () => `__atk_katex_id_${i++}__` + const mathExpressions: { + [key: string]: { type: 'block' | 'inline'; expression: string } + } = {} + + function replaceMathWithIds(text: string) { + // Allowing newlines inside of `$$...$$` + text = text.replace(/\$\$([\s\S]+?)\$\$/g, (_match, expression) => { + const id = nextID() + mathExpressions[id] = { type: 'block', expression } + return id + }) + + // Not allowing newlines or space inside of `$...$` + text = text.replace(/\$([^\n]+?)\$/g, (_match, expression) => { + const id = nextID() + mathExpressions[id] = { type: 'inline', expression } + return id + }) + + return text + } + + // Marked render + const renderer = new markedInstance.Renderer() as any + + const orgListitem = renderer.listitem + const orgParagraph = renderer.paragraph + const orgTablecell = renderer.tablecell + const orgCodespan = renderer.codespan + const orgText = renderer.text + + renderer.listitem = (text: string, task: boolean, checked: boolean) => + orgListitem(replaceMathWithIds(text), task, checked) + renderer.paragraph = (text: string) => orgParagraph(replaceMathWithIds(text)) + renderer.tablecell = (content: string, flags: any) => + orgTablecell(replaceMathWithIds(content), flags) + renderer.codespan = (code: string) => orgCodespan(replaceMathWithIds(code)) + renderer.text = (text: string) => orgText(replaceMathWithIds(text)) // Inline level, maybe unneeded + + ctx.updateConf({ + markedReplacers: [ + (text) => { + text = text.replace(/(__atk_katex_id_\d+__)/g, (_match, capture) => { + const v = mathExpressions[capture] + const type = v.type + let expression = v.expression + + // replace
tag to \n + expression = expression.replace(//gm, '\n') + + return katex.renderToString(expression, { + displayMode: type === 'block', + }) + }) + + return text + }, + ], + }) + + markedInstance.use({ + renderer, + }) + }) +} diff --git a/ui/plugin-katex/tsconfig.json b/ui/plugin-katex/tsconfig.json index 122e9c5f0..3cd806454 100644 --- a/ui/plugin-katex/tsconfig.json +++ b/ui/plugin-katex/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "baseUrl": ".", - "outDir": "dist" + "outDir": "dist", + "types": ["@artalk/plugin-kit/client"] } } diff --git a/ui/plugin-katex/vite.config.ts b/ui/plugin-katex/vite.config.ts index b40c1ff01..51cc9f9e9 100644 --- a/ui/plugin-katex/vite.config.ts +++ b/ui/plugin-katex/vite.config.ts @@ -1,32 +1,17 @@ import { defineConfig } from 'vite' -import { resolve } from 'path' -import tsconfigPaths from 'vite-tsconfig-paths' + +import { ViteArtalkPluginKit } from '@artalk/plugin-kit' export default defineConfig({ - base: './', build: { - target: 'es2015', - outDir: resolve(__dirname, 'dist'), - minify: 'terser', - lib: { - entry: resolve(__dirname, './main.ts'), - name: 'artalk-plugin-katex', - fileName: (format) => - format == 'umd' ? 'artalk-plugin-katex.js' : `artalk-plugin-katex.${format}.js`, - formats: ['es', 'umd', 'iife'], - }, rollupOptions: { - // 确保外部化处理那些你不想打包进库的依赖 - external: ['artalk', 'katex'], + external: ['katex', 'katex/dist/katex.min.css'], output: { - // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量 globals: { - artalk: 'Artalk', katex: 'katex', }, - extend: true, }, }, }, - plugins: [tsconfigPaths()], + plugins: [ViteArtalkPluginKit()], })