import { h, useState, useEvent, useProp, useHost, useRef, useEffect } from 'atomico';
import 'toastr';
import 'funfix';
import { t as toastrMessage } from './chunks/496a9efa.js';
import { g as getComponentOrDefine } from './chunks/65ef80fe.js';
import '@caedman/gs/dist/global-style';
import { Maybe } from 'purify-ts/es/Maybe';
import './kun-icon.js';
import './chunks/a234fa33.js';
import './kun-image-or-default.js';
import { useStylesheet } from '@caedman/kit/dist/use-stylesheet';
import 'lazyload-image';
import './kun-image.js';
import 'dayjs';
import { getKunImageUrl } from './kun-chat-message.js';
import './chunks/b7110801.js';
import './kun-button-puer.js';
import './kun-checkbox.js';
import { e as execWithSixLoad } from './chunks/d4829071.js';
import './kun-dialog.js';
import './kun-ex-link.js';
import '@caedman/seek-api/build/api/upload-markdown';
import './kun-markdown-button.js';
import './kun-form.js';
import { requestParseLink } from '@caedman/seek-api/build/api/req-parse-link';
import { requestGetPageTitle } from '@caedman/seek-api/build/api/get-api';
import { keymap } from 'prosemirror-keymap';
import { setBlockType, lift, wrapIn, chainCommands, exitCode, toggleMark, baseKeymap } from 'prosemirror-commands';
import { InputRule, wrappingInputRule, textblockTypeInputRule, inputRules } from 'prosemirror-inputrules';
import { Slice, Fragment, Schema, DOMParser, DOMSerializer } from 'prosemirror-model';
import javascript from 'highlight.js/lib/languages/javascript';
import python from 'highlight.js/lib/languages/python';
import scala from 'highlight.js/lib/languages/scala';
import css from 'highlight.js/lib/languages/css';
import { DecorationSet, Decoration, EditorView } from 'prosemirror-view';
import { Plugin, PluginKey, EditorState, TextSelection } from 'prosemirror-state';
import { liftListItem, wrapInList, splitListItem, sinkListItem } from 'prosemirror-schema-list';
import { findSelectedNodeOfType, findParentNode, findBlockNodes } from 'prosemirror-utils';
import low from 'lowlight/lib/core';
import { r as requestUploadFile1 } from './chunks/237ddcfd.js';
import { tableNodes } from 'prosemirror-tables';
import 'prosemirror-transform';
import 'prosemirror-collab';
import 'prosemirror-history';
import './kun-link-button.js';

const _jsxFileName = "/Users/rang/rang/frond_ng/packages/six/src/components/kun-editor/tiptap/Components/EditorMenuBarAtomico.tsx";

const EditorMenuBarAtomico = () => (
  h('host', {__self: undefined, __source: {fileName: _jsxFileName, lineNumber: 6}}
    , h('div', {__self: undefined, __source: {fileName: _jsxFileName, lineNumber: 7}}
      , h('h1', {__self: undefined, __source: {fileName: _jsxFileName, lineNumber: 8}}, "dd")
    )
  )
);


getComponentOrDefine("kun-editor-bar-menu", EditorMenuBarAtomico);

const _jsxFileName$1 = "/Users/rang/rang/frond_ng/packages/six/src/components/kun-editor/import-link-dialog/import-link-dialog.tsx";
const mockStyle = `
    .mock {
        
    }
`;
const arrays = [
  {
    label: "Url",
    name: "url",
    formType: "input",
  },
];

const ImportByLinkDialog = () => {
  const [show, setShow] = useState(false);
  const useEvent1 = useEvent("MySubmit", {
    bubbles: true,
    composed: true,
  });

  const onClick = () => {
    console.log("s", show);
    setShow(true);
    console.log("s", show);
  };
  return (
    h('host', { shadowDom: true, __self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 41}}
      , h('style', {__self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 42}}, mockStyle)
      , h('div', {__self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 43}}
        , h('span', { class: "cursor-pointer", onclick: () => onClick(), __self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 44}}, "导入")
        , 
            show && (
            h('kun-dialog', {
              'has-button': false,
              open: show,
              kunTitle: "从链接导入",
              kunWidth: 500,
              onMyClose: () => setShow(false), __self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 47}}
            
              , h('kun-form', {
                slot: "content",
                className: "sm:w-7/12",
                fields: arrays,
                'parse-form': true,
                'submit-text': "提交",
                onMySubmit: async (event) => {
                  await execWithSixLoad(async () => {
                    const data = event.detail.form;
                    const a = await requestParseLink(data.url);
                    if (a.record.title.length !== 0 || a.record.content.length !== 0) {
                      useEvent1(a.record);
                      toastrMessage();
                      setShow(false);
                    } else {
                      toastrMessage("请稍后再试");
                    }
                  });
                }, __self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 54}}
              )
              , h('kun-button-puer', { needleContent: "提交", __self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 74}} )
            )
            )
          
      )
      , h('global-style', {__self: undefined, __source: {fileName: _jsxFileName$1, lineNumber: 79}} )
    )
  ) ;
};


getComponentOrDefine("kun-import-link-dialog-1", ImportByLinkDialog);

const _jsxFileName$2 = "/Users/rang/rang/frond_ng/packages/six/src/components/kun-editor/import-url-dialog/import-url-dialog.tsx";


const mockStyle$1 = `
    .mock {
        
    }
`;
const arrays$1 = [
  {
    label: "Url",
    name: "url",
    formType: "input",
  },
];

const ImportUrlDialog = () => {
  const [show, setShow] = useState(false);
  const useEvent1 = useEvent("MyImportUrl", {
    bubbles: true,
    composed: true,
  });

  const onClick = () => {
    setShow(true);
  };

  return (
    h('host', { shadowDom: true, __self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 40}}
      , h('style', {__self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 41}}, mockStyle$1)
      , h('div', {__self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 42}}
        , h('span', { class: "cursor-pointer", onclick: () => onClick(), __self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 43}}, "添加链接")
        , 
                    show && (
                    h('kun-dialog', {
                      'has-button': false,
                      open: show,
                      kunTitle: "从链接导入",
                      kunWidth: 500,
                      onMyClose: () => setShow(false), __self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 46}}
                    
                      , h('kun-form', {
                        slot: "content",
                        className: "sm:w-7/12",
                        fields: arrays$1,
                        'parse-form': true,
                        'submit-text': "提交",
                        onMySubmit: async (event) => {
                          console.log("subbbbbbbbbbbb");
                          const data = event.detail.form;
                          if (show) {
                            setShow(false);
                            const { msg: title } = await requestGetPageTitle(data.url);
                            useEvent1({
                              title,
                              url: data.url,
                            });
                          }

                          event.preventDefault();
                        }, __self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 53}}
                      )
                      , h('kun-button-puer', { needleContent: "提交", __self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 74}} )
                    )
                    )
                
      )
      , h('global-style', {__self: undefined, __source: {fileName: _jsxFileName$2, lineNumber: 79}} )
    )
    ) ;
};


getComponentOrDefine("kun-import-url-dialog", ImportUrlDialog);

var style = ".hidden {\n  visibility: hidden;\n}\n\n.header-icons {\n}\n\n.editor-menu {\n  width: 32px;\n  height: 24px;\n  justify-content: center;\n  display: flex;\n  align-items: center;\n}\n\nkun-icon {\n  width: 32px;\n  height: 24px;\n  display: flex;\n  align-items: center;\n}\n\n.header-icons {\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n}\n\n.bg-select {\n  background-color: rgba(0,0,0,.1);\n}\n\n.ProseMirror {\n  position: relative;\n}\n\n.ProseMirror {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  font-feature-settings: none;\n  font-variant-ligatures: none;\n}\n\n.ProseMirror pre {\n  white-space: pre-wrap;\n}\n\n.ProseMirror-gapcursor {\n  display: none;\n  pointer-events: none;\n  position: absolute;\n}\n\n.ProseMirror-gapcursor:after {\n  content: \"\";\n  display: block;\n  position: absolute;\n  top: -2px;\n  width: 20px;\n  border-top: 1px solid black;\n  -webkit-animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;\n          animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;\n}\n\n@-webkit-keyframes ProseMirror-cursor-blink {\n  to {\n    visibility: hidden;\n  }\n}\n\n@keyframes ProseMirror-cursor-blink {\n  to {\n    visibility: hidden;\n  }\n}\n\n.ProseMirror-hideselection *::-moz-selection {\n  background: transparent;\n}\n\n.ProseMirror-hideselection *::selection {\n  background: transparent;\n}\n\n.ProseMirror-hideselection *::-moz-selection {\n  background: transparent;\n}\n\n.ProseMirror-hideselection * {\n  caret-color: transparent;\n}\n\n.ProseMirror-focused .ProseMirror-gapcursor {\n  display: block;\n}\n\n.img:empty:before {\n  color: black;\n  content: \"Write a caption\";\n  pointer-events: none;\n}";

class Extension {
  constructor(options = {}) {
    this.options = {
      ...this.defaultOptions,
      ...options,
    };
  }

  init() {
    return null;
  }

  bindEditor(editor = null) {
    this.editor = editor;
  }

  get name() {
    return null;
  }

  get type() {
    return "extension";
  }

  get defaultOptions() {
    return {};
  }

  get plugins() {
    return [];
  }

  inputRules() {
    return [];
  }

  pasteRules() {
    return [];
  }

  keys() {
    return {};
  }
}

class Node extends Extension {
  constructor(options = {}) {
    super(options);
  }

  get type() {
    return "node";
  }

  get view() {
    return null;
  }

  get schema() {
    return null;
  }

  command() {
    return () => {};
  }
}

class Title extends Node {
  get name() {
    return "title";
  }

  get schema() {
    return {
      content: "inline*",
      parseDOM: [{
        tag: "h1",
      }],
      toDOM: () => ["h1", 0],
    };
  }
}

class Doc extends Node {
  get name() {
    return "doc";
  }

  get schema() {
    return {
      // content: "title block+",
      content: "block+",
    };
  }
}

class DocTitle extends Node {
  get name() {
    return "doc";
  }

  get schema() {
    return {
        content: "title block+",
      // content: "block+",
    };
  }
}

function getMarksBetween(start, end, state) {
  let marks = [];

  state.doc.nodesBetween(start, end, (node, pos) => {
    marks = [...marks, ...node.marks.map(mark => ({
      start: pos,
      end: pos + node.nodeSize,
      mark,
    }))];
  });

  return marks
}

function markInputRule (regexp, markType, getAttrs) {
  return new InputRule(regexp, (state, match, start, end) => {
    const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
    const { tr } = state;
    const m = match.length - 1;
    let markEnd = end;
    let markStart = start;

    if (match[m]) {
      const matchStart = start + match[0].indexOf(match[m - 1]);
      const matchEnd = matchStart + match[m - 1].length - 1;
      const textStart = matchStart + match[m - 1].lastIndexOf(match[m]);
      const textEnd = textStart + match[m].length;

      const excludedMarks = getMarksBetween(start, end, state)
        .filter(item => {
          const { excluded } = item.mark.type;
          return excluded.find(type => type.name === markType.name)
        })
        .filter(item => item.end > matchStart);

      if (excludedMarks.length) {
        return false
      }

      if (textEnd < matchEnd) {
        tr.delete(textEnd, matchEnd);
      }
      if (textStart > matchStart) {
        tr.delete(matchStart, textStart);
      }
      markStart = matchStart;
      markEnd = markStart + match[m].length;
    }

    tr.addMark(markStart, markEnd, markType.create(attrs));
    tr.removeStoredMark(markType);
    return tr
  })
}

function nodeInputRule (regexp, type, getAttrs) {
  return new InputRule(regexp, (state, match, start, end) => {
    const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
    const { tr } = state;

    if (match[0]) {
      tr.replaceWith(start - 1, end, type.create(attrs));
    }

    return tr
  })
}

function pasteRule (regexp, type, getAttrs) {
  const handler = (fragment) => {
    const nodes = [];

    fragment.forEach((child) => {
      console.log("child", child);
      if (child.isText) {
        const { text } = child;
        let pos = 0;
        let match;

        do {
          match = regexp.exec(text);
          if (match) {
            const start = match.index;
            const end = start + match[0].length;
            const attrs = getAttrs instanceof Function ? getAttrs(match[0]) : getAttrs;

            if (start > 0) {
              nodes.push(child.cut(pos, start));
            }

            nodes.push(child
              .cut(start, end)
              .mark(type.create(attrs)
                .addToSet(child.marks)));

            pos = end;
          }
        } while (match);

        if (pos < text.length) {
          nodes.push(child.cut(pos));
        }
      } else {
        nodes.push(child.copy(handler(child.content)));
      }
    });

    return Fragment.fromArray(nodes);
  };

  return new Plugin({
    props: {
      transformPasted: (slice) => new Slice(handler(slice.content), slice.openStart, slice.openEnd),
    },
  });
}

function markPasteRule (regexp, type, getAttrs) {
  const handler = (fragment, parent) => {
    const nodes = [];

    fragment.forEach((child) => {
      console.log("child.isText", child.isText);
      if (child.isText) {
        const { text, marks } = child;
        let pos = 0;
        let match;

        const isLink = !!marks.filter((x) => x.type.name === "link")[0];

        // eslint-disable-next-line
        while (!isLink && (match = regexp.exec(text)) !== null) {
          if (parent.type.allowsMarkType(type) && match[1]) {
            const start = match.index;
            const end = start + match[0].length;
            const textStart = start + match[0].indexOf(match[1]);
            const textEnd = textStart + match[1].length;
            const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;

            // adding text before markdown to nodes
            if (start > 0) {
              nodes.push(child.cut(pos, start));
            }

            // adding the markdown part to nodes
            nodes.push(child
              .cut(textStart, textEnd)
              .mark(type.create(attrs)
                .addToSet(child.marks)));

            pos = end;
          }
        }

        // adding rest of text to nodes
        if (pos < text.length) {
          nodes.push(child.cut(pos));
        }
      } else {
        nodes.push(child.copy(handler(child.content, child)));
      }
    });

    return Fragment.fromArray(nodes);
  };

  return new Plugin({
    props: {
      transformPasted: (slice) => new Slice(handler(slice.content), slice.openStart, slice.openEnd),
    },
  });
}

function getMarkAttrs(state, type) {
  const { from, to } = state.selection;
  let marks = [];

  state.doc.nodesBetween(from, to, node => {
    marks = [...marks, ...node.marks];
  });

  const mark = marks.find(markItem => markItem.type.name === type.name);

  if (mark) {
    return mark.attrs
  }

  return {}
}

function getNodeAttrs(state, type) {
  const { from, to } = state.selection;
  let nodes = [];

  state.doc.nodesBetween(from, to, node => {
    nodes = [...nodes, node];
  });

  const node = nodes
    .reverse()
    .find(nodeItem => nodeItem.type.name === type.name);

  if (node) {
    return node.attrs
  }

  return {}
}

function getMarkRange($pos = null, type = null) {

  if (!$pos || !type) {
    return false
  }

  const start = $pos.parent.childAfter($pos.parentOffset);

  if (!start.node) {
    return false
  }

  const link = start.node.marks.find(mark => mark.type === type);
  if (!link) {
    return false
  }

  let startIndex = $pos.index();
  let startPos = $pos.start() + start.offset;
  let endIndex = startIndex + 1;
  let endPos = startPos + start.node.nodeSize;

  while (startIndex > 0 && link.isInSet($pos.parent.child(startIndex - 1).marks)) {
    startIndex -= 1;
    startPos -= $pos.parent.child(startIndex).nodeSize;
  }

  while (endIndex < $pos.parent.childCount && link.isInSet($pos.parent.child(endIndex).marks)) {
    endPos += $pos.parent.child(endIndex).nodeSize;
    endIndex += 1;
  }

  return { from: startPos, to: endPos }

}

function markIsActive(state, type) {
  const {
    from,
    $from,
    to,
    empty,
  } = state.selection;

  if (empty) {
    return !!type.isInSet(state.storedMarks || $from.marks())
  }

  return !!state.doc.rangeHasMark(from, to, type)
}

function nodeIsActive(state, type, attrs = {}) {
  const predicate = (node) => node.type === type;
  const node = findSelectedNodeOfType(type)(state.selection)
    || findParentNode(predicate)(state.selection);

  if (!Object.keys(attrs).length || !node) {
    return !!node;
  }

  return node.node.hasMarkup(type, { ...node.node.attrs, ...attrs });
}

function removeMark (type) {
  return (state, dispatch) => {
    const { tr, selection } = state;
    let { from, to } = selection;
    const { $from, empty } = selection;

    if (empty) {
      const range = getMarkRange($from, type);

      from = range.from;
      to = range.to;
    }

    tr.removeMark(from, to, type);

    return dispatch(tr);
  };
}

function toggleBlockType (type, toggletype, attrs = {}) {
  return (state, dispatch, view) => {
    const isActive = nodeIsActive(state, type, attrs);

    if (isActive) {
      return setBlockType(toggletype)(state, dispatch, view);
    }

    return setBlockType(type, attrs)(state, dispatch, view);
  };
}

function isList(node, schema) {
  return (node.type === schema.nodes.bullet_list
    || node.type === schema.nodes.ordered_list
    || node.type === schema.nodes.todo_list);
}

function toggleList(listType, itemType) {
  return (state, dispatch, view) => {
    const { schema, selection } = state;
    const { $from, $to } = selection;
    const range = $from.blockRange($to);

    if (!range) {
      return false;
    }

    const parentList = findParentNode((node) => isList(node, schema))(selection);

    if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
      if (parentList.node.type === listType) {
        return liftListItem(itemType)(state, dispatch, view);
      }

      if (isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {
        const { tr } = state;
        tr.setNodeMarkup(parentList.pos, listType);

        if (dispatch) {
          dispatch(tr);
        }

        return false;
      }
    }

    return wrapInList(listType)(state, dispatch, view);
  };
}

function toggleWrap (type) {
  return (state, dispatch, view) => {
    const isActive = nodeIsActive(state, type);

    if (isActive) {
      return lift(state, dispatch);
    }

    return wrapIn(type)(state, dispatch, view);
  };
}

function updateMark (type, attrs) {
  return (state, dispatch) => {
    const { tr, selection, doc } = state;
    let { from, to } = selection;
    const { $from, empty } = selection;

    if (empty) {
      const range = getMarkRange($from, type);

      from = range.from;
      to = range.to;
    }

    const hasMark = doc.rangeHasMark(from, to, type);

    if (hasMark) {
      tr.removeMark(from, to, type);
    }

    tr.addMark(from, to, type.create(attrs));

    return dispatch(tr);
  };
}

class Paragraph extends Node {
  get name() {
    return "paragraph";
  }

  get schema() {
    return {
      content: "inline*",
      group: "block",
      draggable: false,
      parseDOM: [{
        tag: "p",
      }],
      toDOM: () => ["p", 0],
    };
  }

  commands({ type }) {
    return () => setBlockType(type);
  }
}

class Text extends Node {
  get name() {
    return "text";
  }

  get schema() {
    return {
      group: "inline",
    };
  }
}

function camelCase (str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (index === 0 ? word.toLowerCase() : word.toUpperCase())).replace(/\s+/g, '')
}

class ExtensionManager {
  constructor(extensions = [], editor) {
    extensions.forEach((extension) => {
      // extension.bindEditor(editor);
      extension.init();
    });
    this.extensions = extensions;
  }

  get nodes() {
    return this.extensions
      .filter((extension) => extension.type === "node")
      .reduce((nodes, { name, schema }) => ({
        ...nodes,
        [name]: schema,
      }), {});
  }

  get options() {
    const { view } = this;
    return this.extensions
      .reduce((nodes, extension) => ({
        ...nodes,
        [extension.name]: new Proxy(extension.options, {
          set(obj, prop, value) {
            const changed = (obj[prop] !== value);

            Object.assign(obj, { [prop]: value });

            if (changed) {
              view.updateState(view.state);
            }

            return true;
          },
        }),
      }), {});
  }

  get marks() {
    return this.extensions
      .filter((extension) => extension.type === "mark")
      .reduce((marks, { name, schema }) => ({
        ...marks,
        [name]: schema,
      }), {});
  }

  get plugins() {
    return this.extensions
      .filter((extension) => extension.plugins)
      .reduce((allPlugins, { plugins }) => ([
        ...allPlugins,
        ...plugins,
      ]), []);
  }

  keymaps({ schema }) {
    const extensionKeymaps = this.extensions
      .filter((extension) => ["extension"].includes(extension.type))
      .filter((extension) => extension.keys)
      .map((extension) => extension.keys({ schema }));

    const nodeMarkKeymaps = this.extensions
      .filter((extension) => ["node", "mark"].includes(extension.type))
      .filter((extension) => extension.keys)
      .map((extension) => extension.keys({
        type: schema[`${extension.type}s`][extension.name],
        schema,
      }));

    return [
      ...extensionKeymaps,
      ...nodeMarkKeymaps,
    ].map((keys) => keymap(keys));
  }

  inputRules({ schema, excludedExtensions }) {
    if (!(excludedExtensions instanceof Array) && excludedExtensions) return [];

    const allowedExtensions = (excludedExtensions instanceof Array) ? this.extensions
      .filter((extension) => !excludedExtensions.includes(extension.name)) : this.extensions;

    const extensionInputRules = allowedExtensions
      .filter((extension) => ["extension"].includes(extension.type))
      .filter((extension) => extension.inputRules)
      .map((extension) => extension.inputRules({ schema }));

    const nodeMarkInputRules = allowedExtensions
      .filter((extension) => ["node", "mark"].includes(extension.type))
      .filter((extension) => extension.inputRules)
      .map((extension) => extension.inputRules({
        type: schema[`${extension.type}s`][extension.name],
        schema,
      }));

    return [
      ...extensionInputRules,
      ...nodeMarkInputRules,
    ].reduce((allInputRules, inputRules) => ([
      ...allInputRules,
      ...inputRules,
    ]), []);
  }

  pasteRules({ schema, excludedExtensions }) {
    if (!(excludedExtensions instanceof Array) && excludedExtensions) return [];

    const allowedExtensions = (excludedExtensions instanceof Array) ? this.extensions
      .filter((extension) => !excludedExtensions.includes(extension.name)) : this.extensions;

    const extensionPasteRules = allowedExtensions
      .filter((extension) => ["extension"].includes(extension.type))
      .filter((extension) => extension.pasteRules)
      .map((extension) => extension.pasteRules({ schema }));

    const nodeMarkPasteRules = allowedExtensions
      .filter((extension) => ["node", "mark"].includes(extension.type))
      .filter((extension) => extension.pasteRules)
      .map((extension) => extension.pasteRules({
        type: schema[`${extension.type}s`][extension.name],
        schema,
      }));

    return [
      ...extensionPasteRules,
      ...nodeMarkPasteRules,
    ].reduce((allPasteRules, pasteRules) => ([
      ...allPasteRules,
      ...pasteRules,
    ]), []);
  }

  commands({ schema }) {
    return this.extensions
      .filter((extension) => extension.commands)
      .reduce((allCommands, extension) => {
        const { name, type } = extension;
        const commands = {};
        const value = extension.commands({
          schema,
          ...["node", "mark"].includes(type) ? {
            type: schema[`${type}s`][name],
          } : {},
        });

        const apply = (cb, attrs) => cb(attrs)();

        const handle = (_name, _value) => {
          if (Array.isArray(_value)) {
            commands[_name] = (attrs) => _value.forEach((callback) => apply(callback, attrs));
          } else if (typeof _value === "function") {
            commands[_name] = (attrs) => apply(_value, attrs);
          }
        };

        if (typeof value === "object") {
          Object.entries(value).forEach(([commandName, commandValue]) => {
            handle(commandName, commandValue);
          });
        } else {
          handle(name, value);
        }

        return {
          ...allCommands,
          ...commands,
        };
      }, {});
  }
}

class Mark extends Extension {

  constructor(options = {}) {
    super(options);
  }

  get type() {
    return 'mark'
  }

  get view() {
    return null
  }

  get schema() {
    return null
  }

  command() {
    return () => {}
  }

}

function minMax(value = 0, min = 0, max = 0) {
  return Math.min(Math.max(parseInt(value, 10), min), max)
}

class Blockquote extends Node {
  get name() {
    return "blockquote";
  }

  get schema() {
    return {
      content: "block*",
      group: "block",
      defining: true,
      draggable: false,
      parseDOM: [
        { tag: "blockquote" },
      ],
      toDOM: () => ["blockquote", 0],
    };
  }

  commands({ type, schema }) {
    return () => toggleWrap(type, schema.nodes.paragraph);
  }

  keys({ type }) {
    return {
      "Ctrl->": toggleWrap(type),
    };
  }

  inputRules({ type }) {
    return [
      wrappingInputRule(/^\s*>\s$/, type),
    ];
  }
}

class Menu {
  constructor({ options }) {
    this.options = options;
    this.preventHide = false;

    // the mousedown event is fired before blur so we can prevent it
    this.mousedownHandler = this.handleClick.bind(this);
    this.options.element.addEventListener("mousedown", this.mousedownHandler, { capture: true });

    this.blurHandler = () => {
      if (this.preventHide) {
        this.preventHide = false;
        return;
      }

      // TODO update
      // this.options.editor.emit("menubar:focusUpdate", false);
    };
    // this.options.editor.on("blur", this.blurHandler);
  }

  handleClick() {
    this.preventHide = true;
  }

  destroy() {
    this.options.element.removeEventListener("mousedown", this.mousedownHandler);
    this.options.editor.off("blur", this.blurHandler);
  }
}

function MenuBar (options) {
  return new Plugin({
    key: new PluginKey("menu_bar"),
    view(editorView) {
      return new Menu({ editorView, options });
    },
  });
}

class BulletList extends Node {
  get name() {
    return "bullet_list";
  }

  get schema() {
    return {
      content: "list_item+",
      group: "block",
      parseDOM: [
        { tag: "ul" },
      ],
      toDOM: () => ["ul", 0],
    };
  }

  commands({ type, schema }) {
    return () => toggleList(type, schema.nodes.list_item);
  }

  keys({ type, schema }) {
    return {
      "Shift-Ctrl-8": toggleList(type, schema.nodes.list_item),
    };
  }

  inputRules({ type }) {
    return [
      wrappingInputRule(/^\s*([-+*])\s$/, type),
    ];
  }
}

function getDecorations({ doc, name }) {
  const decorations = [];
  const blocks = findBlockNodes(doc).filter((item) => item.node.type.name === name);
  const flatten = (list) => list.reduce(
    (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [],
  );

  function parseNodes(nodes, className = []) {
    return nodes.map((node) => {
      const classes = [
        ...className,
        ...node.properties ? node.properties.className : [],
      ];

      if (node.children) {
        return parseNodes(node.children, classes);
      }

      return {
        text: node.value,
        classes,
      };
    });
  }

  blocks.forEach((block) => {
    let startPos = block.pos + 1;
    const nodes = low.highlightAuto(block.node.textContent).value;

    flatten(parseNodes(nodes))
      .map((node) => {
        const from = startPos;
        const to = from + node.text.length;

        startPos = to;

        return {
          ...node,
          from,
          to,
        };
      })
      .forEach((node) => {
        const decoration = Decoration.inline(node.from, node.to, {
          class: node.classes.join(" "),
        });
        decorations.push(decoration);
      });
  });

  return DecorationSet.create(doc, decorations);
}

function HighlightPlugin({ name }) {
  return new Plugin({
    name: new PluginKey("highlight"),
    state: {
      init: (_, { doc }) => getDecorations({ doc, name }),
      apply: (transaction, decorationSet, oldState, newState) => {
        // TODO: find way to cache decorations
        // https://discuss.prosemirror.net/t/how-to-update-multiple-inline-decorations-on-node-change/1493
        const oldNodeName = oldState.selection.$head.parent.type.name;
        const newNodeName = newState.selection.$head.parent.type.name;
        const oldNodes = findBlockNodes(oldState.doc)
          .filter((item) => item.node.type.name === name);
        const newNodes = findBlockNodes(newState.doc)
          .filter((item) => item.node.type.name === name);
        // Apply decorations if selection includes named node, or transaction changes named node.
        if (transaction.docChanged && ([oldNodeName, newNodeName].includes(name)
          || newNodes.length !== oldNodes.length)) {
          return getDecorations({ doc: transaction.doc, name });
        }
        return decorationSet.map(transaction.mapping, transaction.doc);
      },
    },
    props: {
      decorations(state) {
        return this.getState(state);
      },
    },
  });
}

class CodeBlockHighlight extends Node {
  constructor(options = {}) {
    super(options);
    console.log(options);
    try {
      Object.entries(options.languages).forEach(([name, mapping]) => {
        console.log("name", name);
        console.log("mapping", mapping);
        // low.registerLanguage("javascript", javascript);
        low.registerLanguage(name, mapping);
      });
    } catch (err) {
      console.log(err);
      throw new Error("Invalid syntax highlight definitions: define at least one highlight.js language mapping");
    }
  }

  get name() {
    return "code_block";
  }

  get defaultOptions() {
    return {
      languages: {},
    };
  }

  get schema() {
    return {
      content: "text*",
      marks: "",
      group: "block",
      code: true,
      defining: true,
      draggable: false,
      parseDOM: [
        { tag: "pre", preserveWhitespace: "full" },
      ],
      toDOM: () => ["pre", ["code", 0]],
    };
  }

  commands({ type, schema }) {
    return () => toggleBlockType(type, schema.nodes.paragraph);
  }

  keys({ type }) {
    return {
      "Shift-Ctrl-\\": setBlockType(type),
    };
  }

  inputRules({ type }) {
    return [
      textblockTypeInputRule(/^```$/, type),
    ];
  }

  get plugins() {
    return [
      HighlightPlugin({ name: this.name }),
    ];
  }
}

class HardBreak extends Node {
  get name() {
    return "hard_break";
  }

  get schema() {
    return {
      inline: true,
      group: "inline",
      selectable: false,
      parseDOM: [
        { tag: "br" },
      ],
      toDOM: () => ["br"],
    };
  }

  keys({ type }) {
    const command = chainCommands(exitCode, (state, dispatch) => {
      dispatch(state.tr.replaceSelectionWith(type.create()).scrollIntoView());
      return true;
    });
    return {
      "Mod-Enter": command,
      "Shift-Enter": command,
    };
  }
}

class Heading extends Node {
  get name() {
    return "heading";
  }

  get defaultOptions() {
    return {
      levels: [1, 2, 3, 4, 5, 6],
    };
  }

  get schema() {
    return {
      attrs: {
        level: {
          default: 1,
        },
      },
      content: "inline*",
      group: "block",
      defining: true,
      draggable: false,
      parseDOM: this.options.levels
        .map((level) => ({
          tag: `h${level}`,
          attrs: { level },
        })),
      toDOM: (node) => [`h${node.attrs.level}`, 0],
    };
  }

  commands({ type, schema }) {
    return (attrs) => toggleBlockType(type, schema.nodes.paragraph, attrs);
  }

  keys({ type }) {
    return this.options.levels.reduce((items, level) => ({
      ...items,
      ...{
        [`Shift-Ctrl-${level}`]: setBlockType(type, { level }),
      },
    }), {});
  }

  inputRules({ type }) {
    console.log(`inputRules ${type}`, type);
    return this.options.levels.map((level) => textblockTypeInputRule(
      new RegExp(`^(#{1,${level}})\\s$`),
      type,
      () => ({ level }),
    ));
  }
}

// based on the example at: https://prosemirror.net/examples/upload/
const uploadPlaceholder = new Plugin({
  state: {
    init() {
      return DecorationSet.empty;
    },
    apply(tr, set) {
      // Adjust decoration positions to changes made by the transaction
      set = set.map(tr.mapping, tr.doc);

      // See if the transaction adds or removes any placeholders
      const action = tr.getMeta(this);

      if (action && action.add) {
        const element = document.createElement("div");
        element.className = "image placeholder";

        const img = document.createElement("img");
        img.src = URL.createObjectURL(action.add.file);

        element.appendChild(img);
        const e = document.createElement("div");
        const txt = document.createTextNode("上传中");
        e.appendChild(txt);
        e.className = "uploading";

        element.appendChild(e);

        const deco = Decoration.widget(action.add.pos, element, {
          id: action.add.id,
        });
        set = set.add(tr.doc, [deco]);
      } else if (action && action.remove) {
        set = set.remove(
          set.find(null, null, (spec) => spec.id === action.remove.id),
        );
      }
      return set;
    },
  },
  props: {
    decorations(state) {
      return this.getState(state);
    },
  },
});

function findPlaceholder(state, id) {
  const decos = uploadPlaceholder.getState(state);
  const found = decos.find(null, null, (spec) => spec.id === id);
  return found.length ? found[0].from : null;
}

const uploadFile = async (file) => {
  const formData = new FormData();
  formData.set("file", file);
  return requestUploadFile1(formData);
};

const insertFiles = async (view, event, pos, files) => {
  // filter to only include image files
  const images = files.filter((file) => /image/i.test(file.type));
  if (images.length === 0) return;

  // event going any further up the stack
  event.preventDefault();

  // let the user know we're starting to process the images

  const { schema } = view.state;

  // the user might have dropped multiple images at once, we need to loop
  for (const file of images) {
    // Use an object to act as the ID for this upload, clever.
    const id = {};

    const { tr } = view.state;

    // insert a placeholder at this position
    tr.setMeta(uploadPlaceholder, {
      add: { id, file, pos },
    });
    view.dispatch(tr);

    // start uploading the image file to the server. Using "then" syntax
    // to allow all placeholders to be entered at once with the uploads
    // happening in the background in parallel.
    uploadFile(file)
      .then((src) => {
        const pos = findPlaceholder(view.state, id);

        // if the content around the placeholder has been deleted
        // then forget about inserting this image
        if (pos === null) return;

        // otherwise, insert it at the placeholder's position, and remove
        // the placeholder itself
        const transaction = view.state.tr
          .replaceWith(pos, pos, schema.nodes.image.create({ src: getKunImageUrl(src.msg) }))
          .setMeta(uploadPlaceholder, { remove: { id } });

        view.dispatch(transaction);
      })
      .catch((error) => {
        console.error(error);

        // cleanup the placeholder if there is a failure
        const transaction = view.state.tr.setMeta(uploadPlaceholder, {
          remove: { id },
        });
        view.dispatch(transaction);
        toastrMessage(String(error));
      }).then(() => {
      });
  }
};

/**
 * Matches following attributes in Markdown-typed image: [, alt, src, title]
 *
 * Example:
 * ![Lorem](image.jpg) -> [, "Lorem", "image.jpg"]
 * ![](image.jpg "Ipsum") -> [, "", "image.jpg", "Ipsum"]
 * ![Lorem](image.jpg "Ipsum") -> [, "Lorem", "image.jpg", "Ipsum"]
 */
const IMAGE_INPUT_REGEX = /!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\)/;

class Image extends Node {
  get name() {
    return "image";
  }

  get schema() {
    return {
      inline: true,
      attrs: {
        src: {},
        alt: {
          default: null,
        },
        title: {
          default: null,
        },
      },
      group: "inline",
      draggable: true,
      parseDOM: [
        {
          tag: "img[src]",
          getAttrs: (dom) => ({
            src: dom.getAttribute("src"),
            title: dom.getAttribute("title"),
            alt: dom.getAttribute("alt"),
          }),
        },
      ],
      toDOM: (node) => ["img", node.attrs],
    };
  }

  commands({ type }) {
    return (attrs) => (state, dispatch) => {
      console.log("image type", type);
      const { selection } = state;
      const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos;
      const node = type.create(attrs);
      const transaction = state.tr.insert(position, node);
      dispatch(transaction);
    };
  }

  inputRules({ type }) {
    return [
      nodeInputRule(IMAGE_INPUT_REGEX, type, (match) => {
        const [, alt, src, title] = match;
        return {
          src,
          alt,
          title,
        };
      }),
    ];
  }

  get plugins() {
    return [
      uploadPlaceholder,
      // uploadPlugin;
      new Plugin({
        props: {
          handleDOMEvents: {
            paste: async (view, event) => {
              console.log("paste");
              const { items } = event.clipboardData || event.originalEvent.clipboardData;
              console.log("items.lenght", items);
              if (items != null) {
                if (items[0] != null) {
                  items[0].getAsString((s) => {
                    console.log("r", s);
                  });
                }
                if (items[1] != null) {
                  items[1].getAsString((s) => {
                    console.log("r", s);
                  });
                }
                console.log("item", items[0]);
                console.log("item1", items[1]);
                const idUploadImage = items[1].kind === "file" && (/image/.test(items[1].type));
                if (idUploadImage) {
                  const { tr } = view.state;
                  if (!tr.selection.empty) {
                    tr.deleteSelection();
                  }
                  const pos = tr.selection.from;
                  event.preventDefault();

                  const files = Array.prototype.slice
                    .call(items)
                    .map((dt) => dt.getAsFile())
                    .filter((file) => file);
                  await insertFiles(view, event, pos, files);
                  return true;
                  // for (let idex = 0; idex < items.length;) {
                  //   idex += 1;
                  //   const { schema } = view.state;
                  //   const item = items[idex];
                  //   if (item != null && item.kind === "file" && /image/.test(item.type)) {
                  //     const image = item.getAsFile();
                  //     if (!image) {
                  //       return;
                  //     }
                  //     const formData = new FormData();
                  //     formData.append("file", image);
                  //     const r = await requestUploadFile1(formData);
                  //     const node = schema.nodes.image.create({
                  //       src: getKunImageUrl(r.msg),
                  //     });
                  //     const transaction = view.state.tr.replaceSelectionWith(node);
                  //     view.dispatch(transaction);
                  //   }
                  // }
                }
              }
            },
            drop(view, event) {
              console.log("drop");
              const hasFiles = event.dataTransfer
              && event.dataTransfer.files
              && event.dataTransfer.files.length;

              if (!hasFiles) {
                return;
              }

              const images = Array
                .from(event.dataTransfer.files)
                .filter((file) => (/image/i).test(file.type));

              if (images.length === 0) {
                return;
              }

              console.log("xxxxxxxxxxxx  images", images);
              event.preventDefault();

              const { schema } = view.state;
              const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY });

              images.forEach((image) => {
                const reader = new FileReader();
                console.log("read image");

                reader.onload = (readerEvent) => {
                  const node = schema.nodes.image.create({
                    src: readerEvent.target.result,
                  });
                  const transaction = view.state.tr.insert(coordinates.pos, node);
                  view.dispatch(transaction);
                };
                reader.readAsDataURL(image);
              });
            },
          },
        },
      }),
    ];
  }

  // pasteRules({ type }) {
  //   return [
  //     markPasteRule(/img/g, "h1", {
  //
  //     }),
  //   ];
  // }
}

class ListItem extends Node {
  get name() {
    return "list_item";
  }

  get schema() {
    return {
      content: "paragraph block*",
      defining: true,
      draggable: false,
      parseDOM: [
        { tag: "li" },
      ],
      toDOM: () => ["li", 0],
    };
  }

  keys({ type }) {
    return {
      Enter: splitListItem(type),
      Tab: sinkListItem(type),
      "Shift-Tab": liftListItem(type),
    };
  }
}

class OrderedList extends Node {
  get name() {
    return "ordered_list";
  }

  get schema() {
    return {
      attrs: {
        order: {
          default: 1,
        },
      },
      content: "list_item+",
      group: "block",
      parseDOM: [
        {
          tag: "ol",
          getAttrs: (dom) => ({
            order: dom.hasAttribute("start") ? +dom.getAttribute("start") : 1,
          }),
        },
      ],
      toDOM: (node) => (node.attrs.order === 1 ? ["ol", 0] : ["ol", { start: node.attrs.order }, 0]),
    };
  }

  commands({ type, schema }) {
    return () => toggleList(type, schema.nodes.list_item);
  }

  keys({ type, schema }) {
    return {
      "Shift-Ctrl-9": toggleList(type, schema.nodes.list_item),
    };
  }

  inputRules({ type }) {
    return [
      wrappingInputRule(
        /^(\d+)\.\s$/,
        type,
        (match) => ({ order: +match[1] }),
        (match, node) => node.childCount + node.attrs.order === +match[1],
      ),
    ];
  }
}

tableNodes({
  tableGroup: 'block',
  cellContent: 'block+',
  cellAttributes: {
    background: {
      default: null,
      getFromDOM(dom) {
        return dom.style.backgroundColor || null
      },
      setDOMAttr(value, attrs) {
        if (value) {
          const style = { style: `${(attrs.style || '')}background-color: ${value};` };
          Object.assign(attrs, style);
        }
      },
    },
  },
});

class Bold extends Mark {
  // eslint-disable-next-line class-methods-use-this
  get name() {
    return "bold";
  }

  get schema() {
    return {
      parseDOM: [
        {
          tag: "strong",
        },
        {
          tag: "b",
          getAttrs: (node) => node.style.fontWeight !== "normal" && null,
        },
        {
          style: "font-weight",
          getAttrs: (value) => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null,
        },
      ],
      toDOM: () => ["strong", 0],
    };
  }

  keys({ type }) {
    return {
      "Mod-b": toggleMark(type),
    };
  }

  commands({ type }) {
    console.log("commands bold", type);
    return () => toggleMark(type);
  }

  inputRules({ type }) {
    return [
      markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type),
    ];
  }

  pasteRules({ type }) {
    return [
      markPasteRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)/g, type),
    ];
  }
}

class Italic extends Mark {
  get name() {
    return "italic";
  }

  get schema() {
    return {
      parseDOM: [
        { tag: "i" },
        { tag: "em" },
        { style: "font-style=italic" },
      ],
      toDOM: () => ["em", 0],
    };
  }

  keys({ type }) {
    return {
      "Mod-i": toggleMark(type),
    };
  }

  commands({ type }) {
    return () => toggleMark(type);
  }

  inputRules({ type }) {
    return [
      markInputRule(/(?:^|[^_])(_([^_]+)_)$/, type),
      markInputRule(/(?:^|[^*])(\*([^*]+)\*)$/, type),
    ];
  }

  pasteRules({ type }) {
    return [
      markPasteRule(/_([^_]+)_/g, type),
      markPasteRule(/\*([^*]+)\*/g, type),
    ];
  }
}

class Link extends Mark {
  get name() {
    return "link";
  }

  get defaultOptions() {
    return {
      openOnClick: true,
    };
  }

  get schema() {
    return {
      attrs: {
        href: {
          default: null,
        },
      },
      inclusive: false,
      parseDOM: [
        {
          tag: "a[href]",
          getAttrs: (dom) => ({
            href: dom.getAttribute("href"),
          }),
        },
      ],
      toDOM: (node) => ["a", {
        ...node.attrs,
        rel: "noopener noreferrer nofollow",
      }, 0],
    };
  }

  commands({ type }) {
    console.log(`comment type`, type);
    return (attrs) => {
      console.log(`type ${attrs}`, attrs);
      if (attrs.href) {
        return updateMark(type, attrs);
      }

      return removeMark(type);
    };
  }

  pasteRules({ type }) {
    return [
      pasteRule(
        /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-zA-Z]{2,}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g,
        type,
        (url) => ({ href: url }),
      ),
    ];
  }

  get plugins() {
    if (!this.options.openOnClick) {
      return [];
    }

    return [
      new Plugin({
        props: {
          handleClick: (view, pos, event) => {
            const { schema } = view.state;
            const attrs = getMarkAttrs(view.state, schema.marks.link);

            if (attrs.href && event.target instanceof HTMLAnchorElement) {
              event.stopPropagation();
              window.open(attrs.href);
            }
          },
        },
      }),
    ];
  }
}

class Strike extends Mark {
  get name() {
    return "strike";
  }

  get schema() {
    return {
      parseDOM: [
        {
          tag: "s",
        },
        {
          tag: "del",
        },
        {
          tag: "strike",
        },
        {
          style: "text-decoration",
          getAttrs: (value) => value === "line-through",
        },
      ],
      toDOM: () => ["s", 0],
    };
  }

  keys({ type }) {
    return {
      "Mod-d": toggleMark(type),
    };
  }

  commands({ type }) {
    return () => toggleMark(type);
  }

  inputRules({ type }) {
    return [
      markInputRule(/~([^~]+)~$/, type),
    ];
  }

  pasteRules({ type }) {
    return [
      markPasteRule(/~([^~]+)~/g, type),
    ];
  }
}

class Underline extends Mark {
  get name() {
    return "underline";
  }

  get schema() {
    return {
      parseDOM: [
        {
          tag: "u",
        },
        {
          style: "text-decoration",
          getAttrs: (value) => value === "underline",
        },
      ],
      toDOM: () => ["u", 0],
    };
  }

  keys({ type }) {
    return {
      "Mod-u": toggleMark(type),
    };
  }

  commands({ type }) {
    return () => toggleMark(type);
  }
}

class KunUrl extends Node {
  get name() {
    return "url";
  }

  get schema() {
    return {
      inline: true,
      group: "inline",
      atom: true,
      draggable: true,
      attrs: {
        title: {
        },
        url: {
        },
      },
      toDOM: (node) => ["kun-ex-link", node.attrs],
      parseDOM: [
        {
          tag: "kun-ex-link",
          getAttrs: (dom) => ({
            url: dom.getAttribute("url"),
            title: dom.getAttribute("title"),
          }),
        },
      ],
    };
  }

  // get schema() {
  //   return {
  //     // content: "inline*",
  //     group: "inline",
  //     inline: true,
  //     // group: "block",
  //     // defining: true,
  //     draggable: false,
  //     attrs: {
  //       iconType: {
  //         default: "comment",
  //       },
  //       iconWidth: {
  //         default: 16,
  //       },
  //       iconHeight: {
  //         default: 16,
  //       },
  //     },
  //     // parseDOM: [
  //     //   { tag: "kun-icon" },
  //     // ],
  //     parseDOM: [{
  //       tag: "kun-icon",
  //       getAttrs: (dom) => {
  //         const type = dom.getAttribute("iconType");
  //         if (type != null) {
  //           return {
  //             iconType: type,
  //           };
  //         }
  //         return false;
  //       },
  //     }],
  //     toDOM: (node) => ["kun-icon", {...node.attrs,
  //       iconType: "content",
  //       iconWidth: 18,
  //       iconHeight: 18,
  //     }, 0],
  //   };
  // }

  commands({ type }) {
    console.log("commands iconp");
    console.log(`commands iconp ${type}`, type);
    return (attrs) => (state, dispatch) => {
      const { selection } = state;
      const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos;
      const node = type.create(attrs);
      const transaction = state.tr.insert(position, node);
      dispatch(transaction);
    };
  }
}

class Placeholder extends Extension {
  get name() {
    return "placeholder";
  }

  get defaultOptions() {
    return {
      emptyEditorClass: "is-editor-empty",
      emptyNodeClass: "is-empty",
      emptyNodeText: "Write something …",
      showOnlyWhenEditable: true,
      showOnlyCurrent: true,
    };
  }

  get plugins() {
    return [
      new Plugin({
        props: {
          decorations: ({ doc, plugins, selection }) => {
            const editablePlugin = plugins.find((plugin) => plugin.key.startsWith("editable$"));
            const editable = editablePlugin.props.editable();
            const active = editable || !this.options.showOnlyWhenEditable;
            const { anchor } = selection;
            const decorations = [];
            const isEditorEmpty = doc.textContent.length === 0;

            if (!active) {
              return false;
            }

            doc.descendants((node, pos) => {
              const hasAnchor = anchor >= pos && anchor <= (pos + node.nodeSize);
              const isNodeEmpty = node.content.size === 0;

              if ((hasAnchor || !this.options.showOnlyCurrent) && isNodeEmpty) {
                const classes = [this.options.emptyNodeClass];

                if (isEditorEmpty) {
                  classes.push(this.options.emptyEditorClass);
                }

                const decoration = Decoration.node(pos, pos + node.nodeSize, {
                  class: classes.join(" "),
                  "data-empty-text": typeof this.options.emptyNodeText === "function"
                    ? this.options.emptyNodeText(node)
                    : this.options.emptyNodeText,
                });
                decorations.push(decoration);
              }

              return false;
            });

            return DecorationSet.create(doc, decorations);
          },
        },
      }),
    ];
  }
}

class ImageView {
  
  constructor(node) {
    // The editor will use this as the node's DOM representation
    this.dom = document.createElement("img");
    this.dom.src = node.attrs.src;
    this.dom.addEventListener("click", (e) => {
      console.log("You clicked me!");
      e.preventDefault();
    });
  }
  stopEvent() { return true; }
}

class TodoView {
    

    updateAttrs(attrs) {
      if (!this.view.editable) {
        return;
      }

      const { state } = this.view;
      const { type } = this.node;
      const pos = this.getPos();
      const newAttrs = {
        ...this.node.attrs,
        ...attrs,
      };
      const transaction = this.isMark
        ? state.tr
          .removeMark(pos.from, pos.to, type)
          .addMark(pos.from, pos.to, type.create(newAttrs))
        : state.tr.setNodeMarkup(pos, null, newAttrs);

      console.log("this.view.dispatch(transaction)");
      this.view.dispatch(transaction);
    }

    

    

    

    

    

    constructor(node, view, getPos) {
      this.view = view;
      this.node = node;
      this.isNode = !!this.node.marks;
      this.isMark = !this.isNode;
      this.getPos = getPos;
      this.updateAttrs = this.updateAttrs.bind(this);

      // The editor will use this as the node's DOM representation
      // this.dom = document.createElement("kun-checkbox");
      // this.dom.checked = node.attrs.done;
      // const b = document.createElement("li");
      const node1 = document.createElement("LI"); // Create a <li> node
      node1.setAttribute("data-type", "todo_item");
      node1.setAttribute("data-done", node.attrs.done.toString());
      // adata-type=
      node1.className += "todo_item";
      const textnode = document.createElement("span");
      textnode.className += "todo-checkbox";
      // todo-checkbox

      const textnode2 = document.createElement("div");
      textnode2.contenteditable = true;
      textnode2.ref = "todo-content";
      textnode2.className += "todo-content";
      textnode2.class = "todo-content";
      textnode2.setAttribute("contenteditable", "true");
      // render(aHtml, this.dom);
      // console.log("this.dom", this.dom == null);
      // console.log("this.dom");
      node1.appendChild(textnode);
      node1.appendChild(textnode2);
      // b.appendChild("<span class=\"todo-checkbox\" contenteditable=\"false\"></span>");
      // eslint-disable-next-line max-len
      // b.appendChild("<div class=\"todo-content\" ref=\"content\" contenteditable=\"true\"\"></div>");
      this.dom = node1;
      this.dom["data-type"] = node.type.name;
      this.dom["data-done"] = node.attrs.done.toString();
      this.dom["data-drag-handle"] = "true";

      // this.dom.replace(
      //   `<li className="dddddddddddddd" data-type=${node.type.name} data-done="${node.attrs.done.toString()}" data-drag-handle>
      //           <span class="todo-checkbox" contenteditable="false"></span>
      //           <div class="todo-content" ref="content" contenteditable="true""></div>
      //       </li>
      //     `,
      // );
      //
      const D = (e) => {
        console.log("You clicked me toddddddddddddddddo!");
        console.log(this.node.attrs.done);
        console.log(this.view);
        this.updateAttrs({
          done: !this.node.attrs.done,
        });
        e.preventDefault();
      };
      // textnode.addEventListener("click", D.bind(this));
      // this.dom.addEventListener("click", () => {
      //   console.log("a");
      // });
      this.dom.addEventListener("click", D.bind(this));
      // return this.dom;
    }

    stopEvent() { return true; }
}

function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }

const iOptionNoTitle = {
  emptyDocument: {
    type: "doc",
    content: [
      {
        type: "paragraph",
        content: [
          {
            type: "text",
            text: "This is some inserted text. 👋",
          },
        ],
      },
    ],
  },
  parseOptions: {},
};

const iOptionTitle = {
  emptyDocument: {
    type: "doc",
    content: [{
      type: "title",
      content: [
        {
          type: "text",
          text: "xxxxxxxxx",
        },
      ],
    },
    {
      type: "paragraph",
      content: [
        {
          type: "text",
          text: "This is some inserted text. 👋",
        },
      ],
    },

    ],
  },
  parseOptions: {},
};


const createDocument = (schema, content, hasTitle) => {
  console.log("content", content);
  console.log("schema", schema);
  if (content == null) {
    return schema.nodeFromJSON(hasTitle ? iOptionTitle.emptyDocument : iOptionNoTitle.emptyDocument);
  }

  if (typeof content === "object") {
    try {
      return schema.nodeFromJSON(content);
    } catch (error) {
      console.log(error);
      console.log("xxxxxxxxxxxxxxxxxxxxxxxx1");
      console.log(error);
      console.warn("[tiptap warn]: Invalid content.", "Passed value:", content, "Error:", error);
      return schema.nodeFromJSON(hasTitle ? iOptionTitle.emptyDocument : iOptionNoTitle.emptyDocument);
    }
  }

  if (typeof content === "string") {
    const element = document.createElement("div");
    element.innerHTML = content.trim();

    return DOMParser.fromSchema(schema).parse(element, {});
  }

  return false;
};
class PEditor  {
    

    





    set menu(menu) {
      this._menu = menu;
    }

    get menu() {
      return this._menu;
    }

    on(event, fn) {
      this._callbacks = this._callbacks || {};
      // Create namespace for this event
      if (!this._callbacks[event]) {
        this._callbacks[event] = [];
      }
      this._callbacks[event].push(fn);
      return this;
    }

    emit(event, ...args) {
      this._callbacks = this._callbacks || {};
      const callbacks = this._callbacks[event];

      if (callbacks) {
        callbacks.forEach((callback) => callback.apply(this, args));
      }

      return this;
    }


    // Remove event listener for given event.
    // If fn is not provided, all event listeners for that event will be removed.
    // If neither is provided, all event listeners will be removed.
    off(event, fn) {
      if (!arguments.length) {
        this._callbacks = {};
      } else {
        // event listeners for the given event
        const callbacks = this._callbacks ? this._callbacks[event] : null;
        if (callbacks) {
          if (fn) {
            this._callbacks[event] = callbacks.filter((cb) => cb !== fn); // remove specific handler
          } else {
            delete this._callbacks[event]; // remove all handlers
          }
        }
      }

      return this;
    }

    


    __init() {this.extensions =null;}

    __init2() {this.events = [
      "init",
      "transaction",
      "update",
      "focus",
      "blur",
      "paste",
      "drop",
    ];}

    

    

     get view_1() {
      return this.view;
    }

    __init3() {this.selection = { from: 0, to: 0 };}

    __init4() {this.hasTitle = false;}

    constructor(el, updateV, updateFloat, defaultContent, hasTitle) {PEditor.prototype.__init.call(this);PEditor.prototype.__init2.call(this);PEditor.prototype.__init3.call(this);PEditor.prototype.__init4.call(this);PEditor.prototype.__init5.call(this);PEditor.prototype.__init6.call(this);PEditor.prototype.__init7.call(this);PEditor.prototype.__init8.call(this);PEditor.prototype.__init9.call(this);
      console.log("exeditor", hasTitle);
      const options = {
        onUpdate: (r) => updateV(r),
      };
      this.events.forEach((name) => {
        this.on(name, options[camelCase(`on ${name}`)] || (() => {}));
      });

      this.options = hasTitle ? iOptionTitle : iOptionNoTitle;

      const extensionManager = new ExtensionManager([
        new KunUrl(),
        new HardBreak(),
        new Link(),
        new Text(),
        new Placeholder({
          showOnlyCurrent: false,
          emptyNodeText: (node) => {
            if (node.type.name === "title") {
              return "Give me a name";
            }
            return "Write something";
          },
        }),
        new Image(),
        new Paragraph(),
        new Blockquote(),
        new Heading({ levels: [2, 3] }),
        new BulletList(),
        new OrderedList(),
        new ListItem(),
        new Bold(),
        new Italic(),
        new Strike(),
        new Underline(),
        // new KunIconP(),
        new CodeBlockHighlight({
          languages: {
            scala,
            javascript,
            python,
            css,
          },
        }),
      ].concat(...(hasTitle ? [new DocTitle(), new Title()] : [new Doc()])), undefined);

      this.hasTitle = hasTitle;
      this.extensions = extensionManager.extensions;
      const createSchema = () => {
        console.log("nodes");
        console.log(
          extensionManager.nodes,
        );
        console.log("marks");
        console.log(
          extensionManager.marks,
        );
        return new Schema({
          topNode: "doc",
          nodes: extensionManager.nodes,
          marks: extensionManager.marks,
        });
      };
      const schema = createSchema();
      console.log("extensionManager.nodes", schema);
      this.schema = schema;
      const keyMap = extensionManager.keymaps({
        schema,
      });

      const iPut = extensionManager.inputRules({
        schema,
        excludedExtensions: [],
      });

      const pasteRules = extensionManager.pasteRules({
        schema,
        excludedExtensions: [],
      });
      const state = EditorState.create({
        schema,
        doc: createDocument(schema, defaultContent, hasTitle),
        plugins: [
          ...extensionManager.plugins,
          keymap(baseKeymap),
          ...keyMap,
          // gapCursor(),
          new Plugin({
            key: new PluginKey("editable"),
            props: {
              editable: () => true,
            },
          }),
          new Plugin({
            props: {
              attributes: {
                tabindex: 0,
              },
              handleDOMEvents: {
                focus: (view, event) => {
                  this.focus.bind(this)(view, event);
                },
                blur: (view, event) => {
                  this.blur.bind(this)(view, event);
                },
              },
            },
          }),
          // FloatingMenu({
          //   editor: this,
          //   element: elLink,
          //   onUpdate: (item) => onUpdateFloat(item, updateFloat),
          // }),
          MenuBar({
            element: el,
          }),
          // commands1,
          // pasteRules,
          ...pasteRules,
          inputRules({
            rules: iPut,
          }),
        ],
      });
      const view = new EditorView(el, {
        state,
        dispatchTransaction: this.dispatchTransaction.bind(this),
        nodeViews: {
          image(node) { return new ImageView(node); },
          todo_item(node, view, getPos) { return new TodoView(node, view, getPos); },
        },
      });
      this.view = view;
      this.extensions.view = this.view;
    }

    

    

    showLinkMenu(attrs) {
      this.linkUrl = attrs.href;
      this.linkMenuIsActive = true;
      // this.$nextTick(() => {
      //     this.$refs.linkInput.focus()
      // })
    }

    hideLinkMenu() {
      this.linkUrl = null;
      this.linkMenuIsActive = false;
    }

    setLinkUrl(command, url) {
      command({ href: url });
      this.hideLinkMenu();
    }

    __init5() {this.options = {
    };}
    // options = {
    //   emptyDocument: {
    //     type: "doc",
    //     content: [
    //       {
    //         type: "paragraph",
    //         content: [
    //           {
    //             type: "title",
    //             text: "填写标题",
    //           },
    //           {
    //             type: "text",
    //             text: "请填写内容",
    //           },
    //         ],
    //       },
    //     ],
    //   },
    //   parseOptions: {},
    // }

    createDocument(content, parseOptions = this.options.parseOptions) {
      console.log("content");
      if (content == null) {
        return this.schema.nodeFromJSON(this.options.emptyDocument);
      }

      if (typeof content === "object") {
        try {
          return this.schema.nodeFromJSON(content);
        } catch (error) {
          console.warn("[tiptap warn]: Invalid content.", "Passed value:", content, "Error:", error);
          return this.schema.nodeFromJSON(this.options.emptyDocument);
        }
      }

      if (typeof content === "string") {
        const element = document.createElement("div");
        element.innerHTML = content.trim();

        return DOMParser.fromSchema(this.schema).parse(element, parseOptions);
      }

      return false;
    }


    dispatchTransaction(transaction) {
      const newState = this.view.state.apply(transaction);
      this.view.updateState(newState);

      this.selection = {
        from: this.view.state.selection.from,
        to: this.view.state.selection.to,
      };
      this.setActiveNodesAndMarks.bind(this)();

      this.emit("transaction", {
        getHTML: this.getHTML.bind(this),
        getJSON: this.getJSON.bind(this),
        state: this.view.state,
        transaction,
      });

      if (!transaction.docChanged || transaction.getMeta("preventUpdate")) {
        return;
      }

      this.emitUpdate(transaction);
    }

    emitUpdate(transaction) {
      const active = this.getActiveMap();
      console.log("isActiveA", active);
      this.emit("update", {
        getHTML: this.getHTML.bind(this),
        getJSON: this.getJSON.bind(this),
        state: this.view.state,
        active,
        transaction,
      });
    }

    resolveSelection(position = null) {
      if (this.selection && position === null) {
        return this.selection;
      }

      if (position === "start" || position === true) {
        return {
          from: 0,
          to: 0,
        };
      }

      if (position === "end") {
        const { doc } = this.view.state;
        return {
          from: doc.content.size,
          to: doc.content.size,
        };
      }

      return {
        from: position,
        to: position,
      };
    }

    focus(position = null) {
      if ((this.view.focused && position === null) || position === false) {
        return;
      }

      const { from, to } = this.resolveSelection(position);

      this.setSelection(from, to);
      setTimeout(() => this.view.focus(), 10);
    }

    setSelection(from = 0, to = 0) {
      const { doc, tr } = this.view.state;
      const resolvedFrom = minMax(from, 0, doc.content.size);
      const resolvedEnd = minMax(to, 0, doc.content.size);
      const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd);
      const transaction = tr.setSelection(selection);

      this.view.dispatch(transaction);
    }

    blur() {
      this.view.dom.blur();
    }

    getSchemaJSON() {
      return JSON.parse(JSON.stringify({
        nodes: this.extensions.nodes,
        marks: this.extensions.marks,
      }));
    }

    getHTML() {
      const div = document.createElement("div");
      const fragment = DOMSerializer
        .fromSchema(this.schema)
        .serializeFragment(this.view.state.doc.content);

      div.appendChild(fragment);

      return div.innerHTML;
    }

    getJSON() {
      return this.view.state.doc.toJSON();
    }

    setContent(content = {}, emitUpdate = false, parseOptions = {}) {
      console.log("setContent");
      const { doc, tr } = this.view.state;
      const document = this.createDocument(content, parseOptions);
      const selection = TextSelection.create(doc, 0, doc.content.size);
      const transaction = tr
        .setSelection(selection)
        .replaceSelectionWith(document, false)
        .setMeta("preventUpdate", !emitUpdate);

      this.view.dispatch(transaction);
    }

    clearContent(emitUpdate = false) {
      this.setContent(this.options.emptyDocument, emitUpdate);
    }

    __init6() {this.activeMarks = {};}

    __init7() {this.activeMarkAttrs = {};}

    __init8() {this.activeNodes ={};}

    getMarkAttrs(type = null) {
      return this.activeMarkAttrs[type];
    }


    setActiveNodesAndMarks() {
      this.activeMarks = Object
        .entries(this.schema.marks)
        .reduce((marks, [name, mark]) => ({
          ...marks,
          [name]: (attrs = {}) => markIsActive(this.view.state, mark),
        }), {});

      this.activeMarkAttrs = Object
        .entries(this.schema.marks)
        .reduce((marks, [name, mark]) => ({
          ...marks,
          [name]: this.getMarkAttrs(this.view.state, mark),
        }), {});

      this.activeNodes = Object
        .entries(this.schema.nodes)
        .reduce((nodes, [name, node]) => ({
          ...nodes,
          [name]: (attrs = {}) => nodeIsActive(this.view.state, node, attrs),
        }), {});
    }

    getNodeAttrs1(type = null) {
      return {
        ...getNodeAttrs(this.view.state, this.schema.nodes[type]),
      };
    }

    isActiveA() {
      return Object
        .entries({
          ...this.activeMarks,
          ...this.activeNodes,
        })
        .reduce((types, [name, value]) => ({
          ...types,
          [name]: (attrs = {}) => value(attrs),
        }), {});
    }

    get isActive() {
      return Object
        .entries({
          ...this.activeMarks,
          ...this.activeNodes,
        })
        .reduce((types, [name, value]) => ({
          ...types,
          [name]: (attrs = {}) => value(attrs),
        }), {});
    }

    getActiveMap() {
      const r = Object
        .entries({
          ...this.activeMarks,
          ...this.activeNodes,
        })
        .reduce((types, [name, value]) => ({
          ...types,
          [name]: value(),
        }), {});
      return r;
    }

    get isActive() {
      return Object
        .entries({
          ...this.activeMarks,
          ...this.activeNodes,
        })
        .reduce((types, [name, value]) => ({
          ...types,
          [name]: (attrs = {}) => value(attrs),
        }), {});
    }

    

     focus1(view, event) {
      this.focused = true;
      this.emit("focus", {
        event,
        state: this.view.state,
        view,
      });

      const transaction = this.view.state.tr.setMeta("focused", true);
      this.view.dispatch(transaction);
    }

     blur1(view, event) {
      this.focused = false;
      this.emit("blur", {
        event,
        state: view.state,
        view,
      });

      const transaction = this.view.state.tr.setMeta("focused", false);
      this.view.dispatch(transaction);
    }


     __init9() {this.getC = this.getCommands.bind(this);}

    insertHref(url) {
      console.log(`url${url}`);
      _optionalChain([this, 'access', _ => _.getC, 'optionalCall', _2 => _2(), 'optionalAccess', _3 => _3.link, 'call', _4 => _4({ href: url })]);
    }

    insertIcon(url, title) {
      console.log("insertIcon xxxxxxxxx", url);
      console.log("insertIcon xxxxxxxxx", title);
      const { $from } = this.view.state.selection;
      const index = $from.index();
      console.log(`index ${index}`);
      console.log("this.schema.nodes.iconp", this.schema.nodes.url);
      if ($from.parent.canReplaceWith(index, index, this.schema.nodes.url.create({
        title,
        url,
      }))) {
        return false;
      }
      const image = this.schema.nodes.url.create({ iconType: "comment",
        title,
        url,
      });
      if (this.view.dispatch) this.view.dispatch(this.view.state.tr.replaceSelectionWith(image));
    }

    insertImage(url) {
      const { $from } = this.view.state.selection;
      const index = $from.index();
      console.log("this.schema.nodes.image", this.schema.nodes.image);
      if ($from.parent.canReplaceWith(index, index, this.schema.nodes.image.create({ src: url }))) {
        return false;
      }
      const image = this.schema.nodes.image.create({ src: url });
      if (this.view.dispatch) this.view.dispatch(this.view.state.tr.replaceSelectionWith(image));
    }

     getCommands() {
      const { schema } = this;
      return this.extensions
        .filter((extension) => extension.commands)
        .reduce((allCommands, extension) => {
          const { name, type } = extension;
          const commands = {};
          const value = extension.commands({
            schema,
            ...["node", "mark"].includes(type) ? {
              type: schema[`${type}s`][name],
            } : {},
          });

          const apply = (cb, attrs) => cb(attrs)(this.view.state, this.view.dispatch, this.view);
          const handle = (_name, _value) => {
            if (Array.isArray(_value)) {
              commands[_name] = (attrs) => _value.forEach((callback) => apply(callback, attrs));
            } else if (typeof _value === "function") {
              commands[_name] = (attrs) => apply(_value, attrs);
            }
          };

          if (typeof value === "object") {
            Object.entries(value).forEach(([commandName, commandValue]) => {
              handle(commandName, commandValue);
            });
          } else {
            handle(name, value);
          }

          return {
            ...allCommands,
            ...commands,
          };
        }, {});
    }
}

const defaultHtmlStyle = `
 ${style};
 :host {
  background: white;
 }
 
 img {
  max-width: 100%;
 }
 
 .editor {
  padding: 20px;
  min-height: 180px !important;
 }
.editor *.is-empty:nth-child(1)::before,
.editor *.is-empty:nth-child(2)::before {
  content: attr(data-empty-text);
  float: left;
  color: #aaa;
  pointer-events: none;
  height: 0;
  font-style: italic;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-touch-callout: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility; }
  *:focus {
    outline: none; }

*::before,
*::after {
  box-sizing: border-box; }

html {
  font-family: 'Inter';
  font-size: 18px;
  color: #000000;
  line-height: 1.5; }

body {
  margin: 0; }

a {
  color: inherit; }

h1,
h2,
h3,
p,
ul,
ol,
pre,
blockquote {
  margin: 1rem 0; }
  h1:first-child,
  h2:first-child,
  h3:first-child,
  p:first-child,
  ul:first-child,
  ol:first-child,
  pre:first-child,
  blockquote:first-child {
    margin-top: 0; }
  h1:last-child,
  h2:last-child,
  h3:last-child,
  p:last-child,
  ul:last-child,
  ol:last-child,
  pre:last-child,
  blockquote:last-child {
    margin-bottom: 0; }

h1,
h2,
h3 {
  line-height: 1.3; }

.button {
  font-weight: bold;
  display: inline-flex;
  background: transparent;
  border: 0;
  color: #000000;
  padding: 0.2rem 0.5rem;
  margin-right: 0.2rem;
  border-radius: 3px;
  cursor: pointer;
  background-color: rgba(0, 0, 0, 0.1); }
  .button:hover {
    background-color: rgba(0, 0, 0, 0.15); }

.message {
  background-color: rgba(0, 0, 0, 0.05);
  color: rgba(0, 0, 0, 0.7);
  padding: 1rem;
  border-radius: 6px;
  margin-bottom: 1.5rem;
  font-style: italic; }

.editor {
  position: relative;
  max-width: 100%;
  background: white;
  margin: 0 auto 5rem auto; }
  .editor__content {
    overflow-wrap: break-word;
    word-wrap: break-word;
    word-break: break-word; }
    .editor__content * {
      caret-color: currentColor; }
    .editor__content pre {
      padding: 0.7rem 1rem;
      border-radius: 5px;
      background: rgb(247, 246, 243) !important;
      color: black !important;
      font-size: 0.8rem;
      overflow-x: auto; }
      .editor__content pre code {
        display: block; }
    .editor__content p code {
      padding: 0.2rem 0.4rem;
      border-radius: 5px;
      font-size: 0.8rem;
      font-weight: bold;
      background: rgba(0, 0, 0, 0.1);
      color: rgba(0, 0, 0, 0.8); }
    .editor__content ul,
    .editor__content ol {
      padding-left: 1rem; }
    .editor__content li > p,
    .editor__content li > ol,
    .editor__content li > ul {
      margin: 0; }
    .editor__content a {
      color: inherit; }
    .editor__content blockquote {
      border-left: 3px solid rgba(0, 0, 0, 0.1);
      color: rgba(0, 0, 0, 0.8);
      padding-left: 0.8rem;
      font-style: italic; }
      .editor__content blockquote p {
        margin: 0; }
    .editor__content img {
      display: flex;
      margin: 0 auto;
      max-width: 100%;
      border-radius: 3px; }
    .editor__content table {
      border-collapse: collapse;
      table-layout: fixed;
      width: 100%;
      margin: 0;
      overflow: hidden; }
      .editor__content table td, .editor__content table th {
        min-width: 1em;
        border: 2px solid #dddddd;
        padding: 3px 5px;
        vertical-align: top;
        box-sizing: border-box;
        position: relative; }
        .editor__content table td > *, .editor__content table th > * {
          margin-bottom: 0; }
      .editor__content table th {
        font-weight: bold;
        text-align: left; }
      .editor__content table .selectedCell:after {
        z-index: 2;
        position: absolute;
        content: "";
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        background: rgba(200, 200, 255, 0.4);
        pointer-events: none; }
      .editor__content table .column-resize-handle {
        position: absolute;
        right: -2px;
        top: 0;
        bottom: 0;
        width: 4px;
        z-index: 20;
        background-color: #adf;
        pointer-events: none; }
    .editor__content .tableWrapper {
      margin: 1em 0;
      overflow-x: auto; }
    .editor__content .resize-cursor {
      cursor: ew-resize;
      cursor: col-resize; }
  .editor pre::before {
    content: attr(data-language);
    text-transform: uppercase;
    display: block;
    text-align: right;
    font-weight: bold;
    font-size: 0.6rem; }
  .editor pre code .hljs-comment,
  .editor pre code .hljs-quote {
    color: #999999; }
  .editor pre code .hljs-variable,
  .editor pre code .hljs-template-variable,
  .editor pre code .hljs-attribute,
  .editor pre code .hljs-tag,
  .editor pre code .hljs-name,
  .editor pre code .hljs-regexp,
  .editor pre code .hljs-link,
  .editor pre code .hljs-name,
  .editor pre code .hljs-selector-id,
  .editor pre code .hljs-selector-class {
    color: #f2777a; }
  .editor pre code .hljs-number,
  .editor pre code .hljs-meta,
  .editor pre code .hljs-built_in,
  .editor pre code .hljs-builtin-name,
  .editor pre code .hljs-literal,
  .editor pre code .hljs-type,
  .editor pre code .hljs-params {
    color: #f99157; }
  .editor pre code .hljs-string,
  .editor pre code .hljs-symbol,
  .editor pre code .hljs-bullet {
    color: #99cc99; }
  .editor pre code .hljs-title,
  .editor pre code .hljs-section {
    color: #ffcc66; }
  .editor pre code .hljs-keyword,
  .editor pre code .hljs-selector-tag {
    color: #6699cc; }
  .editor pre code .hljs-emphasis {
    font-style: italic; }
  .editor pre code .hljs-strong {
    font-weight: 700; }

.menubar {
  margin-bottom: 1rem;
  transition: visibility 0.2s 0.4s, opacity 0.2s 0.4s; }
  .menubar.is-hidden {
    visibility: hidden;
    opacity: 0; }
  .menubar.is-focused {
    visibility: visible;
    opacity: 1;
    transition: visibility 0.2s, opacity 0.2s; }
  .menubar__button {
    font-weight: bold;
    display: inline-flex;
    background: transparent;
    border: 0;
    color: #000000;
    padding: 0.2rem 0.5rem;
    margin-right: 0.2rem;
    border-radius: 3px;
    cursor: pointer; }
    .menubar__button:hover {
      background-color: rgba(0, 0, 0, 0.05); }
    .menubar__button.is-active {
      background-color: rgba(0, 0, 0, 0.1); }
  .menubar span.menubar__button {
    font-size: 13.3333px; }

.menububble {
  position: absolute;
  display: flex;
  z-index: 20;
  background: #000000;
  border-radius: 5px;
  padding: 0.3rem;
  margin-bottom: 0.5rem;
  transform: translateX(-50%);
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.2s, visibility 0.2s; }
  .menububble.is-active {
    opacity: 1;
    visibility: visible; }
  .menububble__button {
    display: inline-flex;
    background: transparent;
    border: 0;
    color: #ffffff;
    padding: 0.2rem 0.5rem;
    margin-right: 0.2rem;
    border-radius: 3px;
    cursor: pointer; }
    .menububble__button:last-child {
      margin-right: 0; }
    .menububble__button:hover {
      background-color: rgba(255, 255, 255, 0.1); }
    .menububble__button.is-active {
      background-color: rgba(255, 255, 255, 0.2); }
  .menububble__form {
    display: flex;
    align-items: center; }
  .menububble__input {
    font: inherit;
    border: none;
    background: transparent;
    color: #ffffff; }
.editor {
  position: relative;
  margin: 0 auto 5rem auto; }
  .editor__content {
    overflow-wrap: break-word;
    word-wrap: break-word;
    word-break: break-word; }
    .editor__content * {
      caret-color: currentColor; }
    .editor__content pre {
      padding: 0.7rem 1rem;
      border-radius: 5px;
      
      background: rgb(247, 246, 243);
      color: black;
      font-size: 0.8rem;
      overflow-x: auto; }
      .editor__content pre code {
        display: block; }
    .editor__content p code {
      padding: 0.2rem 0.4rem;
      border-radius: 5px;
      font-size: 0.8rem;
      font-weight: bold;
      background: rgba(0, 0, 0, 0.1);
      color: rgba(0, 0, 0, 0.8); }
    .editor__content ul,
    .editor__content ol {
      padding-left: 1rem; }
    .editor__content li > p,
    .editor__content li > ol,
    .editor__content li > ul {
      margin: 0; }
    .editor__content a {
      color: inherit; }
    .editor__content blockquote {
      border-left: 3px solid rgba(0, 0, 0, 0.1);
      color: rgba(0, 0, 0, 0.8);
      padding-left: 0.8rem;
      font-style: italic; }
      .editor__content blockquote p {
        margin: 0; }
    .editor__content img {
      max-width: 100%;
      border-radius: 3px; }
    .editor__content table {
      border-collapse: collapse;
      table-layout: fixed;
      width: 100%;
      margin: 0;
      overflow: hidden; }
      .editor__content table td, .editor__content table th {
        min-width: 1em;
        border: 2px solid #dddddd;
        padding: 3px 5px;
        vertical-align: top;
        box-sizing: border-box;
        position: relative; }
        .editor__content table td > *, .editor__content table th > * {
          margin-bottom: 0; }
      .editor__content table th {
        font-weight: bold;
        text-align: left; }
      .editor__content table .selectedCell:after {
        z-index: 2;
        position: absolute;
        content: "";
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        background: rgba(200, 200, 255, 0.4);
        pointer-events: none; }
      .editor__content table .column-resize-handle {
        position: absolute;
        right: -2px;
        top: 0;
        bottom: 0;
        width: 4px;
        z-index: 20;
        background-color: #adf;
        pointer-events: none; }
    .editor__content .tableWrapper {
      margin: 1em 0;
      overflow-x: auto; }
    .editor__content .resize-cursor {
      cursor: ew-resize;
      cursor: col-resize; }
  .editor pre::before {
    content: attr(data-language);
    text-transform: uppercase;
    display: block;
    text-align: right;
    font-weight: bold;
    font-size: 0.6rem; }
  .editor pre code .hljs-comment,
  .editor pre code .hljs-quote {
    color: #999999; }
  .editor pre code .hljs-variable,
  .editor pre code .hljs-template-variable,
  .editor pre code .hljs-attribute,
  .editor pre code .hljs-tag,
  .editor pre code .hljs-name,
  .editor pre code .hljs-regexp,
  .editor pre code .hljs-link,
  .editor pre code .hljs-name,
  .editor pre code .hljs-selector-id,
  .editor pre code .hljs-selector-class {
    color: #f2777a; }
  .editor pre code .hljs-number,
  .editor pre code .hljs-meta,
  .editor pre code .hljs-built_in,
  .editor pre code .hljs-builtin-name,
  .editor pre code .hljs-literal,
  .editor pre code .hljs-type,
  .editor pre code .hljs-params {
    color: #f99157; }
  .editor pre code .hljs-string,
  .editor pre code .hljs-symbol,
  .editor pre code .hljs-bullet {
    color: #99cc99; }
  .editor pre code .hljs-title,
  .editor pre code .hljs-section {
    color: #ffcc66; }
  .editor pre code .hljs-keyword,
  .editor pre code .hljs-selector-tag {
    color: #6699cc; }
  .editor pre code .hljs-emphasis {
    font-style: italic; }
  .editor pre code .hljs-strong {
    font-weight: 700; }
    
ul[data-type="todo_list"] {
  padding-left: 0; }

li[data-type="todo_item"] {
  display: flex;
  flex-direction: row; }

.todo-checkbox {
  border: 2px solid #000000;
  height: 0.9em;
  width: 0.9em;
  box-sizing: border-box;
  margin-right: 10px;
  margin-top: 0.3rem;
  user-select: none;
  -webkit-user-select: none;
  cursor: pointer;
  border-radius: 0.2em;
  background-color: transparent;
  transition: 0.4s background; }

.todo-content {
  flex: 1; }
  .todo-content > p:last-of-type {
    margin-bottom: 0; }
  .todo-content > ul[data-type="todo_list"] {
    margin: .5rem 0; }

li[data-done="true"] > .todo-content > p {
  text-decoration: line-through; }

li[data-done="true"] > .todo-checkbox {
  background-color: #000000; }

li[data-done="false"] {
  text-decoration: none; }
`;

const _jsxFileName$3 = "/Users/rang/rang/frond_ng/packages/six/src/components/kun-editor/kun-editor.jsx"; function _optionalChain$1(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function KunEditor() {
  const [defaultContent] = useProp("defaultContent");
  const [hasTitle] = useProp("hasTitle");
  const r = "<p>dddddd</p><kun-icon icon-type=\"comment\" />";

  const content = Maybe.fromNullable(defaultContent).orDefault(hasTitle ? "<h1>标题</h1><p>内容</p>" : r);

  const host = useHost();
  const ref = useRef();
  const refMenuBar = useRef();
  const refFile = useRef();
  const refLabel = useRef();
  const updateEditor = useEvent("MyEditorUpdate");
  const [editor, setEditor] = useState(null);
  const [showFloat, setShowFloat] = useState(null);
  const [activeState, setActive] = useState({});

  const onSubmitUrl = (event) => {
    const { title, url } = event.detail;
    editor.insertIcon(url, title);
    event.preventDefault();
  };

  const onSubmit = (event) => {
    const data = event.detail;
    const content1 = data.html;
    if (content1 != null) {
      const contentNew = hasTitle ? `<h1>${data.title}</h1>${content1}` : content1;
      editor.setContent(contentNew, true);
    }
  };

  const onMyUploadMarkdown = (event) => {
    const contentNew = `<h1>请填写标题</h1>${event.detail.content}`;
    editor.setContent(contentNew, true);
  };
  const updateImageFile = async (event) => {
    try {
      const file = event.target.files[0];
      const formData = new FormData();
      formData.set("file", file);
      const r = await requestUploadFile1(formData);
      const fileName = `https://file.wintercoming.xyz/${r.msg}`;
      _optionalChain$1([editor, 'optionalAccess', _ => _.insertImage, 'optionalCall', _2 => _2(fileName)]);
      console.log("r1", r);
    } catch (e) {
      console.error(e);
    }
  };

  const updateImage = () => {
    console.log("image");
    console.log("ref", refFile);
    refLabel.current.click();
  };
  const updateFloatEvt = (name) => {
    if (name === "show") {
      setShowFloat(true);
    } else {
      setShowFloat(false);
    }
  };
  const updateV = ({ getHTML, getJSON, active }) => {
    const html = getHTML();
    const json = getJSON();
    console.log("json", json);
    console.log("html", html);
    updateEditor({ html, json });
    setActive(active);
  };

  useEffect(() => {
    if (host.current != null) {
      const editorInstance = new PEditor(ref.current, updateV, updateFloatEvt, content, hasTitle);
      if (editor == null) {
        setEditor(editorInstance);
      }
      updateEditor({ html: editorInstance.getHTML(), json: editorInstance.getJSON() });
    }
    return () => {
    };
  }, [defaultContent]);

  // TODO style
  const style2 = useStylesheet(defaultHtmlStyle, style);
  return (
    h('host', { shadowDom: true, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 108}}
      , h('style', {__self: this, __source: {fileName: _jsxFileName$3, lineNumber: 109}}, style2)
      , h('div', { className: "editor", __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 110}}
        , h('div', { ref: refMenuBar, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 111}}
          , h('div', { className: "header-icons", __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 112}}
            , h('kun-icon', {
              iconType: "jiacu",
              iconHeight: 14,
              iconWidth: 14,
              className: activeState.bold ? "editor-menu bg-select" : "editor-menu bg",
              onclick: () => {
                  _optionalChain$1([editor, 'optionalAccess', _3 => _3.getC, 'optionalCall', _4 => _4(), 'optionalAccess', _5 => _5.bold, 'optionalCall', _6 => _6()]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 113}}
            )
            , h('kun-icon', {
              iconType: "xieti",
              iconHeight: 12,
              iconWidth: 12,
              className: activeState.italic ? "editor-menu bg-select" : "editor-menu bg",
              onclick: () => {
                    _optionalChain$1([editor, 'optionalAccess', _7 => _7.getC, 'optionalCall', _8 => _8(), 'optionalAccess', _9 => _9.italic, 'optionalCall', _10 => _10()]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 122}}
            )

            , h('kun-icon', {
              iconType: "liebiao",
              iconHeight: 14,
              iconWidth: 14,
              className: activeState.bullet_list ? "editor-menu bg-select" : "editor-menu bg",
              onclick: () => {
                  _optionalChain$1([editor, 'optionalAccess', _11 => _11.getC, 'optionalCall', _12 => _12(), 'optionalAccess', _13 => _13.bullet_list, 'optionalCall', _14 => _14()]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 132}}
            )

            , h('kun-icon', {
              iconType: "youxuliebiao",
              iconHeight: 14,
              iconWidth: 14,
              className: activeState.ordered_list ? "editor-menu bg-select" : "editor-menu bg",
              onclick: () => {
                  _optionalChain$1([editor, 'optionalAccess', _15 => _15.getC, 'optionalCall', _16 => _16(), 'optionalAccess', _17 => _17.ordered_list, 'optionalCall', _18 => _18()]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 142}}
            )

            , h('kun-icon', {
              iconType: "underline",
              iconHeight: 14,
              className: activeState.underline ? "editor-menu bg-select" : "editor-menu bg",
              iconWidth: 14,
              onclick: () => {
                  _optionalChain$1([editor, 'optionalAccess', _19 => _19.getC, 'optionalCall', _20 => _20(), 'optionalAccess', _21 => _21.underline, 'optionalCall', _22 => _22()]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 152}}
            )

            , h('kun-icon', {
              title: "yinyong",
              iconType: "yinyong",
              iconHeight: 14,
              className: activeState.blockquote ? "editor-menu bg-select" : "editor-menu bg",
              iconWidth: 14,
              onclick: () => {
                  _optionalChain$1([editor, 'optionalAccess', _23 => _23.getC, 'optionalCall', _24 => _24(), 'optionalAccess', _25 => _25.blockquote, 'optionalCall', _26 => _26()]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 162}}
            )

            , h('kun-icon', {
              iconType: "tupian",
              iconHeight: 14,
              iconWidth: 14,
              className: activeState.image ? "editor-menu bg-select" : "editor-menu bg",
              onclick: () => {
                console.log("jjjjjj");
                updateImage();
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 173}}
            )

            , h('kun-icon', {
              iconType: "h1",
              iconHeight: 14,
              iconWidth: 14,
              className: _optionalChain$1([editor, 'optionalAccess', _27 => _27.isActive, 'optionalAccess', _28 => _28.heading, 'optionalCall', _29 => _29({ level: 1 })]) ? "editor-menu bg-select" : "editor-menu bg",
              onclick: () => {
                _optionalChain$1([editor, 'optionalAccess', _30 => _30.getC, 'optionalCall', _31 => _31(), 'optionalAccess', _32 => _32.heading, 'optionalCall', _33 => _33({ level: 1 })]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 184}}
            )

            , h('kun-icon', {
              iconType: "h2",
              iconHeight: 14,
              iconWidth: 14,
              className: _optionalChain$1([editor, 'optionalAccess', _34 => _34.isActive, 'optionalAccess', _35 => _35.heading, 'optionalCall', _36 => _36({ level: 2 })]) ? "editor-menu bg-select" : "editor-menu bg",
              onclick: () => {
                _optionalChain$1([editor, 'optionalAccess', _37 => _37.getC, 'optionalCall', _38 => _38(), 'optionalAccess', _39 => _39.heading, 'optionalCall', _40 => _40({ level: 2 })]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 194}}
            )

            , h('kun-icon', {
              iconType: "h3",
              iconHeight: 14,
              className: _optionalChain$1([editor, 'optionalAccess', _41 => _41.isActive, 'optionalAccess', _42 => _42.heading, 'optionalCall', _43 => _43({ level: 3 })]) ? "editor-menu bg-select" : "editor-menu bg",
              iconWidth: 14,
              onclick: () => {
                  _optionalChain$1([editor, 'optionalAccess', _44 => _44.getC, 'optionalCall', _45 => _45(), 'optionalAccess', _46 => _46.heading, 'optionalCall', _47 => _47({ level: 3 })]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 204}}
            )

            , h('kun-import-url-dialog', { onMyImportUrl: onSubmitUrl, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 214}} )

            , h('kun-link-button', {
              'my-selected': _optionalChain$1([editor, 'optionalAccess', _48 => _48.isActive, 'optionalAccess', _49 => _49.link, 'optionalCall', _50 => _50()]),
              'my-url': _optionalChain$1([editor, 'optionalAccess', _51 => _51.getMarkAttrs, 'optionalCall', _52 => _52("href")]),
              onMyUpdate: (event) => {
                  _optionalChain$1([editor, 'optionalAccess', _53 => _53.insertHref, 'optionalCall', _54 => _54(event.detail.url)]);
              }, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 216}}
            )

            , h('kun-markdown-button', { onMyUpload: onMyUploadMarkdown, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 224}} )
            , h('kun-import-link-dialog-1', { onMySubmit: onSubmit, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 225}} )
          )
        )

        , h('input', { ref: refLabel, type: "file", className: "hidden", onchange: updateImageFile, __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 229}} )
        , h('div', { ref: ref, className: " editor__content" , __self: this, __source: {fileName: _jsxFileName$3, lineNumber: 230}} )
      )
    )
  );
}

KunEditor.props = {
  hasTitle: {
    type: Boolean,
    reflect: true,
  },
  defaultContent: {
    type: String,
    reflect: true,
    event: {
      type: "changeMessage",
    },
  },
};

var kunEditor = getComponentOrDefine("kun-editor", KunEditor);

export default kunEditor;
