0.0.2 • Published 21 days ago

@hankliu/rc-mirror-editor v0.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
21 days ago

@hankliu/rc-mirror-editor

NPM version npm download build status Codecov bundle size dumi

Mirror Editor 编辑器是功能齐全的代码编辑器,支持多种常规语言的IDE,允许配置支持智能提示。

特征

  • 支持常见语言
  • 支持多种主题

安装

npm install @hankliu/rc-mirror-editor --save

or

yarn add @hankliu/rc-mirror-editor

or

pnpm install @hankliu/rc-mirror-editor

使用

import type { LanguageName, TMirrorEditorTheme} from '@hankliu/rc-mirror-editor';
import MirrorEditor, { alls, langs } from '@hankliu/rc-mirror-editor';
import { Button, Checkbox, Col, ConfigProvider, Divider, Input, Row, Select } from '@hankliu/hankliu-ui';
import zhCN from '@hankliu/hankliu-ui/lib/locale/zh_CN'
import * as React from 'react';

const LanguageDemo = {
  html: `<h1>Turndown Demo</h1>

  <p>This demonstrates <a href="https://github.com/mixmark-io/turndown">turndown</a> – an HTML to Markdown converter in JavaScript.</p>

  <h2>Usage</h2>

  <pre><code class="language-js">var turndownService = new TurndownService()
  console.log(
    turndownService.turndown('&lt;h1&gt;Hello world&lt;/h1&gt;')
  )</code></pre>

  <hr />

  <p>It aims to be <a href="http://commonmark.org/">CommonMark</a>
   compliant, and includes options to style the output. These options include:</p>

  <ul>
    <li>headingStyle (setext or atx)</li>
    <li>horizontalRule (*, -, or _)</li>
    <li>bullet (*, -, or +)</li>
    <li>codeBlockStyle (indented or fenced)</li>
    <li>fence (~ or ~)</li>
    <li>emDelimiter (_ or *)</li>
    <li>strongDelimiter (** or __)</li>
    <li>linkStyle (inlined or referenced)</li>
    <li>linkReferenceStyle (full, collapsed, or shortcut)</li>
  </ul>
  `,
};

const themeOptions = ['dark', 'light']
  .concat(Object.keys(alls))
  .filter((item) => typeof alls[item as keyof typeof alls] !== 'function')
  .filter((item) => !/^(defaultSettings)/.test(item as keyof typeof alls));
const heightOptions = ['auto', '200px', '300px', '500px'];

export default function Base() {
  const [content, setContent] = React.useState<string>(LanguageDemo.html);
  const [language, setLanguage] = React.useState<LanguageName>("html");
  const [theme, setTheme] = React.useState<TMirrorEditorTheme>('dark');
  const [height, setHeight] = React.useState<string>('500px');
  const [placeholder, setPlaceholder] = React.useState<string>('请输入内容');
  const [autofocus, setAutofocus] = React.useState<boolean>(false);
  const [editable, setEditable] = React.useState<boolean>(true);

  const onDidChangeTheme = (callback: (theme: "dark" | "light") => void) => {
    const root = document.querySelector("html");

    const observer = new MutationObserver((mutationsList) => {
      for (const mutation of mutationsList) {
        if (mutation.type === "attributes") {
          if (root?.getAttribute("data-prefers-color") === "dark") {
            callback("dark");
          } else {
            callback("light");
          }
        }
      }
    });

    observer.observe(root, { attributes: true });

    return () => {
      observer.disconnect();
    };
  }

  return (
    <ConfigProvider locale={zhCN}>
      <MirrorEditor
        editable={editable}
        autoFocus={autofocus}
        placeholder={placeholder}
        height={height}
        value={content}
        language={language}
        theme={theme}
        onChange={(val) => {
          setContent(val);
        }}
        getWebAppTheme={() => {
          return document.querySelector("html")?.getAttribute("data-prefers-color") === "dark"
            ? "dark"
            : "light";
        }}
        onWebAppThemeChange={onDidChangeTheme}
      />

      <Divider />

      <Row gutter={16}>
        <Col span={8}>
          <Row align="middle">
            <Col flex="80px">语言:</Col>
            <Col flex="1">
              <Select
                value={language}
                style={{ width: "100%" }}
                onChange={(val) => {
                  setContent(LanguageDemo[val] || '');
                  setLanguage(val);
                }}
                showSearch
              >
                {
                  Object.keys(langs).sort().map((item) => (
                    <Select.Option key={item} value={item}>{item}</Select.Option>
                  ))
                }
              </Select>
            </Col>
          </Row>
        </Col>
        <Col span={8}>
          <Row align="middle">
            <Col flex="80px">主题:</Col>
            <Col flex="1">
              <Select
                value={theme}
                style={{ width: "100%" }}
                onChange={(val) => {
                  setTheme(val);
                }}
                showSearch
              >
                {
                  themeOptions.map((item) => (
                    <Select.Option key={item} value={item}>{item}</Select.Option>
                  ))
                }
              </Select>
            </Col>
          </Row>
        </Col>
        <Col span={8}>
          <Row align="middle">
            <Col flex="80px">高度:</Col>
            <Col flex="1">
              <Select
                value={height}
                style={{ width: "100%" }}
                onChange={(val) => {
                  setHeight(val);
                }}
                showSearch
              >
                {
                  heightOptions.map((item) => (
                    <Select.Option key={item} value={item}>{item}</Select.Option>
                  ))
                }
              </Select>
            </Col>
          </Row>
        </Col>
      </Row>

      <Row gutter={16} style={{ marginTop: '16px' }}>
        <Col span={8}>
          <Row align="middle">
            <Col flex="80px">placeholder:</Col>
            <Col flex="1">
              <Input
                style={{ width: "100" }}
                value={placeholder}
                onChange={(event) => { setPlaceholder(event.target.value) }}
              />
            </Col>
          </Row>
        </Col>
        <Col span={8}>
          <Row align="middle">
            <Col flex="80px">自动聚焦:</Col>
            <Col flex="1">
              <Checkbox
                checked={autofocus}
                onChange={(event) => { setAutofocus(event.target.checked) }}
              >
                自动聚焦
              </Checkbox>
            </Col>
          </Row>
        </Col>
        <Col span={8}>
          <Row align="middle">
            <Col flex="80px">是否可编辑:</Col>
            <Col flex="1">
              <Checkbox
                checked={editable}
                onChange={(event) => { setEditable(event.target.checked) }}
              >
                可编辑
              </Checkbox>
            </Col>
          </Row>
        </Col>
      </Row>

      <Row gutter={16} style={{ marginTop: '16px' }}>
        <Col span={8}>
          <Button onClick={() => { setContent('') }}>清空内容</Button>
        </Col>
      </Row>
    </ConfigProvider>
  );
}

API 参数

名称类型默认值描述
classNamestring-组件外层元素classname
prefixClsstringhlui-mirror-editor组件外层元素 classname 前缀
widthstring | number100%编辑器的宽度。
minWidthstring | numberauto编辑器的最小宽度。
maxWidthstring | numberauto编辑器的最大宽度。
heightstring | number100%编辑器的高度
minHeightstring | numberauto编辑器的最小高度
maxHeightstring | numberauto编辑器的最大高度
value编辑器中自动创建的模型的值string-
languagestringhtml编辑器中自动创建的模型的初始语言
themeTMirrorEditorTheme-编辑器的主题
optionsEditorStateConfig默认值在如下所示请参阅 EditorStateConfig
placeholderstring | HTMLElement-编辑器中占位符
indentWithTabbooleantrue是否使用制表符缩进
readOnlybooleanfalse编辑器是否只读
editablebooleantrue编辑器是否允许编辑
autoFocusbooleantrue编辑器是否自动聚焦
basicSetupboolean | BasicSetupOptionstrue编辑器中是否进行初始化配置
highlightWhitespacebooleantrue是否高亮空格
highlightActiveLinebooleantrue是否高亮当前所在的行
onChange(newValue: string, event: ViewUpdate) => void-当前编辑器模型的内容发生更改时发出的事件
onWillMount(state: EditorState) => void-在编辑器挂载之前发出的事件(类似于 componentWillMount React
onMount(editor: EditorView, state: EditorState) => void-挂载编辑器时发出的事件(类似于 componentDidMount React
onWillUnmount(editor: EditorView, state: EditorState) => void-在编辑器卸载之前发出的事件(类似于 componentWillUnmount React
getWebAppTheme() => "dark" | "light"getTheme获得当前Web应用的主题模式(亮色|暗色),当不存在 theme 参数时根据当前函数的返回值设置编辑器的主题
onWebAppThemeChange(callback: (theme: "dark" | "light") => void) => (() => void) | voidonDidChangeTheme当当前Web应用的主题模式(亮色|暗色)发生改变时的监听函数,当不存在 theme 参数时根据当前监听函数的返回值动态设置编辑器的主题

案例

npm start 然后打开 http://localhost:8000/examples/

线上案例: https://hankliu62.github.io/rc-mirror-editor

单元测试

npm test

覆盖率

npm run coverage

License

@hankliu/rc-mirror-editor is released under the MIT license.