From 61f4ea35c86b603fe8100c9a8a2154186a40fe40 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Wed, 16 Mar 2022 11:55:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8F=92=E4=BB=B6=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B8=B2=E6=9F=93=E5=9B=BE=E7=89=87=E7=9A=84?= =?UTF-8?q?=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/.ministarrc.js | 8 +++ web/plugins/com.msgbyte.miaolang/README.md | 11 ++++ .../com.msgbyte.miaolang/docs/output.png | Bin 0 -> 9804 bytes .../com.msgbyte.miaolang/docs/send.png | Bin 0 -> 4583 bytes .../com.msgbyte.miaolang/manifest.json | 1 + web/registry.json | 1 + web/src/components/ErrorBoundary.tsx | 57 +++++++++++++++++- web/src/components/Markdown.less | 4 ++ web/src/components/Markdown.tsx | 3 +- web/src/components/Modal.tsx | 6 +- .../DocumentView/DocumentMarkdownRender.tsx | 2 +- web/src/utils/__tests__/url-helper.spec.ts | 14 +++++ web/src/utils/url-helper.ts | 8 +++ web/test/setup.js | 4 ++ 14 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 web/plugins/com.msgbyte.miaolang/README.md create mode 100644 web/plugins/com.msgbyte.miaolang/docs/output.png create mode 100644 web/plugins/com.msgbyte.miaolang/docs/send.png create mode 100644 web/src/utils/__tests__/url-helper.spec.ts create mode 100644 web/src/utils/url-helper.ts diff --git a/web/.ministarrc.js b/web/.ministarrc.js index ee2f50c8..927cffaa 100644 --- a/web/.ministarrc.js +++ b/web/.ministarrc.js @@ -18,6 +18,14 @@ module.exports = { ), dest: path.resolve(__dirname, `./dist/plugins/${pluginName}/assets/`), }, + { + src: path.resolve( + __dirname, + `./plugins/${pluginName}`, + './docs/**/*' + ), + dest: path.resolve(__dirname, `./dist/plugins/${pluginName}/docs/`), + }, { src: path.resolve( __dirname, diff --git a/web/plugins/com.msgbyte.miaolang/README.md b/web/plugins/com.msgbyte.miaolang/README.md new file mode 100644 index 00000000..83ce9788 --- /dev/null +++ b/web/plugins/com.msgbyte.miaolang/README.md @@ -0,0 +1,11 @@ +## 喵语翻译 + +允许用户将自然语言转换为加密后的喵语 + +在任意聊天款的右侧添加喵语翻译 + +![](./docs/send.png) + +在此输入的任意内容都会被转换为加密后的喵语言,只有安装了相同插件的用户才能翻译 + +![](./docs/output.png) diff --git a/web/plugins/com.msgbyte.miaolang/docs/output.png b/web/plugins/com.msgbyte.miaolang/docs/output.png new file mode 100644 index 0000000000000000000000000000000000000000..beb16e14c0954c1d65e4766d6e946b5c400127e8 GIT binary patch literal 9804 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 { + state = { + error: undefined, + info: { + componentStack: '', + }, + }; + + componentDidCatch(error: Error | null, info: any) { + this.setState({ error, info }); + } + + render() { + const { message, description, children } = this.props; + const { error, info } = this.state; + const componentStack = + info && info.componentStack ? info.componentStack : null; + const errorMessage = + typeof message === 'undefined' ? (error || '').toString() : message; + const errorDescription = + typeof description === 'undefined' ? componentStack : description; + if (error) { + return ( +

+ +

{t('页面出现了一些问题')}

+

{errorMessage}

+ + } + /> +
+ ); + } + + return children; + } +} diff --git a/web/src/components/Markdown.less b/web/src/components/Markdown.less index 19849981..a93469bf 100644 --- a/web/src/components/Markdown.less +++ b/web/src/components/Markdown.less @@ -15,4 +15,8 @@ code { @apply px-2 py-1 bg-black bg-opacity-20 rounded; } + + p { + @apply my-2; + } } diff --git a/web/src/components/Markdown.tsx b/web/src/components/Markdown.tsx index 192d63f3..d0a6b8f6 100644 --- a/web/src/components/Markdown.tsx +++ b/web/src/components/Markdown.tsx @@ -1,3 +1,4 @@ +import { markAbsoluteUrl } from '@/utils/url-helper'; import React, { useCallback } from 'react'; import { isValidStr } from 'tailchat-shared'; import { Loadable } from './Loadable'; @@ -17,7 +18,7 @@ export const Markdown: React.FC<{ return url; } - return new URL(url, baseUrl).href; + return new URL(url, markAbsoluteUrl(baseUrl)).href; }, [baseUrl] ); diff --git a/web/src/components/Modal.tsx b/web/src/components/Modal.tsx index fadc3ae2..198fe736 100644 --- a/web/src/components/Modal.tsx +++ b/web/src/components/Modal.tsx @@ -11,9 +11,10 @@ import { Icon } from '@/components/Icon'; import { CSSTransition } from 'react-transition-group'; import clsx from 'clsx'; import { useIsMobile } from '@/hooks/useIsMobile'; +import { stopPropagation } from '@/utils/dom-helper'; +import { ErrorBoundary } from './ErrorBoundary'; import './Modal.less'; -import { stopPropagation } from '@/utils/dom-helper'; const transitionEndListener = (node: HTMLElement, done: () => void) => node.addEventListener('transitionend', done, false); @@ -101,7 +102,8 @@ export const Modal: React.FC = React.memo((props) => { onClick={closeModal} /> )} - {props.children} + + {props.children} diff --git a/web/src/plugin/PluginStore/DocumentView/DocumentMarkdownRender.tsx b/web/src/plugin/PluginStore/DocumentView/DocumentMarkdownRender.tsx index d264fedc..0a36b661 100644 --- a/web/src/plugin/PluginStore/DocumentView/DocumentMarkdownRender.tsx +++ b/web/src/plugin/PluginStore/DocumentView/DocumentMarkdownRender.tsx @@ -24,7 +24,7 @@ export const DocumentMarkdownRender: React.FC<{ url: string }> = React.memo( return ; } - return ; + return ; } ); DocumentMarkdownRender.displayName = 'DocumentMarkdownRender'; diff --git a/web/src/utils/__tests__/url-helper.spec.ts b/web/src/utils/__tests__/url-helper.spec.ts new file mode 100644 index 00000000..a3765703 --- /dev/null +++ b/web/src/utils/__tests__/url-helper.spec.ts @@ -0,0 +1,14 @@ +import { markAbsoluteUrl } from '../url-helper'; + +describe('markAbsoluteUrl', () => { + test.each([ + ['bar', 'https://www.example.com/foo/bar'], + ['./bar', 'https://www.example.com/foo/bar'], + ['../bar', 'https://www.example.com/bar'], + ['/bar', 'https://www.example.com/bar'], + ['https://www.baidu.com', 'https://www.baidu.com/'], + ['https://www.baidu.com/search', 'https://www.baidu.com/search'], + ])('%s', (input, output) => { + expect(markAbsoluteUrl(input)).toBe(output); + }); +}); diff --git a/web/src/utils/url-helper.ts b/web/src/utils/url-helper.ts new file mode 100644 index 00000000..9de60d10 --- /dev/null +++ b/web/src/utils/url-helper.ts @@ -0,0 +1,8 @@ +/** + * 根据输入url返回绝对url + * @param relativeUrl 相对或绝对url + * @returns 绝对url + */ +export function markAbsoluteUrl(relativeUrl: string): string { + return new URL(relativeUrl, location.href).href; +} diff --git a/web/test/setup.js b/web/test/setup.js index 81851bfd..e2bde2e1 100644 --- a/web/test/setup.js +++ b/web/test/setup.js @@ -19,3 +19,7 @@ console.error = (...args) => { originalError.call(console, ...args); }; + +// Mock location +delete window.location; +window.location = new URL('https://www.example.com/foo/index');