diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 3c3629e6..00000000 --- a/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..1636c069 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules +dist +*.js +demo diff --git a/.gitignore b/.gitignore index 596a670b..7d793881 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ logs *.log* .idea -/lib/ +/lib node_modules -/.vscode/ -ts-build/ +/.vscode +/.rollup.cache diff --git a/.prettierrc b/.prettierrc index b6674492..09a139ce 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,12 @@ { + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "jsxSingleQuote": true, + "quoteProps": "as-needed", + "semi": false, + "singleQuote": true, "tabWidth": 2, - "singleQuote": false, - "useTabs": false, - "jsxBracketSameLine": false, - "arrowParens": "avoid", - "trailingComma": "none" + "trailingComma": "all", + "useTabs": false } diff --git a/cleanup.mjs b/cleanup.mjs new file mode 100644 index 00000000..d5c55c80 --- /dev/null +++ b/cleanup.mjs @@ -0,0 +1,18 @@ +import fs from 'fs' +import path, { dirname } from 'path' +import { fileURLToPath } from 'url' +const __dirname = dirname(fileURLToPath(import.meta.url)) +const deleteDirRecursive = (path) => { + if (fs.existsSync(path)) { + fs.readdirSync(path).forEach((file) => { + const curPath = path.join(path, file) + if (fs.lstatSync(curPath).isDirectory()) { + deleteDirRecursive(curPath) + } else { + fs.unlinkSync(curPath) + } + }) + fs.rmdirSync(path) + } +} +deleteDirRecursive(path.join(__dirname, '../lib')) diff --git a/cypress.json b/cypress.json deleted file mode 100644 index 0967ef42..00000000 --- a/cypress.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json deleted file mode 100644 index da18d935..00000000 --- a/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} \ No newline at end of file diff --git a/cypress/integration/keyboard-commands.ts b/cypress/integration/keyboard-commands.ts deleted file mode 100644 index 9a925404..00000000 --- a/cypress/integration/keyboard-commands.ts +++ /dev/null @@ -1,19 +0,0 @@ -context("Keyboard commands", () => { - beforeEach(() => { - cy.visit("http://localhost:4000"); - }); - it("bold", () => { - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("nice") - .type("{ctrl}b") - .should("have.value", "**nice**"); - }); - it("italic", () => { - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("nice") - .type("{ctrl}i") - .should("have.value", "*nice*"); - }); -}); diff --git a/cypress/integration/mentions.ts b/cypress/integration/mentions.ts deleted file mode 100644 index 7264ced8..00000000 --- a/cypress/integration/mentions.ts +++ /dev/null @@ -1,64 +0,0 @@ -const DELAY = 500; - -context("Suggestions", () => { - beforeEach(() => { - cy.visit("http://localhost:4000"); - }); - it("'@' should display the suggestions box", () => { - cy.get(".mde-suggestions").should("not.exist"); - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("@"); - cy.get(".mde-suggestions").should("exist"); - cy.get(".mde-suggestions") - .find("li") - .should("have.length", 4); - }); - it("'@' + 'an' should display 2 elements ", () => { - cy.get(".mde-suggestions").should("not.exist"); - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("@an"); - cy.get(".mde-suggestions").should("exist"); - cy.get(".mde-suggestions") - .find("li") - .should("have.length", 2); - }); - it("'@' + 'an' + 2x backspace should display 4 elements", () => { - cy.get(".mde-suggestions").should("not.exist"); - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("@an") - .type("{backspace}{backspace}"); - cy.get(".mde-suggestions").should("exist"); - cy.get(".mde-suggestions") - .find("li") - .should("have.length", 4); - }); - it("'@ + Enter' should select the first suggestion", () => { - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("@") - .wait(DELAY) - .type("{enter}") - .should("have.value", "@andre "); - }); - it("'@ + Arrow down + Enter' should select the first suggestion", () => { - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("@") - .wait(DELAY) - .type("{downArrow}") - .type("{enter}") - .should("have.value", "@angela "); - }); - it("'@ + 4x Arrow down + Enter' should cycle and select the first suggestion", () => { - cy.get(".mde-text") - .type("{selectall}{backspace}") - .type("@") - .wait(DELAY) - .type("{downArrow}{downArrow}{downArrow}{downArrow}") - .type("{enter}") - .should("have.value", "@andre "); - }); -}); diff --git a/cypress/integration/toolbar.ts b/cypress/integration/toolbar.ts deleted file mode 100644 index 7e262180..00000000 --- a/cypress/integration/toolbar.ts +++ /dev/null @@ -1,41 +0,0 @@ -context("Toolbar", () => { - beforeEach(() => { - cy.visit("http://localhost:4000"); - }); - it("bold", () => { - cy.get(".mde-text").type("{selectall}{backspace}").type("react-mde"); - - cy.get('button[data-name="bold"]').click(); - cy.get(".mde-text").should("have.value", "**react-mde**"); - }); - it("italic", () => { - cy.get(".mde-text").type("{selectall}{backspace}").type("react-mde"); - - cy.get('button[data-name="italic"]').click(); - cy.get(".mde-text").should("have.value", "*react-mde*"); - }); - it("strikethrough", () => { - cy.get(".mde-text").type("{selectall}{backspace}").type("react-mde"); - - cy.get('button[data-name="strikethrough"]').click(); - cy.get(".mde-text").should("have.value", "~~react-mde~~"); - }); - it("link", () => { - cy.get(".mde-text").type("{selectall}{backspace}").type("react-mde"); - - cy.get('button[data-name="link"]').click(); - cy.get(".mde-text").should("have.value", "[react-mde](url)"); - }); - it("quote", () => { - cy.get(".mde-text").type("{selectall}{backspace}").type("react-mde"); - - cy.get('button[data-name="quote"]').click(); - cy.get(".mde-text").should("have.value", "> react-mde"); - }); - it("image", () => { - cy.get(".mde-text").type("{selectall}{backspace}").type("react-mde"); - - cy.get('button[data-name="image"]').click(); - cy.get(".mde-text").should("have.value", "![](react-mde)"); - }); -}); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js deleted file mode 100644 index 68aae934..00000000 --- a/cypress/plugins/index.js +++ /dev/null @@ -1,8 +0,0 @@ -var wp = require("@cypress/webpack-preprocessor"); - -module.exports = function(on) { - var options = { - webpackOptions: require("../webpack.config.js") - }; - on("file:preprocessor", wp(options)); -}; diff --git a/cypress/support/commands.js b/cypress/support/commands.js deleted file mode 100644 index ca4d256f..00000000 --- a/cypress/support/commands.js +++ /dev/null @@ -1,25 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add("login", (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/cypress/support/index.js b/cypress/support/index.js deleted file mode 100644 index d68db96d..00000000 --- a/cypress/support/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json deleted file mode 100644 index 9d5fdf48..00000000 --- a/cypress/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "target": "es5", - "lib": ["es5", "dom"], - "types": ["cypress", "node"] - }, - "include": ["**/*.ts"] -} diff --git a/cypress/tsconfig.plugins.json b/cypress/tsconfig.plugins.json deleted file mode 100644 index f7954d61..00000000 --- a/cypress/tsconfig.plugins.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "target": "es5", - "lib": ["es5", "dom"], - "types": ["cypress", "node"], - "module": "commonjs", - "moduleResolution": "node", - "experimentalDecorators": true, - "jsx": "react", - "esModuleInterop": true, - "emitDecoratorMetadata": true - }, - "include": ["plugins/**/*.ts"] -} diff --git a/cypress/webpack.config.js b/cypress/webpack.config.js deleted file mode 100644 index 89bdb23c..00000000 --- a/cypress/webpack.config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - mode: "development", - resolve: { - extensions: [".ts", ".js"] - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: [/node_modules/], - use: [ - { - loader: "awesome-typescript-loader", - options: { - // skip typechecking for speed - transpileOnly: true - } - } - ] - } - ] - } -}; diff --git a/demo.vite.config.mjs b/demo.vite.config.mjs new file mode 100644 index 00000000..8642ac2b --- /dev/null +++ b/demo.vite.config.mjs @@ -0,0 +1,22 @@ +import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite' +export default defineConfig({ + root: './demo', + plugins: [react()], + build: { + outDir: '../dist', + rollupOptions: { + external: ['react', 'react-dom'], + output: { + globals: { + react: 'React', + 'react-dom': 'ReactDOM', + }, + }, + }, + target: 'esnext', + }, + server: { + open: true, + }, +}) diff --git a/demo/App.tsx b/demo/App.tsx deleted file mode 100644 index d71433fa..00000000 --- a/demo/App.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import * as React from "react"; -import ReactMde from "../src"; -import * as Showdown from "showdown"; -import { SaveImageHandler, Suggestion } from "../src/types"; - -export interface AppState { - value: string; - tab: "write" | "preview"; -} - -export class App extends React.Component<{}, AppState> { - converter: Showdown.Converter; - - constructor(props) { - super(props); - this.state = { - value: "**Hello world!!!**", - tab: "write" - }; - this.converter = new Showdown.Converter({ - tables: true, - simplifiedAutoLink: true, - strikethrough: true, - tasklists: true - }); - } - - handleValueChange = (value: string) => { - this.setState({ value }); - }; - - handleTabChange = (tab: "write" | "preview") => { - this.setState({ tab }); - }; - - loadSuggestions = async (text: string) => { - return new Promise((accept, reject) => { - setTimeout(() => { - const suggestions: Suggestion[] = [ - { - preview: "Andre", - value: "@andre" - }, - { - preview: "Angela", - value: "@angela" - }, - { - preview: "David", - value: "@david" - }, - { - preview: "Louise", - value: "@louise" - } - ].filter(i => i.preview.toLowerCase().includes(text.toLowerCase())); - accept(suggestions); - }, 250); - }); - }; - - render() { - const save: SaveImageHandler = async function*(data: ArrayBuffer, file: Blob) { - // Promise that waits for "time" milliseconds - const wait = function(time: number) { - return new Promise((a, r) => { - setTimeout(() => a(), time); - }); - }; - - // Upload "data" to your server - // Use XMLHttpRequest.send to send a FormData object containing - // "data" - // Check this question: https://stackoverflow.com/questions/18055422/how-to-receive-php-image-data-over-copy-n-paste-javascript-with-xmlhttprequest - - await wait(2000); - // yields the URL that should be inserted in the markdown - yield "https://picsum.photos/300"; - await wait(2000); - - // returns true meaning that the save was successful - return true; - }; - - return ( -
- - Promise.resolve(this.converter.makeHtml(markdown)) - } - selectedTab={this.state.tab} - loadSuggestions={this.loadSuggestions} - suggestionTriggerCharacters={["@"]} - suggestionsAutoplace={true} - paste={{ - saveImage: save - }} - /> -
- ); - } -} diff --git a/demo/client.tsx b/demo/client.tsx deleted file mode 100644 index 44ab3aed..00000000 --- a/demo/client.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import * as React from "react"; -import { render } from "react-dom"; -import { App } from "./App"; - -import "../node_modules/normalize.css/normalize.css"; -import "../src/styles/react-mde-all.scss"; -import "./styles/demo.scss"; -import "./styles/variables.scss"; - -render(, document.getElementById("#app_container")); diff --git a/demo/index.html b/demo/index.html index a15d48d0..9a43d92e 100644 --- a/demo/index.html +++ b/demo/index.html @@ -1,17 +1,14 @@ - react-mde + React Markdown Editor (FC) dev - + -
-
-
- +
\ No newline at end of file diff --git a/demo/index.prod.html b/demo/index.prod.html deleted file mode 100644 index 3c873967..00000000 --- a/demo/index.prod.html +++ /dev/null @@ -1,27 +0,0 @@ - - - react-mde - - - - - - -
-
-
- - - - \ No newline at end of file diff --git a/demo/main.tsx b/demo/main.tsx new file mode 100644 index 00000000..2273efe4 --- /dev/null +++ b/demo/main.tsx @@ -0,0 +1,45 @@ +import React, { useRef, useState } from 'react' +import { createRoot } from 'react-dom/client' +import Showdown from 'showdown' +import { Mde } from '../src' +import { MdeTabProps } from '../src/components/toolbar/typings' +// import { MdeLanguage } from '../src/components/language' +// load languages, default en +// MdeLanguage.setLang('zh-cn') +const App = () => { + const [value, setValue] = useState('### Hello World') + const refTextarea = useRef(null) + const [tab, setTab] = useState('write') + const converter = new Showdown.Converter({ + tables: true, + simplifiedAutoLink: true, + strikethrough: true, + tasklists: true, + }) + const handleValueChange = (value: string) => { + setValue(value) + } + const handleTabChange = (tab: MdeTabProps) => { + setTab(tab) + } + return ( + { + return converter.makeHtml(markdown) + }} + selectedTab={tab} + // paste={{ + // saveImage: save, + // }} + /> + ) +} +const c = document.getElementById('root') +if (!c) { + throw new Error('root not found') +} +createRoot(c).render() diff --git a/demo/server.ts b/demo/server.ts deleted file mode 100644 index 509faa7e..00000000 --- a/demo/server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as fs from "fs"; -import * as express from "express"; -import * as webpackMiddleware from "webpack-dev-middleware"; -import * as webpackHotMiddleware from "webpack-hot-middleware"; -import * as webpack from "webpack"; -import * as webpackConfig from "../webpack.config.demo.dev"; -const packageJson = require("../package.json"); - -const webpackCompiler = webpack(webpackConfig as any); -const port = 4000; - -require.extensions[".html"] = (module, filename) => { - module.exports = fs.readFileSync(filename, "utf8"); -}; - -const app = express(); - -app.use(webpackMiddleware(webpackCompiler)); -app.use(webpackHotMiddleware(webpackCompiler)); -app.use((req, res) => res.status(200).send(require("./index.html"))); - -app.listen(port, "0.0.0.0", () => { - const demoUrl = `http://localhost:${port}/`; - // tslint:disable-next-line - console.log(`${packageJson.name} running at ${demoUrl}`); -}); diff --git a/demo/styles/demo.scss b/demo/styles/demo.scss deleted file mode 100644 index b5d5ff28..00000000 --- a/demo/styles/demo.scss +++ /dev/null @@ -1,17 +0,0 @@ -@import 'variables.scss'; - -* { - box-sizing: border-box; -} - -body { - font-size: 14px; - font-family: sans-serif; -} - -.container { - max-width: 650px; - height: 600px; - padding: 10px; - margin: 0 auto; -} diff --git a/demo/styles/variables.scss b/demo/styles/variables.scss deleted file mode 100644 index 6f9d8041..00000000 --- a/demo/styles/variables.scss +++ /dev/null @@ -1 +0,0 @@ -$default-border-color: rgba(0, 0, 0, .125) !default; \ No newline at end of file diff --git a/dist/fc-mde.css b/dist/fc-mde.css new file mode 100644 index 00000000..cf285a49 --- /dev/null +++ b/dist/fc-mde.css @@ -0,0 +1 @@ +.fc-mde__main_e76010f9ac3f69e6{width:var(--fc-mde-svg-icon-size);height:var(--fc-mde-svg-icon-size)}.fc-mde__content_59ee8347a45e0596{display:flow-root;padding:1rem}.fc-mde__content_59ee8347a45e0596 img{display:block;max-width:100%;height:auto}.fc-mde__content_59ee8347a45e0596 h1{font-size:1.5em}.fc-mde__content_59ee8347a45e0596 h2{font-size:1.45em}.fc-mde__content_59ee8347a45e0596 h3{font-size:1.4em}.fc-mde__content_59ee8347a45e0596 h4{font-size:1.35em}.fc-mde__content_59ee8347a45e0596 h5{font-size:1.3em}.fc-mde__content_59ee8347a45e0596 h6{font-size:1.25em}.fc-mde__content_59ee8347a45e0596 h1,.fc-mde__content_59ee8347a45e0596 h2,.fc-mde__content_59ee8347a45e0596 h3,.fc-mde__content_59ee8347a45e0596 h4,.fc-mde__content_59ee8347a45e0596 h5,.fc-mde__content_59ee8347a45e0596 h6{line-height:1}.fc-mde__content_59ee8347a45e0596 h1,.fc-mde__content_59ee8347a45e0596 h2,.fc-mde__content_59ee8347a45e0596 h3,.fc-mde__content_59ee8347a45e0596 h4,.fc-mde__content_59ee8347a45e0596 h5,.fc-mde__content_59ee8347a45e0596 h6,.fc-mde__content_59ee8347a45e0596 table,.fc-mde__content_59ee8347a45e0596 blockquote,.fc-mde__content_59ee8347a45e0596 p,.fc-mde__content_59ee8347a45e0596 ul,.fc-mde__content_59ee8347a45e0596 ol,.fc-mde__content_59ee8347a45e0596 hr,.fc-mde__content_59ee8347a45e0596 pre{margin-top:1em;margin-bottom:1em}.fc-mde__content_59ee8347a45e0596 ul,.fc-mde__content_59ee8347a45e0596 ol{padding-left:1.5em;margin-bottom:1em}.fc-mde__content_59ee8347a45e0596 ul ul,.fc-mde__content_59ee8347a45e0596 ul ol,.fc-mde__content_59ee8347a45e0596 ol ul,.fc-mde__content_59ee8347a45e0596 ol ol{margin-top:0;margin-bottom:0}.fc-mde__content_59ee8347a45e0596 p{text-align:justify}.fc-mde__content_59ee8347a45e0596 pre{overflow-x:auto}.fc-mde__content_59ee8347a45e0596 pre,.fc-mde__content_59ee8347a45e0596 blockquote,.fc-mde__content_59ee8347a45e0596 code{padding:0 .5em}.fc-mde__content_59ee8347a45e0596 pre,.fc-mde__content_59ee8347a45e0596 blockquote{display:block;padding:1em}.fc-mde__content_59ee8347a45e0596 pre>*:first-child,.fc-mde__content_59ee8347a45e0596 blockquote>*:first-child{margin-top:0}.fc-mde__content_59ee8347a45e0596 pre>*:last-child,.fc-mde__content_59ee8347a45e0596 blockquote>*:last-child{margin-bottom:0}.fc-mde__content_59ee8347a45e0596 pre code,.fc-mde__content_59ee8347a45e0596 blockquote code{background-color:unset}.fc-mde__container_5d480c472a769b14{position:relative}.fc-mde__main_bbe7a060507c7387{outline:none;width:100%;border:0;vertical-align:top;height:10rem;resize:vertical;overflow-y:auto}.fc-mde__tab_707475e156219802{display:flex}.fc-mde__tabButton_5a17ac662ec07934{cursor:pointer;border:none;background:none;padding:var(--fc-mde-space-sm);border-radius:var(--fc-mde-border-radius)}.fc-mde__tabButton_5a17ac662ec07934:hover{background:var(--fc-mde-button-bg-hover)}.fc-mde__tabButton_5a17ac662ec07934[data-active]{background:var(--fc-mde-button-bg-active)}.fc-mde__header_1d136c3d982ffdcc{display:flex;flex-wrap:wrap;margin-bottom:var(--fc-mde-space-sm);padding-bottom:var(--fc-mde-space-sm);border-bottom:var(--fc-mde-border)}.fc-mde__btnGroup_b384efee5a15e109{display:flex;flex-wrap:wrap;align-items:center;margin:0 var(--fc-mde-space-sm) 0 0;padding:0;list-style:none}.fc-mde__btnGroup_b384efee5a15e109[data-hidden]{opacity:.3;pointer-events:none}.fc-mde__btn_a61d3b8445301110{position:relative;margin:0;padding:0}.fc-mde__btn_a61d3b8445301110 button{cursor:pointer;padding:var(--fc-mde-space-sm);margin:0;border:none;background:none;color:var(--fc-mde-fg);border-radius:var(--fc-mde-border-radius)}.fc-mde__btn_a61d3b8445301110 button:hover{background:var(--fc-mde-button-bg-hover)}:root{--fc-mde-fg: hsl(0, 0%, 20%);--fc-mde-button-bg-hover: hsla(0, 0%, 0%, .05);--fc-mde-button-bg-active: hsla(0, 0%, 0%, .1);--fc-mde-border: 1px solid hsla(0, 0%, 0%, .3);--fc-mde-border-radius: .5rem;--fc-mde-space: 1rem;--fc-mde-space-sm: .5rem;--fc-mde-svg-icon-size: 1.25em}.fc-mde__main_c29a242caf055ec0{padding:var(--fc-mde-space);border:var(--fc-mde-border);border-radius:var(--fc-mde-border-radius)}.fc-mde__container_8e4c12095dec4180[data-hidden]{display:none} diff --git a/dist/index.cjs b/dist/index.cjs new file mode 100644 index 00000000..592e116a --- /dev/null +++ b/dist/index.cjs @@ -0,0 +1,117 @@ +"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react"),Ke={zh:"预览","zh-CN":"预览"},He={zh:"编辑","zh-CN":"编辑"},Ve={"Add a link":{zh:"附加链接","zh-CN":"附加链接"},"Add bold text":{zh:"附加粗体","zh-CN":"附加粗体"},"Add checked list":{zh:"附加任务列表","zh-CN":"附加任务列表"},"Add header":{zh:"附加标题","zh-CN":"附加标题"},"Add image":{zh:"附加图像","zh-CN":"附加图像"},"Add italic text":{zh:"附加斜体","zh-CN":"附加斜体"},"Add ordered list":{zh:"附加有序列表","zh-CN":"附加有序列表"},"Add strikethrough text":{zh:"附加删除线","zh-CN":"附加删除线"},"Add unordered list":{zh:"附加无序列表","zh-CN":"附加无序列表"},"Insert a quote":{zh:"附加引用","zh-CN":"附加引用"},"Insert code":{zh:"附加代码","zh-CN":"附加代码"},Preview:Ke,Write:He};class Ge{langId="";setLangId=t=>{this.langId=t};gettext=(t,r="")=>{if(!this.langId)return t;const s=`${r||""}${t}`;return Ve?.[s]?.[this.langId]??t}}const h=new Ge;function Ue(n,t){if(!n)throw Error("Argument 'text' should be truthy");const r=a=>a===" "||a.charCodeAt(0)===10;let s=0,o=n.length;for(let a=t;a-1>-1;a--)if(r(n[a-1])){s=a;break}for(let a=t;a=0&&r>=0;o--)switch(n.charCodeAt(o)){case 32:continue;case 10:r--,s=!1;break;default:return r}return s?0:r}function fe(n="",t){if(t===n.length-1)return 0;let r=2,s=!0;for(let o=t;o=0;o++)switch(n.charCodeAt(o)){case 32:continue;case 10:{r--,s=!1;break}default:return r}return s?0:r}const Je=()=>({buttonProps:{"aria-label":h.gettext("Add bold text"),title:h.gettext("Add bold text")},execute:({initialState:n,textApi:t,setText:r})=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s),a=t.replaceSelection(`**${o.selectedText}**`);r(t.setSelectionRange({start:a.selection.end-2-o.selectedText.length,end:a.selection.end-2}).text)},handleKeyCommand:n=>(n.ctrlKey||n.metaKey)&&n.key==="b"}),Xe=()=>({buttonProps:{"aria-label":h.gettext("Insert code"),title:h.gettext("Insert code")},execute:({initialState:n,textApi:t,setText:r})=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s);if(o.selectedText.indexOf(` +`)===-1){t.replaceSelection(`\`${o.selectedText}\``);const x=o.selection.start+1,w=x+o.selectedText.length;t.setSelectionRange({start:x,end:w});return}const a=ue(o.text,o.selection.start),d=Array(a+1).join(` +`),f=fe(o.text,o.selection.end),p=Array(f+1).join(` +`);t.replaceSelection(`${d}\`\`\` +${o.selectedText} +\`\`\`${p}`);const m=o.selection.start+a+4,v=m+o.selectedText.length;r(t.setSelectionRange({start:m,end:v}).text)}}),Fe=(n,t,r)=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s),a=t.replaceSelection(`${r}${o.selectedText}`);return t.setSelectionRange({start:a.selection.end-o.selectedText.length,end:a.selection.end})},De=()=>({buttonProps:{"aria-label":h.gettext("Add header"),title:h.gettext("Add header")},execute:({initialState:n,textApi:t,setText:r})=>{r(Fe(n,t,"### ").text)}}),Qe=()=>({buttonProps:{"aria-label":h.gettext("Add image"),title:h.gettext("Add image")},execute:({initialState:n,textApi:t,setText:r})=>{const s=t.setSelectionRange(S({text:n.text,selection:n.selection})),o=s.selectedText||"https://example.com/your-image.png";t.replaceSelection(`![](${o})`),r(t.setSelectionRange({start:s.selection.start+4,end:s.selection.start+4+o.length}).text)}}),Ze=()=>({buttonProps:{"aria-label":h.gettext("Add italic text"),title:h.gettext("Add italic text")},execute:({initialState:n,textApi:t,setText:r})=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s),a=t.replaceSelection(`*${o.selectedText}*`);r(t.setSelectionRange({start:a.selection.end-1-o.selectedText.length,end:a.selection.end-1}).text)},handleKeyCommand:n=>(n.ctrlKey||n.metaKey)&&n.key==="i"}),et=()=>({buttonProps:{"aria-label":h.gettext("Add a link"),title:h.gettext("Add a link")},execute:({initialState:n,textApi:t,setText:r})=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s),a=t.replaceSelection(`[${o.selectedText}](url)`);r(t.setSelectionRange({start:a.selection.end-6-o.selectedText.length,end:a.selection.end-6}).text)},handleKeyCommand:n=>(n.ctrlKey||n.metaKey)&&n.key==="k"});function tt(n,t){const r=n.split(/\n/);let s=0;return{modifiedText:r.map((a,d)=>{if(typeof t=="string")return s+=t.length,t+a;if(typeof t=="function"){const f=t(a,d);return s+=f.length,t(a,d)+a}throw Error("insertion is expected to be either a string or a function")}).join(` +`),insertionLength:s}}const me=(n,t,r)=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s),a=ue(o.text,o.selection.start),d=Array(a+1).join(` +`),f=fe(o.text,o.selection.end),p=Array(f+1).join(` +`),m=tt(o.selectedText,r);t.replaceSelection(`${d}${m.modifiedText}${p}`);const v=o.selectedText.indexOf(` +`)===-1?m.insertionLength:0,x=o.selection.start+a+v,w=x+m.modifiedText.length-v;return t.setSelectionRange({start:x,end:w})},nt=()=>({buttonProps:{"aria-label":h.gettext("Add unordered list"),title:h.gettext("Add unordered list")},execute:({initialState:n,textApi:t,setText:r})=>{r(me(n,t,"- ").text)}}),ot=()=>({buttonProps:{"aria-label":h.gettext("Add ordered list"),title:h.gettext("Add ordered list")},execute:({initialState:n,textApi:t,setText:r})=>{r(me(n,t,(s,o)=>`${o+1}. `).text)}}),rt=()=>({buttonProps:{"aria-label":h.gettext("Add checked list"),title:h.gettext("Add checked list")},execute:({initialState:n,textApi:t,setText:r})=>{r(me(n,t,()=>"- [ ] ").text)}}),at=()=>({buttonProps:{"aria-label":h.gettext("Insert a quote"),title:h.gettext("Insert a quote")},execute:({initialState:n,textApi:t,setText:r})=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s),a=ue(o.text,o.selection.start),d=Array(a+1).join(` +`),f=fe(o.text,o.selection.end),p=Array(f+1).join(` +`);t.replaceSelection(`${d}> ${o.selectedText}${p}`);const m=o.selection.start+a+2,v=m+o.selectedText.length;r(t.setSelectionRange({start:m,end:v}).text)}}),st=()=>({buttonProps:{"aria-label":h.gettext("Add strikethrough text"),title:h.gettext("Add strikethrough text")},execute:({initialState:n,textApi:t,setText:r})=>{const s=S({text:n.text,selection:n.selection}),o=t.setSelectionRange(s),a=t.replaceSelection(`~~${o.selectedText}~~`);r(t.setSelectionRange({start:a.selection.end-2-o.selectedText.length,end:a.selection.end-2}).text)}}),$e=()=>[["header","bold","italic","strikethrough"],["link","quote","code","image"],["unorderedList","orderedList","checkedList"]],he=()=>({header:De,bold:Je,italic:Ze,strikethrough:st,link:et,quote:at,code:Xe,image:Qe,unorderedList:nt,orderedList:ot,checkedList:rt});function de(){return"save-image"}var Q={exports:{}},G={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var je;function ct(){if(je)return G;je=1;var n=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function r(s,o,a){var d=null;if(a!==void 0&&(d=""+a),o.key!==void 0&&(d=""+o.key),"key"in o){a={};for(var f in o)f!=="key"&&(a[f]=o[f])}else a=o;return o=a.ref,{$$typeof:n,type:s,key:d,ref:o!==void 0?o:null,props:a}}return G.Fragment=t,G.jsx=r,G.jsxs=r,G}var U={};/** + * @license React + * react-jsx-runtime.development.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ae;function it(){return Ae||(Ae=1,process.env.NODE_ENV!=="production"&&function(){function n(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===qe?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case K:return"Fragment";case ee:return"Portal";case E:return"Profiler";case F:return"StrictMode";case ne:return"Suspense";case oe:return"SuspenseList"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case N:return(e.displayName||"Context")+".Provider";case L:return(e._context.displayName||"Context")+".Consumer";case te:var c=e.render;return e=e.displayName,e||(e=c.displayName||c.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case re:return c=e.displayName||null,c!==null?c:n(e.type)||"Memo";case ae:c=e._payload,e=e._init;try{return n(e(c))}catch{}}return null}function t(e){return""+e}function r(e){try{t(e);var c=!1}catch{c=!0}if(c){c=console;var i=c.error,u=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return i.call(c,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",u),t(e)}}function s(){}function o(){if(H===0){be=console.log,pe=console.info,ve=console.warn,ye=console.error,Ce=console.group,ke=console.groupCollapsed,Ee=console.groupEnd;var e={configurable:!0,enumerable:!0,value:s,writable:!0};Object.defineProperties(console,{info:e,log:e,warn:e,error:e,group:e,groupCollapsed:e,groupEnd:e})}H++}function a(){if(H--,H===0){var e={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:M({},e,{value:be}),info:M({},e,{value:pe}),warn:M({},e,{value:ve}),error:M({},e,{value:ye}),group:M({},e,{value:Ce}),groupCollapsed:M({},e,{value:ke}),groupEnd:M({},e,{value:Ee})})}0>H&&console.error("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}function d(e){if(ce===void 0)try{throw Error()}catch(i){var c=i.stack.trim().match(/\n( *(at )?)/);ce=c&&c[1]||"",we=-1)":-1l||k[g]!==P[l]){var V=` +`+k[g].replace(" at new "," at ");return e.displayName&&V.includes("")&&(V=V.replace("",e.displayName)),typeof e=="function"&&le.set(e,V),V}while(1<=g&&0<=l);break}}}finally{ie=!1,O.H=u,a(),Error.prepareStackTrace=i}return k=(k=e?e.displayName||e.name:"")?d(k):"",typeof e=="function"&&le.set(e,k),k}function p(e){if(e==null)return"";if(typeof e=="function"){var c=e.prototype;return f(e,!(!c||!c.isReactComponent))}if(typeof e=="string")return d(e);switch(e){case ne:return d("Suspense");case oe:return d("SuspenseList")}if(typeof e=="object")switch(e.$$typeof){case te:return e=f(e.render,!1),e;case re:return p(e.type);case ae:c=e._payload,e=e._init;try{return p(e(c))}catch{}}return""}function m(){var e=O.A;return e===null?null:e.getOwner()}function v(e){if(xe.call(e,"key")){var c=Object.getOwnPropertyDescriptor(e,"key").get;if(c&&c.isReactWarning)return!1}return e.key!==void 0}function x(e,c){function i(){Te||(Te=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",c))}i.isReactWarning=!0,Object.defineProperty(e,"key",{get:i,configurable:!0})}function w(){var e=n(this.type);return Se[e]||(Se[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function _(e,c,i,u,C,g){return i=g.ref,e={$$typeof:Y,type:e,key:c,props:g,_owner:C},(i!==void 0?i:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:w}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function $(e,c,i,u,C,g){if(typeof e=="string"||typeof e=="function"||e===K||e===E||e===F||e===ne||e===oe||e===Ie||typeof e=="object"&&e!==null&&(e.$$typeof===ae||e.$$typeof===re||e.$$typeof===N||e.$$typeof===L||e.$$typeof===te||e.$$typeof===We||e.getModuleId!==void 0)){var l=c.children;if(l!==void 0)if(u)if(se(l)){for(u=0;u",l=" Did you accidentally export a JSX literal instead of a component?"):u=typeof e,console.error("React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",u,l);if(xe.call(c,"key")){l=n(e);var R=Object.keys(c).filter(function(k){return k!=="key"});u=0 +React keys must be passed directly to JSX without using spread: + let props = %s; + <%s key={someKey} {...props} />`,u,l,R,l),_e[l+u]=!0)}if(l=null,i!==void 0&&(r(i),l=""+i),v(c)&&(r(c.key),l=""+c.key),"key"in c){i={};for(var B in c)B!=="key"&&(i[B]=c[B])}else i=c;return l&&x(i,typeof e=="function"?e.displayName||e.name||"Unknown":e),_(e,l,g,C,m(),i)}function J(e,c){if(typeof e=="object"&&e&&e.$$typeof!==Ye){if(se(e))for(var i=0;i."),c}var z=y,Y=Symbol.for("react.transitional.element"),ee=Symbol.for("react.portal"),K=Symbol.for("react.fragment"),F=Symbol.for("react.strict_mode"),E=Symbol.for("react.profiler"),L=Symbol.for("react.consumer"),N=Symbol.for("react.context"),te=Symbol.for("react.forward_ref"),ne=Symbol.for("react.suspense"),oe=Symbol.for("react.suspense_list"),re=Symbol.for("react.memo"),ae=Symbol.for("react.lazy"),Ie=Symbol.for("react.offscreen"),ge=Symbol.iterator,qe=Symbol.for("react.client.reference"),O=z.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,xe=Object.prototype.hasOwnProperty,M=Object.assign,We=Symbol.for("react.client.reference"),se=Array.isArray,H=0,be,pe,ve,ye,Ce,ke,Ee;s.__reactDisabledLog=!0;var ce,we,ie=!1,le=new(typeof WeakMap=="function"?WeakMap:Map),Ye=Symbol.for("react.client.reference"),Te,Se={},_e={},Re={};U.Fragment=K,U.jsx=function(e,c,i,u,C){return $(e,c,i,!1,u,C)},U.jsxs=function(e,c,i,u,C){return $(e,c,i,!0,u,C)}}()),U}var Ne;function lt(){return Ne||(Ne=1,process.env.NODE_ENV==="production"?Q.exports=ct():Q.exports=it()),Q.exports}var b=lt();const dt=(n,t)=>{n.setRangeText(t,n.selectionStart||0,n.selectionEnd||0,"select")};function ut(n){const t=[];for(const r in n)n.hasOwnProperty.call(n,r)&&n[r]().handleKeyCommand&&t.push(r);return t}class ft{refTextarea;constructor(t){this.refTextarea=t}replaceSelection=t=>{const r=this.refTextarea.current;return dt(r,t),Z(r)};setSelectionRange=t=>{const r=this.refTextarea.current;return r.focus(),r.selectionStart=t.start,r.selectionEnd=t.end,Z(r)};getState=()=>{const t=this.refTextarea.current;return Z(t)}}const Z=n=>({selection:{start:n.selectionStart,end:n.selectionEnd},text:n.value,selectedText:n.value.slice(n.selectionStart,n.selectionEnd)});class mt{setText;refTextarea;textApi;commandMap;keyActivatedCommands;isExecuting=!1;pasteOptions;constructor({setText:t,customCommands:r,refTextarea:s,pasteOptions:o}){if(o&&!o.saveImage)throw new Error("paste options are incomplete. saveImage are required ");this.commandMap={...he(),...r||{}},this.pasteOptions=o,this.keyActivatedCommands=ut(r),this.refTextarea=s,this.textApi=new ft(s),this.setText=t}getCommand=t=>{const r=this.commandMap[t];if(!r)throw new Error(`Cannot execute command. Command not found: ${t}`);return r()};handleKeyCommand=async t=>{for(const r of this.keyActivatedCommands)if(this.getCommand(r)?.handleKeyCommand?.(t))return await this.executeCommand(r),!0;return!1};executeCommand=async(t,r)=>{if(this.isExecuting)return;this.isExecuting=!0;const s=this.refTextarea.current,o=Z(s);await this.getCommand(t).execute({setText:this.setText,initialState:o,textApi:this.textApi,context:r}),this.isExecuting=!1};executePasteCommand=async t=>{if(this.pasteOptions)return this.executeCommand(this.pasteOptions.command||de(),{pasteOptions:this.pasteOptions,event:t})};executeDropCommand=async t=>{if(this.pasteOptions)return this.executeCommand(this.pasteOptions.command||de(),{pasteOptions:this.pasteOptions,event:t})};executeSelectImageCommand=async t=>{if(this.pasteOptions)return this.executeCommand(this.pasteOptions.command||de(),{pasteOptions:this.pasteOptions,event:t})};getCommandByName=t=>this.commandMap[t]}/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ht=n=>n.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),ze=(...n)=>n.filter((t,r,s)=>!!t&&t.trim()!==""&&s.indexOf(t)===r).join(" ").trim();/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */var gt={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const xt=y.forwardRef(({color:n="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:s,className:o="",children:a,iconNode:d,...f},p)=>y.createElement("svg",{ref:p,...gt,width:t,height:t,stroke:n,strokeWidth:s?Number(r)*24/Number(t):r,className:ze("lucide",o),...f},[...d.map(([m,v])=>y.createElement(m,v)),...Array.isArray(a)?a:[a]]));/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const T=(n,t)=>{const r=y.forwardRef(({className:s,...o},a)=>y.createElement(xt,{ref:a,iconNode:t,className:ze(`lucide-${ht(n)}`,s),...o}));return r.displayName=`${n}`,r};/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const bt=T("Bold",[["path",{d:"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8",key:"mg9rjx"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const pt=T("CodeXml",[["path",{d:"m18 16 4-4-4-4",key:"1inbqp"}],["path",{d:"m6 8-4 4 4 4",key:"15zrgr"}],["path",{d:"m14.5 4-5 16",key:"e7oirm"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const vt=T("Heading",[["path",{d:"M6 12h12",key:"8npq4p"}],["path",{d:"M6 20V4",key:"1w1bmo"}],["path",{d:"M18 20V4",key:"o2hl4u"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const yt=T("Image",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ct=T("Italic",[["line",{x1:"19",x2:"10",y1:"4",y2:"4",key:"15jd3p"}],["line",{x1:"14",x2:"5",y1:"20",y2:"20",key:"bu0au3"}],["line",{x1:"15",x2:"9",y1:"4",y2:"20",key:"uljnxc"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const kt=T("Link",[["path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71",key:"1cjeqo"}],["path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71",key:"19qd67"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Et=T("ListChecks",[["path",{d:"m3 17 2 2 4-4",key:"1jhpwq"}],["path",{d:"m3 7 2 2 4-4",key:"1obspn"}],["path",{d:"M13 6h8",key:"15sg57"}],["path",{d:"M13 12h8",key:"h98zly"}],["path",{d:"M13 18h8",key:"oe0vm4"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const wt=T("ListOrdered",[["path",{d:"M10 12h11",key:"6m4ad9"}],["path",{d:"M10 18h11",key:"11hvi2"}],["path",{d:"M10 6h11",key:"c7qv1k"}],["path",{d:"M4 10h2",key:"16xx2s"}],["path",{d:"M4 6h1v4",key:"cnovpq"}],["path",{d:"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1",key:"m9a95d"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Tt=T("List",[["path",{d:"M3 12h.01",key:"nlz23k"}],["path",{d:"M3 18h.01",key:"1tta3j"}],["path",{d:"M3 6h.01",key:"1rqtza"}],["path",{d:"M8 12h13",key:"1za7za"}],["path",{d:"M8 18h13",key:"1lx6n3"}],["path",{d:"M8 6h13",key:"ik3vkj"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const St=T("Quote",[["path",{d:"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z",key:"rib7q0"}],["path",{d:"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z",key:"1ymkrd"}]]);/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const _t=T("Strikethrough",[["path",{d:"M16 4H9a3 3 0 0 0-2.83 4",key:"43sutm"}],["path",{d:"M14 12a4 4 0 0 1 0 8H6",key:"nlfj13"}],["line",{x1:"4",x2:"20",y1:"12",y2:"12",key:"1e0a9i"}]]),Rt="fc-mde__main_e76010f9ac3f69e6",jt={main:Rt},At=n=>b.jsx("div",{"data-fc-mde-svg-icon-container":!0,...n}),Nt=({icon:n})=>{const t={header:vt,bold:bt,italic:Ct,strikethrough:_t,code:pt,quote:St,unorderedList:wt,orderedList:Tt,checkedList:Et,link:kt,image:yt}[n]??null;return t?b.jsx(At,{children:b.jsx(t,{className:jt.main,"data-fc-mde-svg-icon":!0})}):null},Ot="fc-mde__content_59ee8347a45e0596",Oe={content:Ot},Le=y.forwardRef(({markdown:n,generateMarkdownPreview:t,loadingPreview:r},s)=>{const[o,a]=y.useState(!0),[d,f]=y.useState(""),[p,m]=y.useState(""),v=y.useCallback(async()=>{f(await t(n)),a(!1)},[t,n]);y.useEffect(()=>{n!==p&&(v(),m(n))},[p,n,v]);let x=null;return o?x=b.jsx("div",{className:Oe.content,"data-fc-mde-preview-content":!0,children:r}):x=b.jsx("div",{className:Oe.content,ref:s,"data-fc-mde-preview-content":!0,dangerouslySetInnerHTML:{__html:d}}),b.jsx("div",{"data-mde-preview":!0,"data-loading":o||void 0,children:x})});Le.displayName="MdePreview";const Mt="fc-mde__container_5d480c472a769b14",Pt="fc-mde__main_bbe7a060507c7387",Me={container:Mt,main:Pt},Be=y.forwardRef(({value:n,setValue:t,textareaComponent:r,onKeyCommand:s,...o},a)=>{const d=r||"textarea",f=y.useCallback(m=>{m.preventDefault(),(m.clipboardData.files??[]).length},[]),p=y.useCallback(m=>{t(m.target.value)},[t]);return b.jsx("div",{className:Me.container,"data-fc-mde-textarea-container":!0,children:b.jsx(d,{ref:a,className:Me.main,value:n,onChange:p,onKeyDown:s,onPaste:f,"data-fc-mde-textarea":!0,...o})})});Be.displayName="MdeTextarea";const $t="fc-mde__tab_707475e156219802",zt="fc-mde__tabButton_5a17ac662ec07934",Lt="fc-mde__header_1d136c3d982ffdcc",Bt="fc-mde__btnGroup_b384efee5a15e109",It="fc-mde__btn_a61d3b8445301110",I={tab:$t,tabButton:zt,header:Lt,btnGroup:Bt,btn:It},qt={tabIndex:-1},Wt=({buttonComponentClass:n,buttonContent:t,buttonProps:r,onClick:s,readOnly:o,name:a})=>{const d={...qt,...r||{}},f=n||"button";return b.jsx("div",{className:I.btn,"data-fc-mde-toolbar-button":!0,children:y.createElement(f,{"data-fc-mde-toolbar-button-item":!0,"data-name":a,...d,onClick:s,disabled:o,type:"button"},t)})},Yt=({hidden:n,children:t})=>b.jsx("div",{className:I.btnGroup,"data-fc-mde-toolbar-button-group":!0,"data-hidden":n||void 0,children:t}),Kt=({onTabChange:n,buttons:t,onCommand:r,readOnly:s,disablePreview:o,writeButtonProps:a,previewButtonProps:d,tab:f,buttonProps:p})=>{const m=(x,w)=>{x.preventDefault(),n(w)};if(!t?.length)return null;const v=b.jsxs("div",{className:I.tab,"data-fc-mde-tab":!0,children:[b.jsx("button",{type:"button",className:I.tabButton,"data-fc-mde-tab-button":!0,onClick:x=>m(x,"write"),"data-active":f==="write"||void 0,...a,children:h.gettext("Write")}),b.jsx("button",{type:"button",className:I.tabButton,"data-fc-mde-tab-button":!0,onClick:x=>m(x,"preview"),"data-active":f==="preview"||void 0,...d,children:h.gettext("Preview")})]});return b.jsxs("div",{className:I.header,"data-fc-mde-header":!0,children:[o||v,t.map((x,w)=>b.jsx(Yt,{hidden:f==="preview",children:x.map((_,$)=>b.jsx(Wt,{name:_.commandName,buttonContent:_.buttonContent,buttonProps:{...p||{},..._.buttonProps},onClick:()=>r(_.commandName),readOnly:s,buttonComponentClass:_.buttonComponentClass},$))},w))]})},Ht="fc-mde__main_c29a242caf055ec0",Vt="fc-mde__container_8e4c12095dec4180",Pe={main:Ht,container:Vt},Gt=({setText:n,refTextarea:t,commands:r=he(),toolbarCommands:s=$e(),getIcon:o=W=>b.jsx(Nt,{icon:W}),readOnly:a=!1,selectedTab:d="write",disablePreview:f=!1,paste:p,onTabChange:m,loadingPreview:v,text:x,generateMarkdownPreview:w,textareaComponent:_,commandButtons:$,writeButton:J,previewButton:q,textareaProps:X})=>{const W=y.useRef(null),z=new mt({setText:n,customCommands:r,refTextarea:t,pasteOptions:p}),Y=async E=>{p?.saveImage&&await z.executePasteCommand(E)},ee=E=>{m(E)},K=async E=>{await z.executeCommand(E)},F=s.map(E=>E.map(L=>{const N=z.getCommand(L);return{commandName:L,buttonContent:N.icon?N.icon(o):o(L),buttonProps:N.buttonProps,buttonComponentClass:N.buttonComponentClass}})).filter(E=>E);return b.jsxs("div",{className:Pe.main,"data-fc-mde":!0,children:[b.jsx(Kt,{buttons:F,onCommand:K,onTabChange:ee,tab:d,readOnly:a,disablePreview:f,buttonProps:$,writeButtonProps:J,previewButtonProps:q}),b.jsx("div",{className:Pe.container,"data-fc-mde-container":!0,"data-hidden":d==="preview"||void 0,children:b.jsx(Be,{ref:t,value:x,setValue:n,textareaComponent:_,onKeyCommand:z.handleKeyCommand,onPaste:Y,...X})}),d!=="write"&&b.jsx(Le,{ref:W,loadingPreview:v,generateMarkdownPreview:w,markdown:x})]})};exports.Mde=Gt;exports.getDefaultCommandMap=he;exports.getDefaultToolbarCommands=$e;exports.selectWord=S; diff --git a/dist/index.es.js b/dist/index.es.js new file mode 100644 index 00000000..30a409ea --- /dev/null +++ b/dist/index.es.js @@ -0,0 +1,1399 @@ +import Ve, { forwardRef as ee, createElement as D, useState as ue, useCallback as me, useEffect as Ge, useRef as Ue } from "react"; +const Je = { zh: "预览", "zh-CN": "预览" }, Xe = { zh: "编辑", "zh-CN": "编辑" }, Fe = { + "Add a link": { zh: "附加链接", "zh-CN": "附加链接" }, + "Add bold text": { zh: "附加粗体", "zh-CN": "附加粗体" }, + "Add checked list": { zh: "附加任务列表", "zh-CN": "附加任务列表" }, + "Add header": { zh: "附加标题", "zh-CN": "附加标题" }, + "Add image": { zh: "附加图像", "zh-CN": "附加图像" }, + "Add italic text": { zh: "附加斜体", "zh-CN": "附加斜体" }, + "Add ordered list": { zh: "附加有序列表", "zh-CN": "附加有序列表" }, + "Add strikethrough text": { zh: "附加删除线", "zh-CN": "附加删除线" }, + "Add unordered list": { zh: "附加无序列表", "zh-CN": "附加无序列表" }, + "Insert a quote": { zh: "附加引用", "zh-CN": "附加引用" }, + "Insert code": { zh: "附加代码", "zh-CN": "附加代码" }, + Preview: Je, + Write: Xe +}; +class Qe { + langId = ""; + setLangId = (t) => { + this.langId = t; + }; + gettext = (t, r = "") => { + if (!this.langId) + return t; + const s = `${r || ""}${t}`; + return Fe?.[s]?.[this.langId] ?? t; + }; +} +const h = new Qe(); +function Ze(n, t) { + if (!n) + throw Error("Argument 'text' should be truthy"); + const r = (a) => a === " " || a.charCodeAt(0) === 10; + let s = 0, o = n.length; + for (let a = t; a - 1 > -1; a--) + if (r(n[a - 1])) { + s = a; + break; + } + for (let a = t; a < n.length; a++) + if (r(n[a])) { + o = a; + break; + } + return { start: s, end: o }; +} +function j({ text: n, selection: t }) { + return n && n.length && t.start === t.end ? Ze(n, t.start) : t; +} +function he(n = "", t) { + if (t === 0) + return 0; + let r = 2, s = !0; + for (let o = t - 1; o >= 0 && r >= 0; o--) + switch (n.charCodeAt(o)) { + case 32: + continue; + case 10: + r--, s = !1; + break; + default: + return r; + } + return s ? 0 : r; +} +function ge(n = "", t) { + if (t === n.length - 1) + return 0; + let r = 2, s = !0; + for (let o = t; o < n.length && r >= 0; o++) + switch (n.charCodeAt(o)) { + case 32: + continue; + case 10: { + r--, s = !1; + break; + } + default: + return r; + } + return s ? 0 : r; +} +const De = () => ({ + buttonProps: { + "aria-label": h.gettext("Add bold text"), + title: h.gettext("Add bold text") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s), a = t.replaceSelection(`**${o.selectedText}**`); + r( + t.setSelectionRange({ + start: a.selection.end - 2 - o.selectedText.length, + end: a.selection.end - 2 + }).text + ); + }, + handleKeyCommand: (n) => (n.ctrlKey || n.metaKey) && n.key === "b" +}), et = () => ({ + buttonProps: { + "aria-label": h.gettext("Insert code"), + title: h.gettext("Insert code") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s); + if (o.selectedText.indexOf(` +`) === -1) { + t.replaceSelection(`\`${o.selectedText}\``); + const x = o.selection.start + 1, E = x + o.selectedText.length; + t.setSelectionRange({ + start: x, + end: E + }); + return; + } + const a = he( + o.text, + o.selection.start + ), d = Array(a + 1).join(` +`), f = ge( + o.text, + o.selection.end + ), p = Array(f + 1).join(` +`); + t.replaceSelection( + `${d}\`\`\` +${o.selectedText} +\`\`\`${p}` + ); + const m = o.selection.start + a + 4, v = m + o.selectedText.length; + r( + t.setSelectionRange({ + start: m, + end: v + }).text + ); + } +}), tt = (n, t, r) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s), a = t.replaceSelection(`${r}${o.selectedText}`); + return t.setSelectionRange({ + start: a.selection.end - o.selectedText.length, + end: a.selection.end + }); +}, nt = () => ({ + buttonProps: { + "aria-label": h.gettext("Add header"), + title: h.gettext("Add header") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + r(tt(n, t, "### ").text); + } +}), ot = () => ({ + buttonProps: { + "aria-label": h.gettext("Add image"), + title: h.gettext("Add image") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + const s = t.setSelectionRange( + j({ + text: n.text, + selection: n.selection + }) + ), o = s.selectedText || "https://example.com/your-image.png"; + t.replaceSelection(`![](${o})`), r( + t.setSelectionRange({ + start: s.selection.start + 4, + end: s.selection.start + 4 + o.length + }).text + ); + } +}), rt = () => ({ + buttonProps: { + "aria-label": h.gettext("Add italic text"), + title: h.gettext("Add italic text") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s), a = t.replaceSelection(`*${o.selectedText}*`); + r( + t.setSelectionRange({ + start: a.selection.end - 1 - o.selectedText.length, + end: a.selection.end - 1 + }).text + ); + }, + handleKeyCommand: (n) => (n.ctrlKey || n.metaKey) && n.key === "i" +}), at = () => ({ + buttonProps: { + "aria-label": h.gettext("Add a link"), + title: h.gettext("Add a link") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s), a = t.replaceSelection(`[${o.selectedText}](url)`); + r( + t.setSelectionRange({ + start: a.selection.end - 6 - o.selectedText.length, + end: a.selection.end - 6 + }).text + ); + }, + handleKeyCommand: (n) => (n.ctrlKey || n.metaKey) && n.key === "k" +}); +function st(n, t) { + const r = n.split(/\n/); + let s = 0; + return { modifiedText: r.map((a, d) => { + if (typeof t == "string") + return s += t.length, t + a; + if (typeof t == "function") { + const f = t(a, d); + return s += f.length, t(a, d) + a; + } + throw Error("insertion is expected to be either a string or a function"); + }).join(` +`), insertionLength: s }; +} +const xe = (n, t, r) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s), a = he( + o.text, + o.selection.start + ), d = Array(a + 1).join(` +`), f = ge( + o.text, + o.selection.end + ), p = Array(f + 1).join(` +`), m = st(o.selectedText, r); + t.replaceSelection( + `${d}${m.modifiedText}${p}` + ); + const v = o.selectedText.indexOf(` +`) === -1 ? m.insertionLength : 0, x = o.selection.start + a + v, E = x + m.modifiedText.length - v; + return t.setSelectionRange({ + start: x, + end: E + }); +}, ct = () => ({ + buttonProps: { + "aria-label": h.gettext("Add unordered list"), + title: h.gettext("Add unordered list") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + r(xe(n, t, "- ").text); + } +}), it = () => ({ + buttonProps: { + "aria-label": h.gettext("Add ordered list"), + title: h.gettext("Add ordered list") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + r( + xe(n, t, (s, o) => `${o + 1}. `).text + ); + } +}), lt = () => ({ + buttonProps: { + "aria-label": h.gettext("Add checked list"), + title: h.gettext("Add checked list") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + r(xe(n, t, () => "- [ ] ").text); + } +}), dt = () => ({ + buttonProps: { + "aria-label": h.gettext("Insert a quote"), + title: h.gettext("Insert a quote") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s), a = he( + o.text, + o.selection.start + ), d = Array(a + 1).join(` +`), f = ge( + o.text, + o.selection.end + ), p = Array(f + 1).join(` +`); + t.replaceSelection( + `${d}> ${o.selectedText}${p}` + ); + const m = o.selection.start + a + 2, v = m + o.selectedText.length; + r( + t.setSelectionRange({ + start: m, + end: v + }).text + ); + } +}), ut = () => ({ + buttonProps: { + "aria-label": h.gettext("Add strikethrough text"), + title: h.gettext("Add strikethrough text") + }, + execute: ({ initialState: n, textApi: t, setText: r }) => { + const s = j({ + text: n.text, + selection: n.selection + }), o = t.setSelectionRange(s), a = t.replaceSelection(`~~${o.selectedText}~~`); + r( + t.setSelectionRange({ + start: a.selection.end - 2 - o.selectedText.length, + end: a.selection.end - 2 + }).text + ); + } +}), ft = () => [ + ["header", "bold", "italic", "strikethrough"], + ["link", "quote", "code", "image"], + ["unorderedList", "orderedList", "checkedList"] +], Le = () => ({ + header: nt, + bold: De, + italic: rt, + strikethrough: ut, + link: at, + quote: dt, + code: et, + image: ot, + unorderedList: ct, + orderedList: it, + checkedList: lt +}); +function fe() { + return "save-image"; +} +var Q = { exports: {} }, V = {}; +/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +var Ne; +function mt() { + if (Ne) return V; + Ne = 1; + var n = Symbol.for("react.transitional.element"), t = Symbol.for("react.fragment"); + function r(s, o, a) { + var d = null; + if (a !== void 0 && (d = "" + a), o.key !== void 0 && (d = "" + o.key), "key" in o) { + a = {}; + for (var f in o) + f !== "key" && (a[f] = o[f]); + } else a = o; + return o = a.ref, { + $$typeof: n, + type: s, + key: d, + ref: o !== void 0 ? o : null, + props: a + }; + } + return V.Fragment = t, V.jsx = r, V.jsxs = r, V; +} +var G = {}; +/** + * @license React + * react-jsx-runtime.development.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +var Oe; +function ht() { + return Oe || (Oe = 1, process.env.NODE_ENV !== "production" && function() { + function n(e) { + if (e == null) return null; + if (typeof e == "function") + return e.$$typeof === We ? null : e.displayName || e.name || null; + if (typeof e == "string") return e; + switch (e) { + case W: + return "Fragment"; + case te: + return "Portal"; + case C: + return "Profiler"; + case X: + return "StrictMode"; + case oe: + return "Suspense"; + case re: + return "SuspenseList"; + } + if (typeof e == "object") + switch (typeof e.tag == "number" && console.error( + "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue." + ), e.$$typeof) { + case R: + return (e.displayName || "Context") + ".Provider"; + case z: + return (e._context.displayName || "Context") + ".Consumer"; + case ne: + var c = e.render; + return e = e.displayName, e || (e = c.displayName || c.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e; + case ae: + return c = e.displayName || null, c !== null ? c : n(e.type) || "Memo"; + case se: + c = e._payload, e = e._init; + try { + return n(e(c)); + } catch { + } + } + return null; + } + function t(e) { + return "" + e; + } + function r(e) { + try { + t(e); + var c = !1; + } catch { + c = !0; + } + if (c) { + c = console; + var i = c.error, u = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object"; + return i.call( + c, + "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", + u + ), t(e); + } + } + function s() { + } + function o() { + if (K === 0) { + ve = console.log, ye = console.info, ke = console.warn, Ce = console.error, Ee = console.group, we = console.groupCollapsed, Te = console.groupEnd; + var e = { + configurable: !0, + enumerable: !0, + value: s, + writable: !0 + }; + Object.defineProperties(console, { + info: e, + log: e, + warn: e, + error: e, + group: e, + groupCollapsed: e, + groupEnd: e + }); + } + K++; + } + function a() { + if (K--, K === 0) { + var e = { configurable: !0, enumerable: !0, writable: !0 }; + Object.defineProperties(console, { + log: O({}, e, { value: ve }), + info: O({}, e, { value: ye }), + warn: O({}, e, { value: ke }), + error: O({}, e, { value: Ce }), + group: O({}, e, { value: Ee }), + groupCollapsed: O({}, e, { value: we }), + groupEnd: O({}, e, { value: Te }) + }); + } + 0 > K && console.error( + "disabledDepth fell below zero. This is a bug in React. Please file an issue." + ); + } + function d(e) { + if (ie === void 0) + try { + throw Error(); + } catch (i) { + var c = i.stack.trim().match(/\n( *(at )?)/); + ie = c && c[1] || "", Se = -1 < i.stack.indexOf(` + at`) ? " ()" : -1 < i.stack.indexOf("@") ? "@unknown:0:0" : ""; + } + return ` +` + ie + e + Se; + } + function f(e, c) { + if (!e || le) return ""; + var i = de.get(e); + if (i !== void 0) return i; + le = !0, i = Error.prepareStackTrace, Error.prepareStackTrace = void 0; + var u = null; + u = N.H, N.H = null, o(); + try { + var y = { + DetermineComponentFrameRoot: function() { + try { + if (c) { + var A = function() { + throw Error(); + }; + if (Object.defineProperty(A.prototype, "props", { + set: function() { + throw Error(); + } + }), typeof Reflect == "object" && Reflect.construct) { + try { + Reflect.construct(A, []); + } catch (_) { + var F = _; + } + Reflect.construct(e, [], A); + } else { + try { + A.call(); + } catch (_) { + F = _; + } + e.call(A.prototype); + } + } else { + try { + throw Error(); + } catch (_) { + F = _; + } + (A = e()) && typeof A.catch == "function" && A.catch(function() { + }); + } + } catch (_) { + if (_ && F && typeof _.stack == "string") + return [_.stack, F.stack]; + } + return [null, null]; + } + }; + y.DetermineComponentFrameRoot.displayName = "DetermineComponentFrameRoot"; + var g = Object.getOwnPropertyDescriptor( + y.DetermineComponentFrameRoot, + "name" + ); + g && g.configurable && Object.defineProperty( + y.DetermineComponentFrameRoot, + "name", + { value: "DetermineComponentFrameRoot" } + ); + var l = y.DetermineComponentFrameRoot(), S = l[0], L = l[1]; + if (S && L) { + var k = S.split(` +`), M = L.split(` +`); + for (l = g = 0; g < k.length && !k[g].includes( + "DetermineComponentFrameRoot" + ); ) + g++; + for (; l < M.length && !M[l].includes( + "DetermineComponentFrameRoot" + ); ) + l++; + if (g === k.length || l === M.length) + for (g = k.length - 1, l = M.length - 1; 1 <= g && 0 <= l && k[g] !== M[l]; ) + l--; + for (; 1 <= g && 0 <= l; g--, l--) + if (k[g] !== M[l]) { + if (g !== 1 || l !== 1) + do + if (g--, l--, 0 > l || k[g] !== M[l]) { + var H = ` +` + k[g].replace( + " at new ", + " at " + ); + return e.displayName && H.includes("") && (H = H.replace("", e.displayName)), typeof e == "function" && de.set(e, H), H; + } + while (1 <= g && 0 <= l); + break; + } + } + } finally { + le = !1, N.H = u, a(), Error.prepareStackTrace = i; + } + return k = (k = e ? e.displayName || e.name : "") ? d(k) : "", typeof e == "function" && de.set(e, k), k; + } + function p(e) { + if (e == null) return ""; + if (typeof e == "function") { + var c = e.prototype; + return f( + e, + !(!c || !c.isReactComponent) + ); + } + if (typeof e == "string") return d(e); + switch (e) { + case oe: + return d("Suspense"); + case re: + return d("SuspenseList"); + } + if (typeof e == "object") + switch (e.$$typeof) { + case ne: + return e = f(e.render, !1), e; + case ae: + return p(e.type); + case se: + c = e._payload, e = e._init; + try { + return p(e(c)); + } catch { + } + } + return ""; + } + function m() { + var e = N.A; + return e === null ? null : e.getOwner(); + } + function v(e) { + if (pe.call(e, "key")) { + var c = Object.getOwnPropertyDescriptor(e, "key").get; + if (c && c.isReactWarning) return !1; + } + return e.key !== void 0; + } + function x(e, c) { + function i() { + _e || (_e = !0, console.error( + "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", + c + )); + } + i.isReactWarning = !0, Object.defineProperty(e, "key", { + get: i, + configurable: !0 + }); + } + function E() { + var e = n(this.type); + return je[e] || (je[e] = !0, console.error( + "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release." + )), e = this.props.ref, e !== void 0 ? e : null; + } + function T(e, c, i, u, y, g) { + return i = g.ref, e = { + $$typeof: Y, + type: e, + key: c, + props: g, + _owner: y + }, (i !== void 0 ? i : null) !== null ? Object.defineProperty(e, "ref", { + enumerable: !1, + get: E + }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", { + configurable: !1, + enumerable: !1, + writable: !0, + value: 0 + }), Object.defineProperty(e, "_debugInfo", { + configurable: !1, + enumerable: !1, + writable: !0, + value: null + }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e; + } + function P(e, c, i, u, y, g) { + if (typeof e == "string" || typeof e == "function" || e === W || e === C || e === X || e === oe || e === re || e === Ye || typeof e == "object" && e !== null && (e.$$typeof === se || e.$$typeof === ae || e.$$typeof === R || e.$$typeof === z || e.$$typeof === ne || e.$$typeof === Ke || e.getModuleId !== void 0)) { + var l = c.children; + if (l !== void 0) + if (u) + if (ce(l)) { + for (u = 0; u < l.length; u++) + U(l[u], e); + Object.freeze && Object.freeze(l); + } else + console.error( + "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead." + ); + else U(l, e); + } else + l = "", (e === void 0 || typeof e == "object" && e !== null && Object.keys(e).length === 0) && (l += " You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports."), e === null ? u = "null" : ce(e) ? u = "array" : e !== void 0 && e.$$typeof === Y ? (u = "<" + (n(e.type) || "Unknown") + " />", l = " Did you accidentally export a JSX literal instead of a component?") : u = typeof e, console.error( + "React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", + u, + l + ); + if (pe.call(c, "key")) { + l = n(e); + var S = Object.keys(c).filter(function(k) { + return k !== "key"; + }); + u = 0 < S.length ? "{key: someKey, " + S.join(": ..., ") + ": ...}" : "{key: someKey}", Ae[l + u] || (S = 0 < S.length ? "{" + S.join(": ..., ") + ": ...}" : "{}", console.error( + `A props object containing a "key" prop is being spread into JSX: + let props = %s; + <%s {...props} /> +React keys must be passed directly to JSX without using spread: + let props = %s; + <%s key={someKey} {...props} />`, + u, + l, + S, + l + ), Ae[l + u] = !0); + } + if (l = null, i !== void 0 && (r(i), l = "" + i), v(c) && (r(c.key), l = "" + c.key), "key" in c) { + i = {}; + for (var L in c) + L !== "key" && (i[L] = c[L]); + } else i = c; + return l && x( + i, + typeof e == "function" ? e.displayName || e.name || "Unknown" : e + ), T(e, l, g, y, m(), i); + } + function U(e, c) { + if (typeof e == "object" && e && e.$$typeof !== He) { + if (ce(e)) + for (var i = 0; i < e.length; i++) { + var u = e[i]; + I(u) && J(u, c); + } + else if (I(e)) + e._store && (e._store.validated = 1); + else if (e === null || typeof e != "object" ? i = null : (i = be && e[be] || e["@@iterator"], i = typeof i == "function" ? i : null), typeof i == "function" && i !== e.entries && (i = i.call(e), i !== e)) + for (; !(e = i.next()).done; ) + I(e.value) && J(e.value, c); + } + } + function I(e) { + return typeof e == "object" && e !== null && e.$$typeof === Y; + } + function J(e, c) { + if (e._store && !e._store.validated && e.key == null && (e._store.validated = 1, c = q(c), !Re[c])) { + Re[c] = !0; + var i = ""; + e && e._owner != null && e._owner !== m() && (i = null, typeof e._owner.tag == "number" ? i = n(e._owner.type) : typeof e._owner.name == "string" && (i = e._owner.name), i = " It was passed a child from " + i + "."); + var u = N.getCurrentStack; + N.getCurrentStack = function() { + var y = p(e.type); + return u && (y += u() || ""), y; + }, console.error( + 'Each child in a list should have a unique "key" prop.%s%s See https://react.dev/link/warning-keys for more information.', + c, + i + ), N.getCurrentStack = u; + } + } + function q(e) { + var c = "", i = m(); + return i && (i = n(i.type)) && (c = ` + +Check the render method of \`` + i + "`."), c || (e = n(e)) && (c = ` + +Check the top-level render call using <` + e + ">."), c; + } + var $ = Ve, Y = Symbol.for("react.transitional.element"), te = Symbol.for("react.portal"), W = Symbol.for("react.fragment"), X = Symbol.for("react.strict_mode"), C = Symbol.for("react.profiler"), z = Symbol.for("react.consumer"), R = Symbol.for("react.context"), ne = Symbol.for("react.forward_ref"), oe = Symbol.for("react.suspense"), re = Symbol.for("react.suspense_list"), ae = Symbol.for("react.memo"), se = Symbol.for("react.lazy"), Ye = Symbol.for("react.offscreen"), be = Symbol.iterator, We = Symbol.for("react.client.reference"), N = $.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, pe = Object.prototype.hasOwnProperty, O = Object.assign, Ke = Symbol.for("react.client.reference"), ce = Array.isArray, K = 0, ve, ye, ke, Ce, Ee, we, Te; + s.__reactDisabledLog = !0; + var ie, Se, le = !1, de = new (typeof WeakMap == "function" ? WeakMap : Map)(), He = Symbol.for("react.client.reference"), _e, je = {}, Ae = {}, Re = {}; + G.Fragment = W, G.jsx = function(e, c, i, u, y) { + return P(e, c, i, !1, u, y); + }, G.jsxs = function(e, c, i, u, y) { + return P(e, c, i, !0, u, y); + }; + }()), G; +} +var Me; +function gt() { + return Me || (Me = 1, process.env.NODE_ENV === "production" ? Q.exports = mt() : Q.exports = ht()), Q.exports; +} +var b = gt(); +const xt = (n, t) => { + n.setRangeText( + t, + n.selectionStart || 0, + n.selectionEnd || 0, + "select" + ); +}; +function bt(n) { + const t = []; + for (const r in n) + n.hasOwnProperty.call(n, r) && n[r]().handleKeyCommand && t.push(r); + return t; +} +class pt { + refTextarea; + constructor(t) { + this.refTextarea = t; + } + replaceSelection = (t) => { + const r = this.refTextarea.current; + return xt(r, t), Z(r); + }; + setSelectionRange = (t) => { + const r = this.refTextarea.current; + return r.focus(), r.selectionStart = t.start, r.selectionEnd = t.end, Z(r); + }; + getState = () => { + const t = this.refTextarea.current; + return Z(t); + }; +} +const Z = (n) => ({ + selection: { + start: n.selectionStart, + end: n.selectionEnd + }, + text: n.value, + selectedText: n.value.slice( + n.selectionStart, + n.selectionEnd + ) +}); +class vt { + setText; + refTextarea; + textApi; + commandMap; + /** + * Names of commands that can be activated by the keyboard + */ + keyActivatedCommands; + /** + * Indicates whether there is a command currently executing + */ + isExecuting = !1; + pasteOptions; + constructor({ + setText: t, + customCommands: r, + refTextarea: s, + pasteOptions: o + }) { + if (o && !o.saveImage) + throw new Error("paste options are incomplete. saveImage are required "); + this.commandMap = { ...Le(), ...r || {} }, this.pasteOptions = o, this.keyActivatedCommands = bt(r), this.refTextarea = s, this.textApi = new pt(s), this.setText = t; + } + getCommand = (t) => { + const r = this.commandMap[t]; + if (!r) + throw new Error(`Cannot execute command. Command not found: ${t}`); + return r(); + }; + /** + * Tries to find a command the wants to handle the keyboard event. + * If a command is found, it is executed and the function returns + */ + handleKeyCommand = async (t) => { + for (const r of this.keyActivatedCommands) + if (this.getCommand(r)?.handleKeyCommand?.(t)) + return await this.executeCommand(r), !0; + return !1; + }; + executeCommand = async (t, r) => { + if (this.isExecuting) + return; + this.isExecuting = !0; + const s = this.refTextarea.current, o = Z(s); + await this.getCommand(t).execute({ + setText: this.setText, + initialState: o, + textApi: this.textApi, + context: r + }), this.isExecuting = !1; + }; + /** + * Executes the paste command + */ + executePasteCommand = async (t) => { + if (this.pasteOptions) + return this.executeCommand( + this.pasteOptions.command || fe(), + { + pasteOptions: this.pasteOptions, + event: t + } + ); + }; + /** + * Executes the drop command + */ + executeDropCommand = async (t) => { + if (this.pasteOptions) + return this.executeCommand( + this.pasteOptions.command || fe(), + { + pasteOptions: this.pasteOptions, + event: t + } + ); + }; + /** + * Executes the "select image" command + */ + executeSelectImageCommand = async (t) => { + if (this.pasteOptions) + return this.executeCommand( + this.pasteOptions.command || fe(), + { + pasteOptions: this.pasteOptions, + event: t + } + ); + }; + /** + * Returns a command by name + * @param name + */ + getCommandByName = (t) => this.commandMap[t]; +} +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const yt = (n) => n.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), Be = (...n) => n.filter((t, r, s) => !!t && t.trim() !== "" && s.indexOf(t) === r).join(" ").trim(); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +var kt = { + xmlns: "http://www.w3.org/2000/svg", + width: 24, + height: 24, + viewBox: "0 0 24 24", + fill: "none", + stroke: "currentColor", + strokeWidth: 2, + strokeLinecap: "round", + strokeLinejoin: "round" +}; +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const Ct = ee( + ({ + color: n = "currentColor", + size: t = 24, + strokeWidth: r = 2, + absoluteStrokeWidth: s, + className: o = "", + children: a, + iconNode: d, + ...f + }, p) => D( + "svg", + { + ref: p, + ...kt, + width: t, + height: t, + stroke: n, + strokeWidth: s ? Number(r) * 24 / Number(t) : r, + className: Be("lucide", o), + ...f + }, + [ + ...d.map(([m, v]) => D(m, v)), + ...Array.isArray(a) ? a : [a] + ] + ) +); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const w = (n, t) => { + const r = ee( + ({ className: s, ...o }, a) => D(Ct, { + ref: a, + iconNode: t, + className: Be(`lucide-${yt(n)}`, s), + ...o + }) + ); + return r.displayName = `${n}`, r; +}; +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const Et = w("Bold", [ + [ + "path", + { d: "M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8", key: "mg9rjx" } + ] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const wt = w("CodeXml", [ + ["path", { d: "m18 16 4-4-4-4", key: "1inbqp" }], + ["path", { d: "m6 8-4 4 4 4", key: "15zrgr" }], + ["path", { d: "m14.5 4-5 16", key: "e7oirm" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const Tt = w("Heading", [ + ["path", { d: "M6 12h12", key: "8npq4p" }], + ["path", { d: "M6 20V4", key: "1w1bmo" }], + ["path", { d: "M18 20V4", key: "o2hl4u" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const St = w("Image", [ + ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }], + ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }], + ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const _t = w("Italic", [ + ["line", { x1: "19", x2: "10", y1: "4", y2: "4", key: "15jd3p" }], + ["line", { x1: "14", x2: "5", y1: "20", y2: "20", key: "bu0au3" }], + ["line", { x1: "15", x2: "9", y1: "4", y2: "20", key: "uljnxc" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const jt = w("Link", [ + ["path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71", key: "1cjeqo" }], + ["path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71", key: "19qd67" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const At = w("ListChecks", [ + ["path", { d: "m3 17 2 2 4-4", key: "1jhpwq" }], + ["path", { d: "m3 7 2 2 4-4", key: "1obspn" }], + ["path", { d: "M13 6h8", key: "15sg57" }], + ["path", { d: "M13 12h8", key: "h98zly" }], + ["path", { d: "M13 18h8", key: "oe0vm4" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const Rt = w("ListOrdered", [ + ["path", { d: "M10 12h11", key: "6m4ad9" }], + ["path", { d: "M10 18h11", key: "11hvi2" }], + ["path", { d: "M10 6h11", key: "c7qv1k" }], + ["path", { d: "M4 10h2", key: "16xx2s" }], + ["path", { d: "M4 6h1v4", key: "cnovpq" }], + ["path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1", key: "m9a95d" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const Nt = w("List", [ + ["path", { d: "M3 12h.01", key: "nlz23k" }], + ["path", { d: "M3 18h.01", key: "1tta3j" }], + ["path", { d: "M3 6h.01", key: "1rqtza" }], + ["path", { d: "M8 12h13", key: "1za7za" }], + ["path", { d: "M8 18h13", key: "1lx6n3" }], + ["path", { d: "M8 6h13", key: "ik3vkj" }] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const Ot = w("Quote", [ + [ + "path", + { + d: "M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z", + key: "rib7q0" + } + ], + [ + "path", + { + d: "M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z", + key: "1ymkrd" + } + ] +]); +/** + * @license lucide-react v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */ +const Mt = w("Strikethrough", [ + ["path", { d: "M16 4H9a3 3 0 0 0-2.83 4", key: "43sutm" }], + ["path", { d: "M14 12a4 4 0 0 1 0 8H6", key: "nlfj13" }], + ["line", { x1: "4", x2: "20", y1: "12", y2: "12", key: "1e0a9i" }] +]), Pt = "fc-mde__main_e76010f9ac3f69e6", $t = { + main: Pt +}, zt = (n) => /* @__PURE__ */ b.jsx("div", { "data-fc-mde-svg-icon-container": !0, ...n }), Lt = ({ icon: n }) => { + const t = { + header: Tt, + bold: Et, + italic: _t, + strikethrough: Mt, + code: wt, + quote: Ot, + unorderedList: Rt, + orderedList: Nt, + checkedList: At, + link: jt, + image: St + }[n] ?? null; + return t ? /* @__PURE__ */ b.jsx(zt, { children: /* @__PURE__ */ b.jsx(t, { className: $t.main, "data-fc-mde-svg-icon": !0 }) }) : null; +}, Bt = "fc-mde__content_59ee8347a45e0596", Pe = { + content: Bt +}, Ie = ee( + ({ markdown: n, generateMarkdownPreview: t, loadingPreview: r }, s) => { + const [o, a] = ue(!0), [d, f] = ue(""), [p, m] = ue(""), v = me(async () => { + f(await t(n)), a(!1); + }, [t, n]); + Ge(() => { + n !== p && (v(), m(n)); + }, [p, n, v]); + let x = null; + return o ? x = /* @__PURE__ */ b.jsx("div", { className: Pe.content, "data-fc-mde-preview-content": !0, children: r }) : x = /* @__PURE__ */ b.jsx( + "div", + { + className: Pe.content, + ref: s, + "data-fc-mde-preview-content": !0, + dangerouslySetInnerHTML: { __html: d } + } + ), /* @__PURE__ */ b.jsx("div", { "data-mde-preview": !0, "data-loading": o || void 0, children: x }); + } +); +Ie.displayName = "MdePreview"; +const It = "fc-mde__container_5d480c472a769b14", qt = "fc-mde__main_bbe7a060507c7387", $e = { + container: It, + main: qt +}, qe = ee( + ({ value: n, setValue: t, textareaComponent: r, onKeyCommand: s, ...o }, a) => { + const d = r || "textarea", f = me((m) => { + m.preventDefault(), (m.clipboardData.files ?? []).length; + }, []), p = me( + (m) => { + t(m.target.value); + }, + [t] + ); + return /* @__PURE__ */ b.jsx("div", { className: $e.container, "data-fc-mde-textarea-container": !0, children: /* @__PURE__ */ b.jsx( + d, + { + ref: a, + className: $e.main, + value: n, + onChange: p, + onKeyDown: s, + onPaste: f, + "data-fc-mde-textarea": !0, + ...o + } + ) }); + } +); +qe.displayName = "MdeTextarea"; +const Yt = "fc-mde__tab_707475e156219802", Wt = "fc-mde__tabButton_5a17ac662ec07934", Kt = "fc-mde__header_1d136c3d982ffdcc", Ht = "fc-mde__btnGroup_b384efee5a15e109", Vt = "fc-mde__btn_a61d3b8445301110", B = { + tab: Yt, + tabButton: Wt, + header: Kt, + btnGroup: Ht, + btn: Vt +}, Gt = { + tabIndex: -1 +}, Ut = ({ + buttonComponentClass: n, + buttonContent: t, + buttonProps: r, + onClick: s, + readOnly: o, + name: a +}) => { + const d = { ...Gt, ...r || {} }, f = n || "button"; + return /* @__PURE__ */ b.jsx("div", { className: B.btn, "data-fc-mde-toolbar-button": !0, children: D( + f, + { + "data-fc-mde-toolbar-button-item": !0, + "data-name": a, + ...d, + onClick: s, + disabled: o, + type: "button" + }, + t + ) }); +}, Jt = ({ + hidden: n, + children: t +}) => /* @__PURE__ */ b.jsx( + "div", + { + className: B.btnGroup, + "data-fc-mde-toolbar-button-group": !0, + "data-hidden": n || void 0, + children: t + } +), Xt = ({ + onTabChange: n, + buttons: t, + onCommand: r, + readOnly: s, + disablePreview: o, + writeButtonProps: a, + previewButtonProps: d, + tab: f, + buttonProps: p +}) => { + const m = (x, E) => { + x.preventDefault(), n(E); + }; + if (!t?.length) + return null; + const v = /* @__PURE__ */ b.jsxs("div", { className: B.tab, "data-fc-mde-tab": !0, children: [ + /* @__PURE__ */ b.jsx( + "button", + { + type: "button", + className: B.tabButton, + "data-fc-mde-tab-button": !0, + onClick: (x) => m(x, "write"), + "data-active": f === "write" || void 0, + ...a, + children: h.gettext("Write") + } + ), + /* @__PURE__ */ b.jsx( + "button", + { + type: "button", + className: B.tabButton, + "data-fc-mde-tab-button": !0, + onClick: (x) => m(x, "preview"), + "data-active": f === "preview" || void 0, + ...d, + children: h.gettext("Preview") + } + ) + ] }); + return /* @__PURE__ */ b.jsxs("div", { className: B.header, "data-fc-mde-header": !0, children: [ + o || v, + t.map((x, E) => /* @__PURE__ */ b.jsx(Jt, { hidden: f === "preview", children: x.map((T, P) => /* @__PURE__ */ b.jsx( + Ut, + { + name: T.commandName, + buttonContent: T.buttonContent, + buttonProps: { ...p || {}, ...T.buttonProps }, + onClick: () => r(T.commandName), + readOnly: s, + buttonComponentClass: T.buttonComponentClass + }, + P + )) }, E)) + ] }); +}, Ft = "fc-mde__main_c29a242caf055ec0", Qt = "fc-mde__container_8e4c12095dec4180", ze = { + main: Ft, + container: Qt +}, Dt = ({ + setText: n, + refTextarea: t, + commands: r = Le(), + toolbarCommands: s = ft(), + getIcon: o = (q) => /* @__PURE__ */ b.jsx(Lt, { icon: q }), + readOnly: a = !1, + selectedTab: d = "write", + disablePreview: f = !1, + paste: p, + onTabChange: m, + loadingPreview: v, + text: x, + generateMarkdownPreview: E, + textareaComponent: T, + commandButtons: P, + writeButton: U, + previewButton: I, + textareaProps: J +}) => { + const q = Ue(null), $ = new vt({ + setText: n, + customCommands: r, + refTextarea: t, + pasteOptions: p + }), Y = async (C) => { + p?.saveImage && await $.executePasteCommand(C); + }, te = (C) => { + m(C); + }, W = async (C) => { + await $.executeCommand(C); + }, X = s.map((C) => C.map((z) => { + const R = $.getCommand(z); + return { + commandName: z, + buttonContent: R.icon ? R.icon(o) : o(z), + buttonProps: R.buttonProps, + buttonComponentClass: R.buttonComponentClass + }; + })).filter((C) => C); + return /* @__PURE__ */ b.jsxs("div", { className: ze.main, "data-fc-mde": !0, children: [ + /* @__PURE__ */ b.jsx( + Xt, + { + buttons: X, + onCommand: W, + onTabChange: te, + tab: d, + readOnly: a, + disablePreview: f, + buttonProps: P, + writeButtonProps: U, + previewButtonProps: I + } + ), + /* @__PURE__ */ b.jsx( + "div", + { + className: ze.container, + "data-fc-mde-container": !0, + "data-hidden": d === "preview" || void 0, + children: /* @__PURE__ */ b.jsx( + qe, + { + ref: t, + value: x, + setValue: n, + textareaComponent: T, + onKeyCommand: $.handleKeyCommand, + onPaste: Y, + ...J + } + ) + } + ), + d !== "write" && /* @__PURE__ */ b.jsx( + Ie, + { + ref: q, + loadingPreview: v, + generateMarkdownPreview: E, + markdown: x + } + ) + ] }); +}; +export { + Dt as Mde, + Le as getDefaultCommandMap, + ft as getDefaultToolbarCommands, + j as selectWord +}; diff --git a/dist/types/commands/command-orchestrator.d.ts b/dist/types/commands/command-orchestrator.d.ts new file mode 100644 index 00000000..5542583a --- /dev/null +++ b/dist/types/commands/command-orchestrator.d.ts @@ -0,0 +1,59 @@ +import { ChangeEvent, KeyboardEvent, RefObject } from 'react'; +import { MdeTextApi, MdeTextState } from '../typings/command-options'; +import { MdeSelection } from '../typings/selection'; +import { MdeCommandContext, MdeCommandMapProps, MdeCommandProps, MdePasteOptions } from './command'; +export declare class MdeTextAreaTextApi implements MdeTextApi { + private readonly refTextarea; + constructor(refTextarea: RefObject); + replaceSelection: (text: string) => MdeTextState; + setSelectionRange: (selection: MdeSelection) => MdeTextState; + getState: () => MdeTextState; +} +export declare const getStateFromTextArea: (textarea: HTMLTextAreaElement) => MdeTextState; +interface MdeCommandOrchestratorProps { + setText: (text: string) => void; + customCommands: MdeCommandMapProps; + refTextarea: RefObject; + pasteOptions?: MdePasteOptions; +} +export declare class MdeCommandOrchestrator { + private readonly setText; + private readonly refTextarea; + private readonly textApi; + private readonly commandMap; + /** + * Names of commands that can be activated by the keyboard + */ + private keyActivatedCommands; + /** + * Indicates whether there is a command currently executing + */ + private isExecuting; + private readonly pasteOptions?; + constructor({ setText, customCommands, refTextarea, pasteOptions, }: MdeCommandOrchestratorProps); + getCommand: (name: string) => MdeCommandProps; + /** + * Tries to find a command the wants to handle the keyboard event. + * If a command is found, it is executed and the function returns + */ + handleKeyCommand: (e: KeyboardEvent) => Promise; + executeCommand: (commandName: string, context?: MdeCommandContext) => Promise; + /** + * Executes the paste command + */ + executePasteCommand: (event: ClipboardEvent) => Promise; + /** + * Executes the drop command + */ + executeDropCommand: (event: DragEvent) => Promise; + /** + * Executes the "select image" command + */ + executeSelectImageCommand: (event: ChangeEvent) => Promise; + /** + * Returns a command by name + * @param name + */ + getCommandByName: (name: string) => CallableFunction; +} +export {}; diff --git a/dist/types/commands/command-utils.d.ts b/dist/types/commands/command-utils.d.ts new file mode 100644 index 00000000..73a1ffc9 --- /dev/null +++ b/dist/types/commands/command-utils.d.ts @@ -0,0 +1,7 @@ +import { MdeCommandMapProps } from './command'; +/** + * Returns a flat array of commands that can be activated by the keyboard. + * When keydowns happen, these commands 'handleKeyCommand' will be executed, in this order, + * and the first that returns true will be executed. + */ +export declare function extractKeyActivatedCommands(commandMap: MdeCommandMapProps): string[]; diff --git a/dist/types/commands/command.d.ts b/dist/types/commands/command.d.ts new file mode 100644 index 00000000..14cdfbf3 --- /dev/null +++ b/dist/types/commands/command.d.ts @@ -0,0 +1,53 @@ +import { ChangeEvent, ComponentClass, ReactNode, ButtonHTMLAttributes } from 'react'; +import { MdeTextApi, MdeTextState } from '../typings/command-options'; +import { MdeHandleKeyCommand } from '../typings/function-types'; +export type MdeGetIcon = (iconName: string) => ReactNode; +export interface MdeExecuteOptions { + setText: (text: string) => void; + initialState: MdeTextState; + textApi: MdeTextApi; + context?: MdeCommandContext; +} +export interface MdeCommandProps { + buttonComponentClass?: ComponentClass | string; + icon?: (getIconFromProvider: MdeGetIcon) => ReactNode; + buttonProps?: ButtonHTMLAttributes; + execute: (options: MdeExecuteOptions) => void | Promise; + /** + * On every key-down, "handleKeyCommand", if defined, will be executed for every command. + * The first "HandleKeyCommand" that returns true will cause the command to be executed. + * "HandleKeyCommand" for subsequent commands will not be executed after the first one returns true. + */ + handleKeyCommand?: MdeHandleKeyCommand; +} +export interface MdeCommandContext { + type: string; +} +export interface MdePasteCommandContext extends MdeCommandContext { + type: 'paste'; + event: ClipboardEvent | DragEvent | ChangeEvent; + pasteOptions: MdePasteOptions; +} +export type MdeToolbarCommands = string[][]; +export type MdeCommandMapProps = Record; +export interface MdePasteOptions { + /** + * Generator function to save images pasted. + * This generator should 1) Yield the image URL. 2) Return true if the save was successful or false, otherwise + */ + saveImage: MdeSaveImageHandler; + /** + * Command to execute on paste command + */ + command?: string; + /** + * The accept attribute specifies a filter for what file types the user can pick from the file input dialog box. + */ + accept?: string; + /** + * When present, it specifies that the user is allowed to enter more than one value in the file input dialog box. + * By default is set to true + */ + multiple?: boolean; +} +export type MdeSaveImageHandler = (data: ArrayBuffer, file: Blob) => AsyncGenerator; diff --git a/dist/types/commands/default-commands/bold.d.ts b/dist/types/commands/default-commands/bold.d.ts new file mode 100644 index 00000000..2af333b8 --- /dev/null +++ b/dist/types/commands/default-commands/bold.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const boldCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/code.d.ts b/dist/types/commands/default-commands/code.d.ts new file mode 100644 index 00000000..c936a417 --- /dev/null +++ b/dist/types/commands/default-commands/code.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const codeCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/defaults.d.ts b/dist/types/commands/default-commands/defaults.d.ts new file mode 100644 index 00000000..0ca429e0 --- /dev/null +++ b/dist/types/commands/default-commands/defaults.d.ts @@ -0,0 +1,4 @@ +import { MdeCommandMapProps, MdeToolbarCommands } from '../command'; +export declare const getDefaultToolbarCommands: () => MdeToolbarCommands; +export declare const getDefaultCommandMap: () => MdeCommandMapProps; +export declare function getDefaultSaveImageCommandName(): string; diff --git a/dist/types/commands/default-commands/header.d.ts b/dist/types/commands/default-commands/header.d.ts new file mode 100644 index 00000000..68a870eb --- /dev/null +++ b/dist/types/commands/default-commands/header.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const headerCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/image.d.ts b/dist/types/commands/default-commands/image.d.ts new file mode 100644 index 00000000..cfeea2cb --- /dev/null +++ b/dist/types/commands/default-commands/image.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const imageCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/italic.d.ts b/dist/types/commands/default-commands/italic.d.ts new file mode 100644 index 00000000..d5f07219 --- /dev/null +++ b/dist/types/commands/default-commands/italic.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const italicCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/link.d.ts b/dist/types/commands/default-commands/link.d.ts new file mode 100644 index 00000000..a029b111 --- /dev/null +++ b/dist/types/commands/default-commands/link.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const linkCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/list.d.ts b/dist/types/commands/default-commands/list.d.ts new file mode 100644 index 00000000..e7ce49a4 --- /dev/null +++ b/dist/types/commands/default-commands/list.d.ts @@ -0,0 +1,14 @@ +import { MdeTextApi, MdeTextState } from '../../typings/command-options'; +import { MdeCommandProps } from '../command'; +export type AlterLineFunction = (line: string, index: number) => string; +/** + * Inserts insertionString before each line + */ +export declare function insertBeforeEachLine(selectedText: string, insertBefore: string | AlterLineFunction): { + modifiedText: string; + insertionLength: number; +}; +export declare const makeList: (state0: MdeTextState, api: MdeTextApi, insertBefore: string | AlterLineFunction) => MdeTextState; +export declare const unorderedListCommand: () => MdeCommandProps; +export declare const orderedListCommand: () => MdeCommandProps; +export declare const checkedListCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/quote.d.ts b/dist/types/commands/default-commands/quote.d.ts new file mode 100644 index 00000000..94be33b6 --- /dev/null +++ b/dist/types/commands/default-commands/quote.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const quoteCommand: () => MdeCommandProps; diff --git a/dist/types/commands/default-commands/strike-through.d.ts b/dist/types/commands/default-commands/strike-through.d.ts new file mode 100644 index 00000000..1d7f51ea --- /dev/null +++ b/dist/types/commands/default-commands/strike-through.d.ts @@ -0,0 +1,2 @@ +import { MdeCommandProps } from '../command'; +export declare const strikeThroughCommand: () => MdeCommandProps; diff --git a/dist/types/components/bootstrap/index.d.ts b/dist/types/components/bootstrap/index.d.ts new file mode 100644 index 00000000..5b692d34 --- /dev/null +++ b/dist/types/components/bootstrap/index.d.ts @@ -0,0 +1,3 @@ +import { FC } from 'react'; +import { MdeProps } from './typings'; +export declare const Mde: FC; diff --git a/dist/types/components/bootstrap/typings.d.ts b/dist/types/components/bootstrap/typings.d.ts new file mode 100644 index 00000000..5ace414f --- /dev/null +++ b/dist/types/components/bootstrap/typings.d.ts @@ -0,0 +1,33 @@ +import { ButtonHTMLAttributes, FC, ReactNode, RefObject, TextareaHTMLAttributes } from 'react'; +import { MdeCommandMapProps, MdeGetIcon, MdePasteOptions } from '../../commands/command'; +import { MdeGenerateMarkdownPreview } from '../../typings/function-types'; +import { MdeTabProps } from '../toolbar/typings'; +export interface MdeProps { + text: string; + setText: (text: string) => void; + selectedTab: MdeTabProps; + onTabChange: (tab: MdeTabProps) => void; + generateMarkdownPreview: MdeGenerateMarkdownPreview; + refTextarea: RefObject; + toolbarCommands?: string[][]; + commands?: MdeCommandMapProps; + getIcon?: MdeGetIcon; + loadingPreview?: ReactNode; + readOnly?: boolean; + disablePreview?: boolean; + writeButton?: ButtonHTMLAttributes; + previewButton?: ButtonHTMLAttributes; + commandButtons?: ButtonHTMLAttributes; + textareaProps?: TextareaHTMLAttributes; + paste?: MdePasteOptions; + /** + * Custom textarea component. "textareaComponent" can be any React component which + * props are a subset of the props of an HTMLTextAreaElement + */ + textareaComponent?: FC; + /** + * Custom toolbar button component. "toolbarButtonComponent" can be any React component which + * props are a subset of the props of an HTMLButtonElement + */ + toolbarButtonComponent?: FC; +} diff --git a/dist/types/components/icon/svg-icon.d.ts b/dist/types/components/icon/svg-icon.d.ts new file mode 100644 index 00000000..18789259 --- /dev/null +++ b/dist/types/components/icon/svg-icon.d.ts @@ -0,0 +1,3 @@ +import { FC } from 'react'; +import { MdeIconProviderProps } from './typings'; +export declare const MdeSvgIcon: FC; diff --git a/dist/types/components/icon/typings.d.ts b/dist/types/components/icon/typings.d.ts new file mode 100644 index 00000000..01aae471 --- /dev/null +++ b/dist/types/components/icon/typings.d.ts @@ -0,0 +1,3 @@ +export interface MdeIconProviderProps { + icon: string; +} diff --git a/dist/types/components/language/data.json.d.ts b/dist/types/components/language/data.json.d.ts new file mode 100644 index 00000000..243dbcc7 --- /dev/null +++ b/dist/types/components/language/data.json.d.ts @@ -0,0 +1,56 @@ +declare const _default: { + "Add a link": { + "zh": "附加链接", + "zh-CN": "附加链接" + }, + "Add bold text": { + "zh": "附加粗体", + "zh-CN": "附加粗体" + }, + "Add checked list": { + "zh": "附加任务列表", + "zh-CN": "附加任务列表" + }, + "Add header": { + "zh": "附加标题", + "zh-CN": "附加标题" + }, + "Add image": { + "zh": "附加图像", + "zh-CN": "附加图像" + }, + "Add italic text": { + "zh": "附加斜体", + "zh-CN": "附加斜体" + }, + "Add ordered list": { + "zh": "附加有序列表", + "zh-CN": "附加有序列表" + }, + "Add strikethrough text": { + "zh": "附加删除线", + "zh-CN": "附加删除线" + }, + "Add unordered list": { + "zh": "附加无序列表", + "zh-CN": "附加无序列表" + }, + "Insert a quote": { + "zh": "附加引用", + "zh-CN": "附加引用" + }, + "Insert code": { + "zh": "附加代码", + "zh-CN": "附加代码" + }, + "Preview": { + "zh": "预览", + "zh-CN": "预览" + }, + "Write": { + "zh": "编辑", + "zh-CN": "编辑" + } +}; + +export default _default; diff --git a/dist/types/components/language/index.d.ts b/dist/types/components/language/index.d.ts new file mode 100644 index 00000000..858bf105 --- /dev/null +++ b/dist/types/components/language/index.d.ts @@ -0,0 +1,7 @@ +declare class Main { + private langId; + setLangId: (langId: string) => void; + gettext: (text: string, context?: string) => string; +} +export declare const MdeLanguage: Main; +export {}; diff --git a/dist/types/components/language/typings.d.ts b/dist/types/components/language/typings.d.ts new file mode 100644 index 00000000..c57fbf86 --- /dev/null +++ b/dist/types/components/language/typings.d.ts @@ -0,0 +1 @@ +export type MdeLangProps = 'zh' | 'zh-cn'; diff --git a/dist/types/components/preview/index.d.ts b/dist/types/components/preview/index.d.ts new file mode 100644 index 00000000..a00a26ab --- /dev/null +++ b/dist/types/components/preview/index.d.ts @@ -0,0 +1,2 @@ +import { MdePreviewProps } from './typings'; +export declare const MdePreview: import('react').ForwardRefExoticComponent>; diff --git a/dist/types/components/preview/typings.d.ts b/dist/types/components/preview/typings.d.ts new file mode 100644 index 00000000..4c0a8839 --- /dev/null +++ b/dist/types/components/preview/typings.d.ts @@ -0,0 +1,7 @@ +import { ReactNode } from 'react'; +import { MdeGenerateMarkdownPreview } from '../../typings/function-types'; +export interface MdePreviewProps { + loadingPreview?: ReactNode; + generateMarkdownPreview: MdeGenerateMarkdownPreview; + markdown: string; +} diff --git a/dist/types/components/textarea/index.d.ts b/dist/types/components/textarea/index.d.ts new file mode 100644 index 00000000..216c9b42 --- /dev/null +++ b/dist/types/components/textarea/index.d.ts @@ -0,0 +1,2 @@ +import { MdeTextareaProps } from './typings'; +export declare const MdeTextarea: import('react').ForwardRefExoticComponent>; diff --git a/dist/types/components/textarea/typings.d.ts b/dist/types/components/textarea/typings.d.ts new file mode 100644 index 00000000..3b555c89 --- /dev/null +++ b/dist/types/components/textarea/typings.d.ts @@ -0,0 +1,14 @@ +import { FC, KeyboardEvent, TextareaHTMLAttributes } from 'react'; +export interface MdeTextareaProps extends TextareaHTMLAttributes { + setValue: (text: string) => void; + /** + * Custom textarea component. "textareaComponent" can be any React component which + * props are a subset of the props of an HTMLTextAreaElement + */ + textareaComponent?: FC; + /** + * On keydown, the TextArea will trigger "onKeyCommand" as an opportunity for React-Mde to + * execute a command. If a command is executed, React-Mde should return true, otherwise, false. + */ + onKeyCommand?: (e: KeyboardEvent) => Promise; +} diff --git a/dist/types/components/toolbar/btn.d.ts b/dist/types/components/toolbar/btn.d.ts new file mode 100644 index 00000000..8c70719c --- /dev/null +++ b/dist/types/components/toolbar/btn.d.ts @@ -0,0 +1,3 @@ +import { FC } from 'react'; +import { MdeToolbarBtnProps } from './typings'; +export declare const MdeToolbarButton: FC; diff --git a/dist/types/components/toolbar/group.d.ts b/dist/types/components/toolbar/group.d.ts new file mode 100644 index 00000000..594d4d5d --- /dev/null +++ b/dist/types/components/toolbar/group.d.ts @@ -0,0 +1,3 @@ +import { FC } from 'react'; +import { MdeToolbarBtnGroupProps } from './typings'; +export declare const MdeToolbarBtnGroup: FC; diff --git a/dist/types/components/toolbar/index.d.ts b/dist/types/components/toolbar/index.d.ts new file mode 100644 index 00000000..25d686de --- /dev/null +++ b/dist/types/components/toolbar/index.d.ts @@ -0,0 +1,3 @@ +import { FC } from 'react'; +import { MdeToolbarProps } from './typings'; +export declare const MdeToolbar: FC; diff --git a/dist/types/components/toolbar/typings.d.ts b/dist/types/components/toolbar/typings.d.ts new file mode 100644 index 00000000..d695987f --- /dev/null +++ b/dist/types/components/toolbar/typings.d.ts @@ -0,0 +1,31 @@ +import { ComponentClass, HtmlHTMLAttributes, ReactNode } from 'react'; +export type MdeTabProps = 'write' | 'preview'; +export interface MdeToolbarProps { + buttons: MdeToolbarBtnData[][]; + onCommand: (commandName: string) => void; + onTabChange: (tab: MdeTabProps) => void; + readOnly: boolean; + disablePreview: boolean; + tab: MdeTabProps; + writeButtonProps?: HtmlHTMLAttributes; + previewButtonProps?: HtmlHTMLAttributes; + buttonProps?: HtmlHTMLAttributes; +} +export interface MdeToolbarBtnData { + commandName: string; + buttonContent: ReactNode; + buttonProps: any; + buttonComponentClass: ComponentClass | string; +} +export interface MdeToolbarBtnProps { + name: string; + buttonComponentClass?: ComponentClass | string; + buttonProps: any; + buttonContent: React.ReactNode; + onClick: React.MouseEventHandler; + readOnly: boolean; +} +export interface MdeToolbarBtnGroupProps { + hidden: boolean; + children: ReactNode; +} diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts new file mode 100644 index 00000000..ef95e200 --- /dev/null +++ b/dist/types/index.d.ts @@ -0,0 +1,7 @@ +import { MdeCommandProps } from './commands/command'; +import { getDefaultCommandMap, getDefaultToolbarCommands } from './commands/default-commands/defaults'; +import { Mde } from './components/bootstrap'; +import { MdeTabProps } from './components/toolbar/typings'; +import { selectWord } from './utils/markdown-util'; +export { Mde, getDefaultCommandMap, getDefaultToolbarCommands, selectWord }; +export type { MdeCommandProps, MdeTabProps }; diff --git a/dist/types/typings/command-options.d.ts b/dist/types/typings/command-options.d.ts new file mode 100644 index 00000000..e970d427 --- /dev/null +++ b/dist/types/typings/command-options.d.ts @@ -0,0 +1,35 @@ +import { MdeSelection } from './selection'; +/** + * The state of the text of the whole editor + */ +export interface MdeTextState { + /** + * All the text in the editor + */ + text: string; + /** + * The text that is selected + */ + selectedText: string; + /** + * The section of the text that is selected + */ + selection: MdeSelection; +} +export interface MdeTextApi { + /** + * Replaces the current selection with the new text. This will make the new selectedText to be empty, the + * selection start and selection end will be the same and will both point to the end + * @param text Text that should replace the current selection + */ + replaceSelection(text: string): MdeTextState; + /** + * Selects the specified text range + * @param selection + */ + setSelectionRange(selection: MdeSelection): MdeTextState; + /** + * Get the current text state + */ + getState(): MdeTextState; +} diff --git a/dist/types/typings/function-types.d.ts b/dist/types/typings/function-types.d.ts new file mode 100644 index 00000000..0c1fb822 --- /dev/null +++ b/dist/types/typings/function-types.d.ts @@ -0,0 +1,7 @@ +import { KeyboardEvent } from 'react'; +export type MdeGenerateMarkdownPreview = (markdown: string) => Promise; +/** + * If the command returns true for a given KeyboardEvent, + * the command is executed + */ +export type MdeHandleKeyCommand = (e: KeyboardEvent) => boolean; diff --git a/dist/types/typings/selection.d.ts b/dist/types/typings/selection.d.ts new file mode 100644 index 00000000..afc3c9c5 --- /dev/null +++ b/dist/types/typings/selection.d.ts @@ -0,0 +1,4 @@ +export interface MdeSelection { + start: number; + end: number; +} diff --git a/dist/types/typings/text-section.d.ts b/dist/types/typings/text-section.d.ts new file mode 100644 index 00000000..c70a6b01 --- /dev/null +++ b/dist/types/typings/text-section.d.ts @@ -0,0 +1,5 @@ +import { MdeSelection } from './selection'; +export interface MdeTextSection { + text: string; + selection: MdeSelection; +} diff --git a/dist/types/utils/insert-text-at-position.d.ts b/dist/types/utils/insert-text-at-position.d.ts new file mode 100644 index 00000000..9d629f7e --- /dev/null +++ b/dist/types/utils/insert-text-at-position.d.ts @@ -0,0 +1,5 @@ +/** + * Inserts the given text at the cursor. If the element contains a selection, the selection + * will be replaced by the text. + */ +export declare const insertText: (input: HTMLTextAreaElement | HTMLInputElement, text: string) => void; diff --git a/dist/types/utils/markdown-util.d.ts b/dist/types/utils/markdown-util.d.ts new file mode 100644 index 00000000..3eb57af9 --- /dev/null +++ b/dist/types/utils/markdown-util.d.ts @@ -0,0 +1,20 @@ +import { MdeSelection } from '../typings/selection'; +import { MdeTextSection } from '../typings/text-section'; +export declare function getSurroundingWord(text: string, position: number): MdeSelection; +/** + * If the cursor is inside a word and (selection.start === selection.end) + * returns a new Selection where the whole word is selected + * @param text + * @param selection + */ +export declare function selectWord({ text, selection }: MdeTextSection): MdeSelection; +/** + * Gets the number of line-breaks that would have to be inserted before the given 'startPosition' + * to make sure there's an empty line between 'startPosition' and the previous text + */ +export declare function getBreaksNeededForEmptyLineBefore(text: string | undefined, startPosition: number): number; +/** + * Gets the number of line-breaks that would have to be inserted after the given 'startPosition' + * to make sure there's an empty line between 'startPosition' and the next text + */ +export declare function getBreaksNeededForEmptyLineAfter(text: string | undefined, startPosition: number): number; diff --git a/docs-md/5-readme.md b/docs-md/5-readme.md deleted file mode 100644 index 6df1fc5b..00000000 --- a/docs-md/5-readme.md +++ /dev/null @@ -1,203 +0,0 @@ -# react-mde - -A simple yet powerful and extensible Markdown Editor editor for React. React-mde is built on top of [Draft.js](https://draftjs.org/). - -## Demos - -- [Demos](http://andrerpena.me/react-mde/). - -## Installing - - npm i --save react-mde - -## Dependencies - -React-mde currently depends on: - -- [Draft.js](https://draftjs.org/). This facilitates features that would otherwise be quite -difficult. The best examples being history management, mentions and pasting files. - - - npm i --save draft-js - -- [Font Awesome 5.*](https://fontawesome.com/) for the icons. This is not a hard dependency and can be changed (see the **Customizing Icons** section below). -To use Font Awesome icons, install [using your preferred method](https://fontawesome.com/how-to-use/svg-with-js). -The easiest is just add this to ``: - - - - -It is possible to use React-mde with Font Awesome 4 (and possibly earlier versions) – see below under 'Customizing Icons'. - -## Optional dependencies - -- [Showdown](https://github.com/showdownjs/showdown). React-mde is not opinionated as to how to transform markdown into HTML and this can be done both in client-side, -like StackOverflow, or in server-side, like GitHub. The easiest way is to use Showdown and process it in client-side. If you -decide to do so, install Showdown: - - - npm i --save showdown - -## Using - -React-mde is a completely controlled component. - -Minimal example using Showdown: -```jsx -import * as React from "react"; -import ReactMde, {ReactMdeTypes} from "../src"; -import * as Showdown from "showdown"; - -export interface AppState { - mdeState: ReactMdeTypes.MdeState; -} - -export class App extends React.Component<{}, AppState> { - - converter: Showdown.Converter; - - constructor(props) { - super(props); - this.state = { - mdeState: null, - }; - this.converter = new Showdown.Converter({tables: true, simplifiedAutoLink: true}); - } - - handleValueChange = (mdeState: ReactMdeTypes.MdeState) => { - this.setState({mdeState}); - } - - render() { - return ( -
- Promise.resolve(this.converter.makeHtml(markdown))} - /> -
- ); - } -} -``` - -### Customizing Icons - -By default, React-mde will use Font Awesome class names to render icons (see above for how to install). -The default icon provider returns icons that look like the following: - -```jsx -