Skip to content

Commit

Permalink
feat: 💥 题目编排&latex支持&修复link
Browse files Browse the repository at this point in the history
  • Loading branch information
rojer95 committed Aug 9, 2023
1 parent 5de6863 commit 2275856
Show file tree
Hide file tree
Showing 27 changed files with 833 additions and 92 deletions.
1 change: 1 addition & 0 deletions .dumirc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default defineConfig({
github: 'https://github.com/rojer95/dslate',
},
},
mfsu: false,
monorepoRedirect: {
srcDir: ['packages'],
peerDeps: true,
Expand Down
114 changes: 114 additions & 0 deletions docs/demos/math.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* defaultShowCode: true
*/
import DSlate, { DefaultToolbar, DSlateRef } from '@dslate/antd';
import { Button, ConfigProvider, Input, Space, theme } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import type { Descendant } from 'slate';

export default () => {
const [resultWeapp, setResultWeapp] = useState<string>();
const [resultHtml, setResultHtml] = useState<string>();
const [value, setValue] = useState<Descendant[]>([
{
type: 'paragraph',
children: [
{ text: '当' },
{ type: 'latex', children: [{ text: '' }], formula: 'b=1' },
{ text: '、' },
{ type: 'latex', children: [{ text: '' }], formula: 'c=2' },
{ text: '时,请计算' },
{ type: 'latex', children: [{ text: '' }], formula: 'a=b+c' },
{ text: '的结果?' },
],
},
]);

const ref = useRef<DSlateRef>(null);
const [mode, setMode] = useState(
document.documentElement.getAttribute('data-prefers-color') ?? 'light',
);

const switchMode = () => {
const doc = document.documentElement;
const attrName = 'data-prefers-color';
if (!doc.hasAttribute(attrName) || doc.getAttribute(attrName) === 'dark') {
doc.setAttribute(attrName, 'light');
setMode('light');
} else {
doc.setAttribute(attrName, 'dark');
setMode('dark');
}
};

const watch = (mutationsList: any[]) => {
const attrName = 'data-prefers-color';
for (const mutation of mutationsList) {
if (mutation.attributeName === attrName) {
setMode(document.documentElement.getAttribute(attrName) ?? 'light');
}
}
};

useEffect(() => {
let observer: any;
if (MutationObserver) {
observer = new MutationObserver(watch);
// 以上述配置开始观察目标节点
observer.observe(document.documentElement, { attributes: true });
// 之后,可停止观察
}
return () => observer?.disconnect?.();
}, []);

return (
<ConfigProvider
theme={{
algorithm:
mode === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm,
}}
>
<div>
<DSlate
toolbar={[...DefaultToolbar, 'latex']}
ref={ref}
value={value}
onChange={setValue}
/>
<br />
<Space>
<Button
onClick={() => {
setResultWeapp(
JSON.stringify(
ref.current?.serializeWeapp({
children: value,
}),
null,
2,
),
);
setResultHtml(
ref.current?.serialize?.({
children: value,
}),
);
}}
>
转格式
</Button>
<Button onClick={switchMode}>
{mode === 'dark' ? '亮色模式' : '暗色模式'}
</Button>
</Space>
<br />
<p>小程序结果:</p>
<Input.TextArea value={resultWeapp} autoSize readOnly />

<br />
<p>html结果:</p>
<Input.TextArea value={resultHtml} autoSize readOnly />
</div>
</ConfigProvider>
);
};
17 changes: 17 additions & 0 deletions docs/getting-started/math.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: 题目编排
order: 7
nav: 文档
---

# 题目编排

基于 DSlate 的 Antd 风格包,支持 html 渲染与小程序 RichNode 渲染模式

> 小程序请手动引入 katex-mini 包的 css ,具体请看链接:https://github.com/rojer95/katex-mini
> Antd 版本要求:antd >= 5.0
## Demo

<code src="../demos/math.tsx"></code>
13 changes: 7 additions & 6 deletions packages/antd/lib/components/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from "./editor";
export * from "./button";
export * from "./select";
export * from "./divider";
export * from "./tooltip";
export * from "./popover";
export * from './button';
export * from './divider';
export * from './editor';
export * from './input';
export * from './popover';
export * from './select';
export * from './tooltip';
19 changes: 19 additions & 0 deletions packages/antd/lib/components/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Input as AntdInput } from 'antd';
import { PropsWithChildren } from 'react';

export const Input = ({
children,
onChange,
...props
}: PropsWithChildren<any>) => {
return (
<AntdInput
{...props}
onChange={(e) => {
onChange?.(e.target.value);
}}
>
{children}
</AntdInput>
);
};
5 changes: 3 additions & 2 deletions packages/antd/lib/components/select.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { PropsWithChildren } from "react";
import { Select as AntdSelect } from "antd";
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Select as AntdSelect } from 'antd';
import { PropsWithChildren } from 'react';

export const Select = ({
children,
Expand Down
19 changes: 19 additions & 0 deletions packages/antd/lib/components/textarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Input as AntdInput } from 'antd';
import { PropsWithChildren } from 'react';

export const Textarea = ({
children,
onChange,
...props
}: PropsWithChildren<any>) => {
return (
<AntdInput.TextArea
{...props}
onChange={(e) => {
onChange?.(e.target.value);
}}
>
{children}
</AntdInput.TextArea>
);
};
7 changes: 5 additions & 2 deletions packages/antd/lib/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ import { registerElement } from '@dslate/component';

import DefaultPlugin from '@dslate/plugin';

import { Input, InputNumber, Progress } from 'antd';
import { InputNumber, Progress } from 'antd';
import {
AntdEditor,
Button,
Divider,
Input,
Popover,
Select,
Tooltip,
} from './components';

import type { AntdStyleDSlateProps } from './typing';

import { Textarea } from './components/textarea';
import EN_US from './locale/en_US';
import ZH_CN from './locale/zh_CN';

Expand All @@ -33,6 +35,7 @@ registerElement('input', Input);
registerElement('input-number', InputNumber);
registerElement('button', Button);
registerElement('select', Select);
registerElement('textarea', Textarea);

export const DefaultLocales = [ZH_CN, EN_US];

Expand Down Expand Up @@ -81,7 +84,7 @@ export default forwardRef<DSlateRef, AntdStyleDSlateProps>(
locales: mergeLocalteFromPlugins(locales, plugins),
plugins,
iconScriptUrl:
'//at.alicdn.com/t/c/font_3062978_atuqwazgoap.js',
'//at.alicdn.com/t/c/font_3062978_igshjiflyft.js',
}}
>
<AntdEditor {...props} toolbar={toolbar} ref={ref} />
Expand Down
57 changes: 30 additions & 27 deletions packages/component/lib/components/editable.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useCallback } from "react";
import {
mergeStyle,
PluginUuidContext,
useConfig,
useMessage,
usePluginHelper,
} from '@dslate/core';
import React, { useCallback } from 'react';
import {
DefaultElement,
Editable as SlateEditable,
RenderLeafProps,
useSlate,
} from "slate-react";
import {
PluginUuidContext,
usePluginHelper,
mergeStyle,
useConfig,
useMessage,
} from "@dslate/core";
} from 'slate-react';

import type { DSlatePlugin, RenderElementPropsWithStyle } from "@dslate/core";
import type { DSlatePlugin, RenderElementPropsWithStyle } from '@dslate/core';

interface EditableProps {
disabled?: boolean;
Expand All @@ -33,10 +33,10 @@ const Editable = ({
const getMessage = useMessage();

const renderElement = useCallback((props: RenderElementPropsWithStyle) => {
const style = mergeStyle(props.element, plugins, "element", editor);
const style = mergeStyle(props.element, plugins, 'element', editor);
const plugin = plugins.find(
(i: DSlatePlugin) =>
i.nodeType === "element" && i.type === props.element.type
i.nodeType === 'element' && i.type === props.element.type,
) as DSlatePlugin | undefined;

let dom;
Expand All @@ -53,7 +53,7 @@ const Editable = ({
);
} else {
const defaultElementPlugin = plugins.find(
(p: DSlatePlugin) => p.isDefaultElement
(p: DSlatePlugin) => p.isDefaultElement,
);

if (defaultElementPlugin && defaultElementPlugin.renderElement) {
Expand All @@ -77,10 +77,10 @@ const Editable = ({
const { attributes, children, leaf } = props;
const needRenderPlugin = plugins.find(
(i: DSlatePlugin) =>
i.nodeType === "text" && i.type in leaf && !!i.renderLeaf
i.nodeType === 'text' && i.type in leaf && !!i.renderLeaf,
) as DSlatePlugin | undefined;

const style = mergeStyle(leaf, plugins, "text", editor);
const style = mergeStyle(leaf, plugins, 'text', editor);

if (needRenderPlugin && needRenderPlugin.renderLeaf) {
return needRenderPlugin.renderLeaf({ ...props, style }, editor);
Expand All @@ -95,24 +95,27 @@ const Editable = ({

const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
for (const plugin of plugins) {
if (typeof plugin.onKeyDown === "function") {
if (typeof plugin.onKeyDown === 'function') {
plugin.onKeyDown(e, editor);
}
}
}, []);

return (
<SlateEditable
className={`dslate-editable ${className || ""}`}
renderElement={renderElement}
renderLeaf={renderLeaf}
onMouseDown={() => {
setVisibleKey?.(undefined);
}}
onKeyDown={onKeyDown}
readOnly={disabled}
placeholder={placeholder ?? getMessage("placeholder", "")}
/>
<>
<SlateEditable
className={`dslate-editable ${className || ''}`}
renderElement={renderElement}
renderLeaf={renderLeaf}
onMouseDown={() => {
setVisibleKey?.(undefined);
}}
onKeyDown={onKeyDown}
readOnly={disabled}
placeholder={placeholder ?? getMessage('placeholder', '')}
/>
<div style={{ clear: 'both' }}></div>
</>
);
};

Expand Down
21 changes: 11 additions & 10 deletions packages/component/lib/components/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export * from "./counter";
export * from "./divider";
export * from "./input-number";
export * from "./input";
export * from "./popover";
export * from "./progress";
export * from "./tooltip";
export * from "./icon";
export * from "./toolbar";
export * from "./editable";
export * from './counter';
export * from './divider';
export * from './editable';
export * from './icon';
export * from './input';
export * from './input-number';
export * from './popover';
export * from './progress';
export * from './textarea';
export * from './toolbar';
export * from './tooltip';
28 changes: 28 additions & 0 deletions packages/component/lib/components/textarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { PropsWithChildren } from 'react';
import { getElement } from '../element';

type InputProps = {
value?: string;
onChange: (value: string) => void;
autosize?: boolean;
[index: string]: any;
};

const Textarea = ({
children,
autosize,
...props
}: PropsWithChildren<InputProps>) => {
const InputElement = getElement('textarea');
if (!InputElement) return null;
return React.createElement(
InputElement,
{
...(props || {}),
autoSize: autosize,
} as any,
children,
);
};

export { Textarea };
Loading

0 comments on commit 2275856

Please sign in to comment.