├── .cursorrules
├── .gitignore
├── .npmignore
├── .npmrc
├── .prettierrc
├── .stylelintrc.json
├── .vscode
├── extensions.json
└── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README.zh-CN.md
├── TODO
├── biome.json
├── eslint.config.ts
├── index.html
├── jsconfig.json
├── package.json
├── public
└── favicon.png
├── src
├── app.vue
├── assets
│ ├── icons
│ │ ├── align-center.svg
│ │ ├── align-distributed.svg
│ │ ├── align-justify.svg
│ │ ├── align-left.svg
│ │ ├── align-right.svg
│ │ ├── arrow-down.svg
│ │ ├── assistant.svg
│ │ ├── audio.svg
│ │ ├── auto-width.svg
│ │ ├── background-color.svg
│ │ ├── barcode.svg
│ │ ├── block-add.svg
│ │ ├── block-menu.svg
│ │ ├── bold.svg
│ │ ├── bookmark.svg
│ │ ├── border-none.svg
│ │ ├── border.svg
│ │ ├── break-marks.svg
│ │ ├── bullet-list-2.svg
│ │ ├── bullet-list-circle.svg
│ │ ├── bullet-list-disc.svg
│ │ ├── bullet-list-square.svg
│ │ ├── bullet-list.svg
│ │ ├── callout.svg
│ │ ├── check.svg
│ │ ├── chinese-case.svg
│ │ ├── clear-cache.svg
│ │ ├── clear-format.svg
│ │ ├── clickable.svg
│ │ ├── close.svg
│ │ ├── code-block.svg
│ │ ├── code-line-number.svg
│ │ ├── code-word-wrap.svg
│ │ ├── code.svg
│ │ ├── color.svg
│ │ ├── columns.svg
│ │ ├── copy.svg
│ │ ├── date.svg
│ │ ├── diagrams.svg
│ │ ├── download.svg
│ │ ├── echarts.svg
│ │ ├── edit.svg
│ │ ├── embed.svg
│ │ ├── emoji.svg
│ │ ├── equal-proportion.svg
│ │ ├── exit.svg
│ │ ├── expand-down.svg
│ │ ├── file-view.svg
│ │ ├── file.svg
│ │ ├── font-size-decrease.svg
│ │ ├── font-size-increase.svg
│ │ ├── format-painter.svg
│ │ ├── format.svg
│ │ ├── full-screen-exit.svg
│ │ ├── full-screen.svg
│ │ ├── hard-break.svg
│ │ ├── heading.svg
│ │ ├── help.svg
│ │ ├── hide-toolbar.svg
│ │ ├── highlight.svg
│ │ ├── home-page.svg
│ │ ├── hr.svg
│ │ ├── html5.svg
│ │ ├── image-draggable.svg
│ │ ├── image-failed.svg
│ │ ├── image-flip.svg
│ │ ├── image-preview.svg
│ │ ├── image-remove-background.svg
│ │ ├── image-reset.svg
│ │ ├── image-rotate.svg
│ │ ├── image.svg
│ │ ├── indent.svg
│ │ ├── italic.svg
│ │ ├── laser-pointer.svg
│ │ ├── line-height.svg
│ │ ├── line-number.svg
│ │ ├── link.svg
│ │ ├── loading.svg
│ │ ├── margin.svg
│ │ ├── markdown.svg
│ │ ├── math.svg
│ │ ├── mention.svg
│ │ ├── menu.svg
│ │ ├── mermaid.svg
│ │ ├── message.svg
│ │ ├── mind-map.svg
│ │ ├── minus.svg
│ │ ├── new-window.svg
│ │ ├── node-add.svg
│ │ ├── node-clear-format.svg
│ │ ├── node-copy.svg
│ │ ├── node-cut.svg
│ │ ├── node-delete-2.svg
│ │ ├── node-delete.svg
│ │ ├── node-duplicate.svg
│ │ ├── node-switch.svg
│ │ ├── ordered-list-2.svg
│ │ ├── ordered-list-decimal-leading-zero.svg
│ │ ├── ordered-list-decimal.svg
│ │ ├── ordered-list-lower-latin.svg
│ │ ├── ordered-list-lower-roman.svg
│ │ ├── ordered-list-simp-chinese-formal.svg
│ │ ├── ordered-list-trad-chinese-informal.svg
│ │ ├── ordered-list-upper-latin.svg
│ │ ├── ordered-list-upper-roman.svg
│ │ ├── ordered-list.svg
│ │ ├── outdent.svg
│ │ ├── page-background.svg
│ │ ├── page-break.svg
│ │ ├── page-footer.svg
│ │ ├── page-header.svg
│ │ ├── page-margin.svg
│ │ ├── page-orientation.svg
│ │ ├── page-size.svg
│ │ ├── page.svg
│ │ ├── palette-color.svg
│ │ ├── paragraph.svg
│ │ ├── pdf.svg
│ │ ├── plus.svg
│ │ ├── preview.svg
│ │ ├── print.svg
│ │ ├── qrcode.svg
│ │ ├── quote.svg
│ │ ├── redo.svg
│ │ ├── reload.svg
│ │ ├── remove.svg
│ │ ├── reply.svg
│ │ ├── seal.svg
│ │ ├── search-replace.svg
│ │ ├── select-all.svg
│ │ ├── selected.svg
│ │ ├── setting.svg
│ │ ├── share.svg
│ │ ├── shortcut.svg
│ │ ├── signature.svg
│ │ ├── spellcheck.svg
│ │ ├── strike.svg
│ │ ├── subscript.svg
│ │ ├── superscript.svg
│ │ ├── symbol.svg
│ │ ├── table-add-column-after.svg
│ │ ├── table-add-column-before.svg
│ │ ├── table-add-row-after.svg
│ │ ├── table-add-row-before.svg
│ │ ├── table-cells-align.svg
│ │ ├── table-cells-background.svg
│ │ ├── table-delete-column.svg
│ │ ├── table-delete-row.svg
│ │ ├── table-delete.svg
│ │ ├── table-fix.svg
│ │ ├── table-header-cell.svg
│ │ ├── table-header-column.svg
│ │ ├── table-header-row.svg
│ │ ├── table-merge-cell.svg
│ │ ├── table-next-cell.svg
│ │ ├── table-previous-cell.svg
│ │ ├── table-split-cell.svg
│ │ ├── table.svg
│ │ ├── tag.svg
│ │ ├── task-list-2.svg
│ │ ├── task-list.svg
│ │ ├── template.svg
│ │ ├── text-box.svg
│ │ ├── text.svg
│ │ ├── time.svg
│ │ ├── toc.svg
│ │ ├── toolbar-classic.svg
│ │ ├── toolbar-ribbon.svg
│ │ ├── toolbar-source.svg
│ │ ├── underline.svg
│ │ ├── undo.svg
│ │ ├── video.svg
│ │ ├── view.svg
│ │ ├── watermark.svg
│ │ ├── web-page.svg
│ │ └── word.svg
│ ├── images
│ │ ├── avatar.svg
│ │ ├── format-painter.svg
│ │ ├── laser-pointer.svg
│ │ ├── watermark-compact.png
│ │ └── watermark-spacious.png
│ └── styles
│ │ ├── _mixins.less
│ │ ├── _variables.less
│ │ ├── drager.less
│ │ ├── editor.less
│ │ ├── index.less
│ │ ├── plyr.less
│ │ └── tdesign.less
├── components
│ ├── ai
│ │ └── assistant
│ │ │ └── input.vue
│ ├── color-picker.vue
│ ├── container
│ │ ├── page.vue
│ │ ├── print.vue
│ │ ├── search-replace.vue
│ │ └── toc.vue
│ ├── editor
│ │ └── index.vue
│ ├── icon.vue
│ ├── index.ts
│ ├── index.vue
│ ├── menus
│ │ ├── bubble
│ │ │ ├── assistant.vue
│ │ │ ├── callout
│ │ │ │ ├── background.vue
│ │ │ │ ├── builtin.vue
│ │ │ │ └── emoji-remove.vue
│ │ │ ├── file
│ │ │ │ └── download.vue
│ │ │ ├── image
│ │ │ │ ├── draggable.vue
│ │ │ │ ├── edit.vue
│ │ │ │ ├── flip.vue
│ │ │ │ ├── open.vue
│ │ │ │ ├── preview.vue
│ │ │ │ ├── proportion.vue
│ │ │ │ ├── remove-background.vue
│ │ │ │ ├── reset.vue
│ │ │ │ └── rotate.vue
│ │ │ ├── index.vue
│ │ │ ├── link
│ │ │ │ ├── copy.vue
│ │ │ │ ├── edit.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── open.vue
│ │ │ │ └── unlink.vue
│ │ │ ├── menus.vue
│ │ │ ├── node
│ │ │ │ ├── delete.vue
│ │ │ │ ├── duplicate.vue
│ │ │ │ └── tofile.vue
│ │ │ ├── tag
│ │ │ │ ├── background.vue
│ │ │ │ ├── builtin.vue
│ │ │ │ ├── color.vue
│ │ │ │ ├── delete.vue
│ │ │ │ └── input.vue
│ │ │ ├── text-box
│ │ │ │ ├── background.vue
│ │ │ │ └── border.vue
│ │ │ └── webpage
│ │ │ │ ├── clickable.vue
│ │ │ │ └── open.vue
│ │ ├── button.vue
│ │ ├── context
│ │ │ └── block
│ │ │ │ ├── common.vue
│ │ │ │ ├── index.vue
│ │ │ │ └── node.vue
│ │ └── toolbar
│ │ │ ├── base
│ │ │ ├── align-center.vue
│ │ │ ├── align-distributed.vue
│ │ │ ├── align-dropdown.vue
│ │ │ ├── align-justify.vue
│ │ │ ├── align-left.vue
│ │ │ ├── align-right.vue
│ │ │ ├── background-color.vue
│ │ │ ├── bold.vue
│ │ │ ├── bullet-list.vue
│ │ │ ├── clear-format.vue
│ │ │ ├── code.vue
│ │ │ ├── color.vue
│ │ │ ├── font-family.vue
│ │ │ ├── font-size.vue
│ │ │ ├── format-painter.vue
│ │ │ ├── heading.vue
│ │ │ ├── highlight.vue
│ │ │ ├── import-word.vue
│ │ │ ├── indent.vue
│ │ │ ├── italic.vue
│ │ │ ├── line-height.vue
│ │ │ ├── margin.vue
│ │ │ ├── markdown.vue
│ │ │ ├── ordered-list.vue
│ │ │ ├── outdent.vue
│ │ │ ├── print.vue
│ │ │ ├── quote.vue
│ │ │ ├── redo.vue
│ │ │ ├── search-replace.vue
│ │ │ ├── select-all.vue
│ │ │ ├── strike.vue
│ │ │ ├── subscript.vue
│ │ │ ├── superscript.vue
│ │ │ ├── task-list.vue
│ │ │ ├── underline.vue
│ │ │ └── undo.vue
│ │ │ ├── export
│ │ │ ├── embed.vue
│ │ │ ├── html.vue
│ │ │ ├── image.vue
│ │ │ ├── pdf.vue
│ │ │ ├── share.vue
│ │ │ ├── text.vue
│ │ │ └── word.vue
│ │ │ ├── insert
│ │ │ ├── audio.vue
│ │ │ ├── bookmark.vue
│ │ │ ├── callout.vue
│ │ │ ├── chinese-date.vue
│ │ │ ├── code-block.vue
│ │ │ ├── columns.vue
│ │ │ ├── emoji.vue
│ │ │ ├── file.vue
│ │ │ ├── hard-break.vue
│ │ │ ├── hr.vue
│ │ │ ├── image.vue
│ │ │ ├── link.vue
│ │ │ ├── math.vue
│ │ │ ├── mention.vue
│ │ │ ├── symbol.vue
│ │ │ ├── tag.vue
│ │ │ ├── template.vue
│ │ │ ├── text-box.vue
│ │ │ ├── toc.vue
│ │ │ ├── video.vue
│ │ │ └── web-page.vue
│ │ │ ├── page
│ │ │ ├── background.vue
│ │ │ ├── break-marks.vue
│ │ │ ├── break.vue
│ │ │ ├── footer.vue
│ │ │ ├── header.vue
│ │ │ ├── line-number.vue
│ │ │ ├── margin.vue
│ │ │ ├── orientation.vue
│ │ │ ├── preview.vue
│ │ │ ├── size.vue
│ │ │ ├── toggle-toc.vue
│ │ │ └── watermark.vue
│ │ │ ├── table
│ │ │ ├── add-column-after.vue
│ │ │ ├── add-column-before.vue
│ │ │ ├── add-row-after.vue
│ │ │ ├── add-row-before.vue
│ │ │ ├── border-color.vue
│ │ │ ├── cells-align.vue
│ │ │ ├── cells-background.vue
│ │ │ ├── delete-column.vue
│ │ │ ├── delete-row.vue
│ │ │ ├── delete.vue
│ │ │ ├── fix.vue
│ │ │ ├── insert.vue
│ │ │ ├── merge-cells.vue
│ │ │ ├── next-cell.vue
│ │ │ ├── previous-cell.vue
│ │ │ ├── split-cell.vue
│ │ │ ├── toggle-header-cell.vue
│ │ │ ├── toggle-header-column.vue
│ │ │ └── toggle-header-row.vue
│ │ │ └── tools
│ │ │ ├── barcode.vue
│ │ │ ├── chinese-case.vue
│ │ │ ├── diagrams.vue
│ │ │ ├── echarts.vue
│ │ │ ├── mermaid.vue
│ │ │ ├── mind-map.vue
│ │ │ ├── qrcode.vue
│ │ │ ├── seal.vue
│ │ │ └── signature.vue
│ ├── modal.vue
│ ├── page-options.vue
│ ├── statusbar
│ │ ├── countdown.vue
│ │ ├── index.vue
│ │ └── shortcuts.vue
│ ├── toolbar
│ │ ├── classic.vue
│ │ ├── index.vue
│ │ ├── ribbon.vue
│ │ └── scrollable.vue
│ └── tooltip.vue
├── composables
│ ├── dialog.ts
│ ├── hotkeys.ts
│ ├── i18n.ts
│ ├── popup.ts
│ ├── select.ts
│ └── state.ts
├── extensions
│ ├── audio
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── bookmark.ts
│ ├── break-marks.ts
│ ├── bullet-list.ts
│ ├── callout
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── code-block
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── color-highlighter
│ │ ├── find-colors.ts
│ │ └── index.ts
│ ├── datetime
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── echarts
│ │ ├── cal-service.ts
│ │ ├── index.ts
│ │ ├── init-service.ts
│ │ └── node-view.vue
│ ├── file-handler.ts
│ ├── file
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── font-size.ts
│ ├── format-painter.ts
│ ├── hr.ts
│ ├── iframe
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── image
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── indent.ts
│ ├── index.ts
│ ├── line-height.ts
│ ├── link.ts
│ ├── margin.ts
│ ├── mention
│ │ ├── index.ts
│ │ ├── mentions.vue
│ │ └── suggestion.ts
│ ├── node-align.ts
│ ├── ordered-list.ts
│ ├── page-break.ts
│ ├── selection.ts
│ ├── table
│ │ ├── cell.ts
│ │ ├── header.ts
│ │ └── index.ts
│ ├── tag
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── text-align.ts
│ ├── text-box
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── toc
│ │ ├── index.ts
│ │ └── node-view.vue
│ ├── type-writer.ts
│ └── video
│ │ ├── index.ts
│ │ └── node-view.vue
├── i18n.ts
├── locales
│ ├── bo.json
│ ├── en-US.json
│ ├── ru-RU.json
│ ├── tdesign
│ │ └── ru-RU.ts
│ └── zh-CN.json
├── main.ts
├── options
│ ├── ai.ts
│ ├── dicts.ts
│ ├── index.ts
│ └── web-pages.ts
└── utils
│ ├── browser.ts
│ ├── content-transform.ts
│ ├── copyright.ts
│ ├── diagram-editor.ts
│ ├── file.ts
│ ├── functional.spec.ts
│ ├── functional.ts
│ ├── options.ts
│ ├── player.ts
│ ├── short-id.ts
│ ├── shortcut.ts
│ └── time-ago.ts
├── tsconfig.json
├── types
├── index.d.ts
└── shims.d.ts
├── vite.config.ts
└── vitest.config.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node modules
2 | node_modules/
3 |
4 | # Build output
5 | dist/
6 | package/
7 |
8 | # Editor directories and files
9 | .idea/
10 | *.suo
11 | *.ntvs*
12 | *.njsproj
13 | *.sln
14 | *.sw?
15 |
16 | # Logs
17 | logs
18 | *.log
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
23 | # Cache
24 | *.tsbuildinfo
25 | .npm
26 | .eslintcache
27 | .stylelintcache
28 | .prettiercache
29 | .biomecache
30 | vite.config.ts.timestamp*
31 | vitest.config.ts.timestamp*
32 |
33 | # Husky
34 | .husky/_
35 |
36 | # Auto Imports
37 | types/imports.d.ts
38 | types/components.d.ts
39 |
40 | # Lock files
41 | package-lock.json
42 | yarn.lock
43 | pnpm-lock.yaml
44 |
45 | # Other
46 | .DS_Store
47 | Thumbs.db
48 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | // Ignore all files and folders starting with a dot
2 | .*
3 |
4 | // Ignore logs
5 | *.log*
6 |
7 | // Ignore timestamp files
8 | *.timestamp*
9 |
10 | // Ignore development files
11 | node_modules
12 | src/
13 | public/
14 | biome.json
15 | eslint.config.mjs
16 | index.html
17 | jsconfig.json
18 | package.json
19 | TODO
20 | tsconfig.json
21 | vite.config.ts
22 | vitest.config.ts
23 | yarn.lock
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | @tiptap-pro:registry=https://registry.tiptap.dev/
2 | //registry.tiptap.dev/:_authToken=9fsQEgp8C8pbxpk8PFAjYr2oqCJzh96jh9UkQZtq4SCi1XDwBeVw2Kcs/YD1oVje
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/prettierrc",
3 | "semi": false,
4 | "tabWidth": 2,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["stylelint-less"],
3 | "rules": {
4 | "color-no-invalid-hex": true,
5 | "less/color-no-invalid-hex": true,
6 | "no-descending-specificity": null,
7 | "selector-pseudo-class-no-unknown": [
8 | true,
9 | { "ignorePseudoClasses": ["deep"] }
10 | ]
11 | },
12 | "extends": [
13 | "stylelint-config-recommended-vue",
14 | "stylelint-config-recommended-less"
15 | ],
16 | "customSyntax": "postcss-html"
17 | }
18 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "Vue.volar",
4 | "dbaeumer.vscode-eslint",
5 | "esbenp.prettier-vscode",
6 | "i18n-ally.vscode-i18n-ally"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.codeActionsOnSave": {
3 | "source.fixAll.eslint": "always",
4 | "quickfix.biome": "always"
5 | },
6 | "editor.formatOnSave": true,
7 | "eslint.validate": [
8 | "javascript",
9 | "javascriptreact",
10 | "typescript",
11 | "typescriptreact"
12 | ],
13 | "[javascript]": {
14 | "editor.defaultFormatter": "esbenp.prettier-vscode"
15 | },
16 | "[javascriptreact]": {
17 | "editor.defaultFormatter": "esbenp.prettier-vscode"
18 | },
19 | "[typescript]": {
20 | "editor.defaultFormatter": "esbenp.prettier-vscode"
21 | },
22 | "[typescriptreact]": {
23 | "editor.defaultFormatter": "esbenp.prettier-vscode"
24 | },
25 | "i18n-ally.localesPaths": ["src/locales"],
26 | "i18n-ally.keystyle": "nested"
27 | }
28 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | [English Changelog](https://editor.umodoc.com/en/docs/changelog) | [中文更新日志](https://editor.umodoc.com/cn/docs/changelog)
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright © 2024 umo-team
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | [ ] 页面设置等可撤销和重做
--------------------------------------------------------------------------------
/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
3 | "formatter": {
4 | "enabled": false
5 | },
6 | "linter": {
7 | "enabled": true,
8 | "ignore": ["node_modules", "dist"],
9 | "rules": {
10 | "recommended": true,
11 | "suspicious": {
12 | "noExplicitAny": "off"
13 | },
14 | "performance": {
15 | "noDelete": "off",
16 | "noAccumulatingSpread": "off"
17 | },
18 | "style": {
19 | "noNonNullAssertion": "off",
20 | "noParameterAssign": "off"
21 | }
22 | }
23 | },
24 | "json": {
25 | "formatter": {
26 | "enabled": true
27 | }
28 | },
29 | "css": {
30 | "linter": {
31 | "enabled": true
32 | }
33 | },
34 | "organizeImports": {
35 | "enabled": false
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Umo Editor
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "paths": {
4 | "@/*": ["./src/*"]
5 | }
6 | },
7 | "include": ["./types/**/*.d.ts"],
8 | "exclude": ["node_modules", "dist"],
9 | "types": ["vue/ref-macros"]
10 | }
11 |
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umodoc/editor/50f1247102b2e297bad4cae963ffed66b32a597a/public/favicon.png
--------------------------------------------------------------------------------
/src/assets/icons/align-center.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/align-distributed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/align-justify.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/align-left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/align-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/arrow-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/assistant.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/audio.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/auto-width.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/background-color.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/barcode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/block-add.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/block-menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/bold.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/bookmark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/border-none.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/border.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/break-marks.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/bullet-list-2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/bullet-list-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/bullet-list-disc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/bullet-list-square.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/bullet-list.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/callout.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/chinese-case.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/clear-cache.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/clear-format.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/clickable.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/code-block.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/code-line-number.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/code-word-wrap.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/code.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/color.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/columns.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/copy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/date.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/diagrams.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/download.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/echarts.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/embed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/emoji.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/equal-proportion.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/exit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/expand-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/file-view.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/file.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/font-size-decrease.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/font-size-increase.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/format-painter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/format.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/full-screen-exit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/full-screen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/hard-break.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/heading.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/help.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/hide-toolbar.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/highlight.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/home-page.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/hr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/html5.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image-draggable.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image-failed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image-flip.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image-preview.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image-remove-background.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image-reset.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image-rotate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/image.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/indent.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/italic.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/laser-pointer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/line-height.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/line-number.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/loading.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/margin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/markdown.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/math.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/mention.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/mermaid.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/mind-map.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/minus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/new-window.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/node-add.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/node-clear-format.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/node-copy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/node-cut.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/assets/icons/node-delete-2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/node-delete.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/node-duplicate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/node-switch.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/ordered-list-2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/ordered-list-lower-roman.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/ordered-list-trad-chinese-informal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/ordered-list-upper-latin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/ordered-list-upper-roman.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/ordered-list.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/outdent.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page-background.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page-break.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page-footer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page-header.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page-margin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page-orientation.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page-size.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/page.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/palette-color.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/paragraph.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/pdf.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/preview.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/print.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/qrcode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/quote.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/redo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/reload.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/remove.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/reply.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/seal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/search-replace.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/select-all.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/selected.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/share.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/shortcut.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/signature.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/spellcheck.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/strike.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/subscript.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/superscript.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/symbol.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-add-column-after.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-add-column-before.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-add-row-after.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-add-row-before.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-cells-align.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-cells-background.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-delete-column.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-delete-row.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-delete.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-fix.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-header-cell.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-header-column.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-header-row.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-merge-cell.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-next-cell.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-previous-cell.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table-split-cell.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/tag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/task-list-2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/task-list.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/template.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/text-box.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/text.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/time.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/toc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/toolbar-classic.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/toolbar-ribbon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/toolbar-source.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/underline.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/undo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/video.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/view.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/watermark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/web-page.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/word.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/images/avatar.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/images/format-painter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/images/laser-pointer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/images/watermark-compact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umodoc/editor/50f1247102b2e297bad4cae963ffed66b32a597a/src/assets/images/watermark-compact.png
--------------------------------------------------------------------------------
/src/assets/images/watermark-spacious.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umodoc/editor/50f1247102b2e297bad4cae963ffed66b32a597a/src/assets/images/watermark-spacious.png
--------------------------------------------------------------------------------
/src/assets/styles/index.less:
--------------------------------------------------------------------------------
1 | @import './_variables.less';
2 | @import './_mixins.less';
3 | @import './tdesign.less';
4 |
5 | .umo-editor-container {
6 | p,
7 | ul,
8 | ol {
9 | margin: 0;
10 | padding: 0;
11 | }
12 | }
13 |
14 | .umo-scrollbar {
15 | .umo-scrollbar();
16 | }
17 |
--------------------------------------------------------------------------------
/src/assets/styles/plyr.less:
--------------------------------------------------------------------------------
1 | .plyr {
2 | --plyr-color-main: var(--umo-primary-color);
3 | --plyr-badge-border-radius: var(--umo-radius);
4 | --plyr-menu-arrow-size: 0;
5 | --plyr-menu-item-arrow-size: 0;
6 | --plyr-tooltip-color: var(--umo-text-color);
7 | --plyr-tooltip-arrow-size: 0;
8 | --plyr-tooltip-radius: 2px;
9 | --plyr-tooltip-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
10 | border-radius: var(--umo-radius);
11 | @media print {
12 | .plyr__controls {
13 | display: none;
14 | }
15 | .plyr__control {
16 | background-color: transparent;
17 | svg {
18 | width: 24px;
19 | height: 24px;
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/components/icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
23 |
24 |
29 |
--------------------------------------------------------------------------------
/src/components/index.ts:
--------------------------------------------------------------------------------
1 | import 'virtual:svg-icons-register'
2 |
3 | import UmoEditor from './index.vue'
4 | import UmoMenuButton from './menus/button.vue'
5 | import UmoDialog from './modal.vue'
6 | import UmoTooltip from './tooltip.vue'
7 |
8 | const useUmoEditor = {
9 | install: (app: any, options: any) => {
10 | app.provide('defaultOptions', options)
11 | app.component(UmoEditor.name ?? 'UmoEditor', UmoEditor)
12 | },
13 | }
14 |
15 | export {
16 | UmoEditor as default,
17 | UmoDialog,
18 | UmoEditor,
19 | UmoMenuButton,
20 | UmoTooltip,
21 | useUmoEditor,
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/assistant.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/callout/background.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
36 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/callout/emoji-remove.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
25 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/file/download.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
27 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/draggable.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
24 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
17 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/flip.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
14 |
15 |
16 |
17 |
37 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/open.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
24 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/preview.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
21 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/proportion.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
24 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/reset.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
28 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/image/rotate.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
12 |
13 |
14 |
15 |
30 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/link/copy.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
29 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/link/open.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ t('insert.link.open') }}
6 |
7 |
8 |
9 |
19 |
20 |
28 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/link/unlink.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
20 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/node/delete.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/node/duplicate.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
39 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/node/tofile.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
28 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/tag/background.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
34 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/tag/color.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
34 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/tag/delete.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/tag/input.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
48 |
49 |
59 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/text-box/background.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
34 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/webpage/clickable.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
24 |
--------------------------------------------------------------------------------
/src/components/menus/bubble/webpage/open.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
26 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/align-center.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
31 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/align-distributed.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/align-dropdown.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
47 |
48 |
54 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/align-justify.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/align-left.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
30 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/align-right.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
31 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/bold.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/clear-format.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/code.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/format-painter.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
25 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/indent.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/italic.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/line-height.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
41 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/markdown.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
46 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/outdent.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/print.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/quote.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/redo.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/search-replace.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/select-all.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/strike.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/subscript.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/superscript.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/task-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
18 | {{ t('list.task.split') }}
19 |
20 |
24 | {{ t('list.task.sink') }}
25 |
26 |
30 | {{ t('list.task.lift') }}
31 |
32 |
33 |
34 |
35 |
36 |
37 |
40 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/underline.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/base/undo.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/export/html.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/export/pdf.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/export/share.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
17 |
26 |
27 |
28 |
29 |
44 |
45 |
62 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/export/text.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
29 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/export/word.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/audio.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/callout.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/code-block.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/file.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/hard-break.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/image.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/math.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/mention.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/tag.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/text-box.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/toc.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/insert/video.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/break-marks.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
24 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/break.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/line-number.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/margin.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/preview.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/page/toggle-toc.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/add-column-after.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/add-column-before.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/add-row-after.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/add-row-before.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/border-color.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
33 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/cells-align.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
39 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/cells-background.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
30 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/delete-column.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
38 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/delete-row.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
38 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/delete.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
36 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/fix.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/merge-cells.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/next-cell.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
17 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/previous-cell.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
17 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/split-cell.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/toggle-header-cell.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/toggle-header-column.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/table/toggle-header-row.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/src/components/menus/toolbar/tools/mind-map.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/components/modal.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | {{ $attrs.header }}
14 |
15 |
16 |
17 |
18 |
19 |
28 |
--------------------------------------------------------------------------------
/src/components/tooltip.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
23 |
--------------------------------------------------------------------------------
/src/composables/dialog.ts:
--------------------------------------------------------------------------------
1 | import type { DialogOptions, MessageOptions } from 'tdesign-vue-next'
2 | import { DialogPlugin, MessagePlugin } from 'tdesign-vue-next'
3 |
4 | export const useAlert = (
5 | parmas: Omit,
6 | ) => {
7 | return DialogPlugin.alert({
8 | placement: 'center',
9 | ...parmas,
10 | })
11 | }
12 | export const useConfirm = (parmas: DialogOptions) => {
13 | return DialogPlugin.confirm({
14 | placement: 'center',
15 | preventScrollThrough: false,
16 | cancelBtn: t('dialog.cancel'),
17 | ...parmas,
18 | })
19 | }
20 | export const useMessage = (type: string, parmas: string | MessageOptions) => {
21 | const options = typeof parmas === 'string' ? { content: parmas } : parmas
22 | return (
23 | MessagePlugin[type as keyof typeof MessagePlugin] as
24 | | CallableFunction
25 | | undefined
26 | )?.(options)
27 | }
28 |
29 | export { DialogPlugin, MessagePlugin }
30 |
--------------------------------------------------------------------------------
/src/composables/hotkeys.ts:
--------------------------------------------------------------------------------
1 | import hotkeys from 'hotkeys-js'
2 |
3 | export const useHotkeys = (keys: string, callback: CallableFunction) => {
4 | hotkeys.filter = () => true
5 | hotkeys(keys, (e: Event) => {
6 | e.preventDefault()
7 | callback()
8 | return false
9 | })
10 | }
11 |
12 | export const removeAllHotkeys = () => {
13 | hotkeys.unbind()
14 | }
15 |
--------------------------------------------------------------------------------
/src/composables/i18n.ts:
--------------------------------------------------------------------------------
1 | import { isRecord } from '@tool-belt/type-predicates'
2 |
3 | import { i18n } from '../i18n'
4 |
5 | const { global } = i18n
6 |
7 | // @ts-ignore
8 | export const { t } = global
9 |
10 | export const l = (data: string | Record) => {
11 | if (typeof data === 'string') {
12 | return data
13 | }
14 |
15 | if (isRecord(data)) {
16 | return data[global.locale.value.replace('-', '_')]
17 | }
18 | }
19 |
20 | export const useI18n = () => global
21 |
--------------------------------------------------------------------------------
/src/composables/popup.ts:
--------------------------------------------------------------------------------
1 | export function usePopup() {
2 | const popupVisible = ref(false)
3 |
4 | const togglePopup = (visible?: boolean) => {
5 | popupVisible.value = visible ?? !popupVisible.value
6 | }
7 |
8 | return { popupVisible, togglePopup }
9 | }
10 |
--------------------------------------------------------------------------------
/src/composables/select.ts:
--------------------------------------------------------------------------------
1 | // 为解决 tdesign-vue-next select 组件的自身 Bug,采用延时渲染来避免
2 |
3 | export function useSelect() {
4 | const selectVisible = ref(false)
5 |
6 | onMounted(() => {
7 | selectVisible.value = true
8 | })
9 |
10 | return { selectVisible }
11 | }
12 |
--------------------------------------------------------------------------------
/src/extensions/audio/index.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from '@tiptap/core'
2 | import { VueNodeViewRenderer } from '@tiptap/vue-3'
3 |
4 | import NodeView from './node-view.vue'
5 |
6 | declare module '@tiptap/core' {
7 | interface Commands {
8 | setAudio: {
9 | setAudio: (options: any) => ReturnType
10 | }
11 | }
12 | }
13 | export default Node.create({
14 | name: 'audio',
15 | group: 'block',
16 | atom: true,
17 | addAttributes() {
18 | return {
19 | vnode: {
20 | default: true,
21 | },
22 | file: {
23 | default: null,
24 | },
25 | id: {
26 | default: null,
27 | },
28 | name: {
29 | default: null,
30 | },
31 | size: {
32 | default: null,
33 | },
34 | src: {
35 | default: null,
36 | },
37 | uploaded: {
38 | default: false,
39 | },
40 | previewType: {
41 | default: 'audio',
42 | },
43 | }
44 | },
45 | parseHTML() {
46 | return [{ tag: 'audio' }]
47 | },
48 | renderHTML({ HTMLAttributes }) {
49 | return ['audio', mergeAttributes(HTMLAttributes)]
50 | },
51 | addNodeView() {
52 | return VueNodeViewRenderer(NodeView)
53 | },
54 | addCommands() {
55 | return {
56 | setAudio:
57 | (options) =>
58 | ({ commands, editor }) => {
59 | return commands.insertContentAt(editor.state.selection.anchor, {
60 | type: this.name,
61 | attrs: options,
62 | })
63 | },
64 | }
65 | },
66 | })
67 |
--------------------------------------------------------------------------------
/src/extensions/break-marks.ts:
--------------------------------------------------------------------------------
1 | import type { Node } from '@tiptap/pm/model'
2 | import { InvisibleNode } from '@tiptap-pro/extension-invisible-characters'
3 | import InvisibleCharacters, {
4 | HardBreakNode,
5 | ParagraphNode,
6 | } from '@tiptap-pro/extension-invisible-characters'
7 |
8 | class HeadingNode extends InvisibleNode {
9 | constructor() {
10 | super({
11 | type: 'paragraph',
12 | predicate: (node: Node) => ['heading'].includes(node.type.name),
13 | })
14 | }
15 | }
16 |
17 | const breakMarks = InvisibleCharacters.configure({
18 | injectCSS: false,
19 | builders: [new HardBreakNode(), new ParagraphNode(), new HeadingNode()],
20 | })
21 |
22 | export default breakMarks
23 |
--------------------------------------------------------------------------------
/src/extensions/bullet-list.ts:
--------------------------------------------------------------------------------
1 | import BulletList from '@tiptap/extension-bullet-list'
2 |
3 | // https://www.npmjs.com/package/tiptap-extension-bullet-list
4 | export default BulletList.extend({
5 | content: 'listItem*',
6 | addAttributes() {
7 | return {
8 | ...this.parent?.(),
9 | listType: {
10 | default: 'disc',
11 | parseHTML: (element) =>
12 | element.style.getPropertyValue('list-style-type') || 'disc',
13 | renderHTML: ({ listType }) => {
14 | return {
15 | style: `list-style-type: ${listType}`,
16 | type: listType,
17 | }
18 | },
19 | },
20 | }
21 | },
22 | })
23 |
--------------------------------------------------------------------------------
/src/extensions/code-block/index.ts:
--------------------------------------------------------------------------------
1 | import CodeBlock from '@tiptap/extension-code-block-lowlight'
2 | import { VueNodeViewRenderer } from '@tiptap/vue-3'
3 | import { common, createLowlight } from 'lowlight'
4 |
5 | import NodeView from './node-view.vue'
6 |
7 | const lowlight = createLowlight(common)
8 |
9 | const customCodeBlock = CodeBlock.extend({
10 | addAttributes() {
11 | return {
12 | ...this.parent?.(),
13 | language: {
14 | default: 'plaintext',
15 | },
16 | theme: {
17 | default: 'light',
18 | },
19 | wordWrap: {
20 | default: true,
21 | },
22 | }
23 | },
24 | addNodeView() {
25 | return VueNodeViewRenderer(NodeView)
26 | },
27 | })
28 |
29 | export default customCodeBlock.configure({
30 | lowlight,
31 | })
32 |
--------------------------------------------------------------------------------
/src/extensions/color-highlighter/find-colors.ts:
--------------------------------------------------------------------------------
1 | import { Node } from '@tiptap/pm/model'
2 | import { Decoration, DecorationSet } from '@tiptap/pm/view'
3 |
4 | export default function (doc: Node): DecorationSet {
5 | const hexColor = /(#[0-9a-f]{3,6})\b/gi
6 | const decorations: Decoration[] = []
7 |
8 | doc.descendants((node, position) => {
9 | if (!node.text) {
10 | return
11 | }
12 |
13 | Array.from(node.text.matchAll(hexColor)).forEach((match) => {
14 | // eslint-disable-next-line prefer-destructuring
15 | const color = match[0]
16 | const index = match.index || 0
17 | const from = position + index
18 | const to = from + color.length
19 | const decoration = Decoration.inline(from, to, {
20 | class: 'umo-color-highlighter',
21 | style: `--color: ${color}`,
22 | })
23 |
24 | decorations.push(decoration)
25 | })
26 | })
27 |
28 | return DecorationSet.create(doc, decorations)
29 | }
30 |
--------------------------------------------------------------------------------
/src/extensions/color-highlighter/index.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from '@tiptap/core'
2 | import { Plugin } from '@tiptap/pm/state'
3 |
4 | import findColors from './find-colors'
5 |
6 | export const ColorHighlighter = Extension.create({
7 | name: 'colorHighlighter',
8 | addProseMirrorPlugins() {
9 | return [
10 | new Plugin({
11 | state: {
12 | init(_, { doc }) {
13 | return findColors(doc)
14 | },
15 | apply(transaction, oldState) {
16 | return transaction.docChanged
17 | ? findColors(transaction.doc)
18 | : oldState
19 | },
20 | },
21 | props: {
22 | decorations(state) {
23 | return this.getState(state)
24 | },
25 | },
26 | }),
27 | ]
28 | },
29 | })
30 |
--------------------------------------------------------------------------------
/src/extensions/datetime/index.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from '@tiptap/core'
2 | import { VueNodeViewRenderer } from '@tiptap/vue-3'
3 |
4 | import NodeView from './node-view.vue'
5 |
6 | declare module '@tiptap/core' {
7 | interface Commands {
8 | insertDatetime: {
9 | insertDatetime: (options: any) => ReturnType
10 | }
11 | }
12 | }
13 |
14 | export default Node.create({
15 | name: 'datetime',
16 | group: 'inline',
17 | inline: true,
18 | atom: true,
19 | selectable: false,
20 |
21 | addAttributes() {
22 | return {
23 | type: { default: 'datetime' },
24 | date: { default: null },
25 | text: { default: '[日期]' },
26 | format: { default: null },
27 | withTime: { default: false },
28 | capitalize: { default: false },
29 | }
30 | },
31 |
32 | parseHTML() {
33 | return [{ tag: 'span[data-type="datetime"]' }]
34 | },
35 |
36 | renderHTML({ HTMLAttributes }) {
37 | return [
38 | 'span',
39 | mergeAttributes(HTMLAttributes, { 'data-type': 'datetime' }),
40 | HTMLAttributes.text,
41 | ]
42 | },
43 |
44 | addNodeView() {
45 | return VueNodeViewRenderer(NodeView)
46 | },
47 |
48 | addCommands() {
49 | return {
50 | insertDatetime:
51 | (options) =>
52 | ({ chain }) => {
53 | return chain()
54 | .insertContent({
55 | type: this.name,
56 | attrs: options,
57 | })
58 | .run()
59 | },
60 | }
61 | },
62 | })
63 |
--------------------------------------------------------------------------------
/src/extensions/echarts/init-service.ts:
--------------------------------------------------------------------------------
1 | /*
2 | //**此服务主要作用**
3 | onMounted 钩子在初次加载时容易出现 echarts-script 已经存在,但 onload 未完成的情况,
4 | 导致第二次进入时判断已存在但实际 echart 还未加载完成,导致只加载出了第一个图表,后续图表都没加载上
5 | loadEchartScript :解决同时加载多个图表时只有第一个图表展示问题。
6 | */
7 |
8 | const echartsLoadPromise = ref | null>(null)
9 |
10 | // npm 包引入 echarts 会导致整个打包的包变大,为了解决这个问题,现使用 cdn 方式引入
11 | export function useEchartsLoader(options: any) {
12 | return {
13 | // 调用此方法,实现初始化加载 js 脚本
14 | loadEchartScript: () => {
15 | if (!options.toolbar?.disableMenuItems.includes('echarts')) {
16 | if (!echartsLoadPromise.value) {
17 | echartsLoadPromise.value = new Promise((resolve, reject) => {
18 | const existingScript = document.querySelector('#echarts-script')
19 | if (!existingScript) {
20 | const script = document.createElement('script')
21 | script.src = `${options.cdnUrl}/libs/echarts/echarts.min.js`
22 | script.id = 'echarts-script'
23 | script.type = 'text/javascript'
24 | script.onload = () => resolve()
25 | script.onerror = (error) =>
26 | reject(new Error(`load Echarts ERROR`))
27 | document.querySelector('head')!.append(script)
28 | } else {
29 | // 如果脚本已存在,则立即解析 Promise
30 | resolve()
31 | }
32 | })
33 | }
34 | return echartsLoadPromise.value
35 | } else {
36 | return null
37 | }
38 | },
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/extensions/iframe/index.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from '@tiptap/core'
2 | import { VueNodeViewRenderer } from '@tiptap/vue-3'
3 |
4 | import NodeView from './node-view.vue'
5 | declare module '@tiptap/core' {
6 | interface Commands {
7 | setIframe: {
8 | setIframe: (options: any) => ReturnType
9 | }
10 | }
11 | }
12 | export default Node.create({
13 | name: 'iframe',
14 | inline: false,
15 | group: 'block',
16 | atom: true,
17 | addAttributes() {
18 | return {
19 | vnode: {
20 | default: true,
21 | },
22 | type: {
23 | default: 0,
24 | },
25 | src: {
26 | default: null,
27 | },
28 | width: {
29 | default: null,
30 | },
31 | height: {
32 | default: 200,
33 | },
34 | clickable: {
35 | default: false,
36 | },
37 | }
38 | },
39 | parseHTML() {
40 | return [{ tag: 'iframe' }]
41 | },
42 | renderHTML({ HTMLAttributes }) {
43 | return [
44 | 'iframe',
45 | mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
46 | ]
47 | },
48 | addNodeView() {
49 | return VueNodeViewRenderer(NodeView)
50 | },
51 | addCommands() {
52 | return {
53 | setIframe:
54 | (options) =>
55 | ({ commands }) => {
56 | return commands.insertContent({
57 | type: this.name,
58 | attrs: options,
59 | })
60 | },
61 | }
62 | },
63 | })
64 |
--------------------------------------------------------------------------------
/src/extensions/link.ts:
--------------------------------------------------------------------------------
1 | import Link from '@tiptap/extension-link'
2 | import { Plugin } from '@tiptap/pm/state'
3 |
4 | const CustomLink = Link.extend({
5 | addStorage() {
6 | return {
7 | edit: false,
8 | meta: {},
9 | }
10 | },
11 | addProseMirrorPlugins() {
12 | return [
13 | new Plugin({
14 | props: {
15 | handleClick(view, pos, event) {
16 | const target = event.target as HTMLElement
17 | if (target.tagName === 'A') {
18 | const href = target.getAttribute('href')
19 | view.dispatch(
20 | view.state.tr.setMeta('link-click', {
21 | target,
22 | href,
23 | pos,
24 | }),
25 | )
26 | return true
27 | }
28 | return false
29 | },
30 | },
31 | }),
32 | ]
33 | },
34 | onTransaction({ transaction }) {
35 | const meta = transaction.getMeta('link-click')
36 | if (meta) {
37 | this.storage.edit = true
38 | this.storage.meta = meta
39 | }
40 | },
41 | })
42 |
43 | CustomLink.configure({
44 | // @ts-ignore
45 | openOnClick: (props) => !props.editor.isEditable,
46 | })
47 |
48 | export default CustomLink
49 |
--------------------------------------------------------------------------------
/src/extensions/mention/index.ts:
--------------------------------------------------------------------------------
1 | import Mention from '@tiptap/extension-mention'
2 |
3 | declare module '@tiptap/core' {
4 | interface Commands {
5 | insertMention: {
6 | insertMention: (options: any) => ReturnType
7 | }
8 | }
9 | }
10 |
11 | const CustomMention = Mention.extend({
12 | addAttributes() {
13 | return {
14 | id: {
15 | default: null,
16 | },
17 | label: {
18 | default: null,
19 | },
20 | }
21 | },
22 | addCommands() {
23 | return {
24 | insertMention:
25 | () =>
26 | ({ commands }) => {
27 | return commands.insertContent(
28 | ` ${this.options?.suggestion?.char ?? '@'}`,
29 | )
30 | },
31 | }
32 | },
33 | })
34 |
35 | // 配置并导出扩展
36 | export default CustomMention.configure({
37 | HTMLAttributes: {
38 | class: 'umo-node-mention',
39 | },
40 | })
41 |
--------------------------------------------------------------------------------
/src/extensions/ordered-list.ts:
--------------------------------------------------------------------------------
1 | import OrderedList from '@tiptap/extension-ordered-list'
2 |
3 | // https://www.npmjs.com/package/tiptap-extension-ordered-list
4 | export default OrderedList.extend({
5 | content: 'listItem*',
6 | addAttributes() {
7 | return {
8 | ...this.parent?.(),
9 | listType: {
10 | default: 'decimal',
11 | parseHTML: (element) =>
12 | element.style.getPropertyValue('list-style-type') || 'decimal',
13 | renderHTML: ({ listType }) => {
14 | return {
15 | style: `list-style-type: ${listType}`,
16 | type: listType,
17 | }
18 | },
19 | },
20 | }
21 | },
22 | })
23 |
--------------------------------------------------------------------------------
/src/extensions/page-break.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from '@tiptap/core'
2 |
3 | declare module '@tiptap/core' {
4 | interface Commands {
5 | setPageBreak: {
6 | setPageBreak: () => ReturnType
7 | }
8 | }
9 | }
10 |
11 | export default Node.create({
12 | name: 'pageBreak',
13 | group: 'block',
14 | addOptions() {
15 | return {
16 | HTMLAttributes: {
17 | class: 'umo-page-break',
18 | 'data-line-number': false,
19 | 'data-content': t('page.break'),
20 | },
21 | }
22 | },
23 | parseHTML() {
24 | return [{ tag: 'div[class*="umo-page-break"]' }]
25 | },
26 | renderHTML({ HTMLAttributes }) {
27 | return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]
28 | },
29 | addCommands() {
30 | return {
31 | setPageBreak:
32 | () =>
33 | ({ commands }) =>
34 | commands.insertContent({
35 | type: this.name,
36 | }),
37 | }
38 | },
39 | addKeyboardShortcuts() {
40 | return {
41 | 'Mod-Enter': () => this.editor.commands.setPageBreak(),
42 | }
43 | },
44 | })
45 |
--------------------------------------------------------------------------------
/src/extensions/table/cell.ts:
--------------------------------------------------------------------------------
1 | import TableCell from '@tiptap/extension-table-cell'
2 |
3 | const TableCellOptions = {
4 | addAttributes(): any {
5 | return {
6 | // @ts-ignore
7 | ...this.parent?.(),
8 | align: {
9 | default: null,
10 | parseHTML: (element: any) => element.getAttribute('align') ?? null,
11 | renderHTML: ({ align }: any) => ({ align }),
12 | },
13 | background: {
14 | default: null,
15 | parseHTML: (element: any) => {
16 | const style = element.getAttribute('style') ?? ''
17 | const match = style.match(/background(?:-color)?:\s*([^;]+)/i)
18 | return match ? match[1].trim() : null
19 | },
20 | renderHTML: ({ background }: any) => {
21 | return background ? { style: `background-color: ${background}` } : {}
22 | },
23 | },
24 | color: {
25 | default: null,
26 | parseHTML: (element: any) => {
27 | const style = element.getAttribute('style') ?? ''
28 | const match = style.match(/(? {
33 | return color ? { style: `color: ${color}` } : {}
34 | },
35 | },
36 | }
37 | },
38 | }
39 |
40 | export default TableCell.extend(TableCellOptions)
41 | export { TableCellOptions }
42 |
--------------------------------------------------------------------------------
/src/extensions/table/header.ts:
--------------------------------------------------------------------------------
1 | import TableHeader from '@tiptap/extension-table-header'
2 |
3 | import { TableCellOptions } from './cell'
4 |
5 | export default TableHeader.extend(TableCellOptions)
6 |
--------------------------------------------------------------------------------
/src/extensions/tag/index.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from '@tiptap/core'
2 | import { VueNodeViewRenderer } from '@tiptap/vue-3'
3 |
4 | import NodeView from './node-view.vue'
5 |
6 | declare module '@tiptap/core' {
7 | interface Commands {
8 | insertTag: {
9 | insertTag: (options: any) => ReturnType
10 | }
11 | }
12 | }
13 |
14 | export default Node.create({
15 | name: 'tag',
16 | group: 'inline',
17 | inline: true,
18 | atom: true,
19 |
20 | addAttributes() {
21 | return {
22 | type: { default: 'default' },
23 | text: { default: '标签内容' },
24 | color: { default: '#999' },
25 | backgroundColor: { default: 'rgba(0, 0, 0, 0.05)' },
26 | }
27 | },
28 |
29 | parseHTML() {
30 | return [{ tag: 'span[data-type="tag"]' }]
31 | },
32 |
33 | renderHTML({ HTMLAttributes }) {
34 | return [
35 | 'span',
36 | mergeAttributes(HTMLAttributes, { 'data-type': 'tag' }),
37 | HTMLAttributes.text,
38 | ]
39 | },
40 |
41 | addNodeView() {
42 | return VueNodeViewRenderer(NodeView)
43 | },
44 |
45 | addCommands() {
46 | return {
47 | insertTag:
48 | (options) =>
49 | ({ chain }) => {
50 | return chain()
51 | .insertContent({
52 | type: this.name,
53 | attrs: options,
54 | })
55 | .run()
56 | },
57 | }
58 | },
59 | })
60 |
--------------------------------------------------------------------------------
/src/extensions/tag/node-view.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
19 |
20 |
39 |
--------------------------------------------------------------------------------
/src/extensions/text-align.ts:
--------------------------------------------------------------------------------
1 | import TextAlign from '@tiptap/extension-text-align'
2 |
3 | export default TextAlign.extend({
4 | addOptions() {
5 | return {
6 | ...this.parent?.(),
7 | types: ['heading', 'paragraph'],
8 | alignments: ['left', 'center', 'right', 'justify', 'distributed'],
9 | }
10 | },
11 | addGlobalAttributes() {
12 | return [
13 | {
14 | types: this.options.types,
15 | attributes: {
16 | textAlign: {
17 | default: this.options.defaultAlignment,
18 | parseHTML: (element) => {
19 | if (element.style.textAlignLast) {
20 | return 'distributed'
21 | }
22 | return element.style.textAlign || this.options.defaultAlignment
23 | },
24 | renderHTML: (attributes) => {
25 | if (attributes.textAlign === this.options.defaultAlignment) {
26 | return {}
27 | }
28 | if (attributes.textAlign === 'distributed') {
29 | return { style: 'text-align-last: justify' }
30 | }
31 | return { style: `text-align: ${attributes.textAlign}` }
32 | },
33 | },
34 | },
35 | },
36 | ]
37 | },
38 | addKeyboardShortcuts() {
39 | return {
40 | ...this.parent?.(),
41 | 'Mod-Shift-d': () => this.editor.commands.setTextAlign('distributed'),
42 | }
43 | },
44 | })
45 |
--------------------------------------------------------------------------------
/src/extensions/toc/index.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from '@tiptap/core'
2 | import { VueNodeViewRenderer } from '@tiptap/vue-3'
3 |
4 | import NodeView from './node-view.vue'
5 | declare module '@tiptap/core' {
6 | interface Commands {
7 | addTableOfContents: {
8 | addTableOfContents: (option: any) => ReturnType
9 | }
10 | }
11 | }
12 | export default Node.create({
13 | name: 'toc',
14 | group: 'block',
15 | atom: true,
16 | addAttributes() {
17 | return {
18 | vnode: {
19 | default: true,
20 | },
21 | }
22 | },
23 | parseHTML() {
24 | return [{ tag: 'toc' }]
25 | },
26 | renderHTML({ HTMLAttributes }) {
27 | return ['toc', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]
28 | },
29 | addNodeView() {
30 | return VueNodeViewRenderer(NodeView)
31 | },
32 | addGlobalAttributes() {
33 | return [
34 | {
35 | types: ['heading'],
36 | attributes: {},
37 | },
38 | ]
39 | },
40 | addCommands() {
41 | return {
42 | addTableOfContents:
43 | (options) =>
44 | ({ chain }) => {
45 | return chain()
46 | .insertContent({
47 | type: this.name,
48 | attrs: options,
49 | })
50 | .run()
51 | },
52 | }
53 | },
54 | })
55 |
--------------------------------------------------------------------------------
/src/i18n.ts:
--------------------------------------------------------------------------------
1 | import { createI18n } from 'vue-i18n'
2 |
3 | import en_US from './locales/en-US.json'
4 | import ru_RU from './locales/ru-RU.json'
5 | import zh_CN from './locales/zh-CN.json'
6 |
7 | export const i18n = createI18n({
8 | legacy: false,
9 | locale: 'zh-CN',
10 | defaultLocale: 'zh-CN',
11 | messages: {
12 | 'en-US': en_US,
13 | 'zh-CN': zh_CN,
14 | 'ru-RU': ru_RU,
15 | },
16 | })
17 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import type { UmoEditorOptions } from '@/types'
2 |
3 | import App from './app.vue'
4 | import { useUmoEditor } from './components'
5 | const app = createApp(App)
6 |
7 | const options = {}
8 |
9 | app.use(useUmoEditor, options as unknown as UmoEditorOptions)
10 |
11 | app.mount('#app')
12 |
--------------------------------------------------------------------------------
/src/utils/browser.ts:
--------------------------------------------------------------------------------
1 | const nav = typeof navigator !== 'undefined' ? navigator : null
2 | const doc = typeof document !== 'undefined' ? document : null
3 | export const agent = nav?.userAgent ?? ''
4 |
5 | export const ie_edge = /Edg\/(\d+)/.exec(agent)
6 | export const ie_upto10 = /MSIE \d/.exec(agent)
7 | export const ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent)
8 |
9 | export const ie = !!(ie_upto10 ?? ie_11up ?? ie_edge)
10 | export const ie_version = ie_upto10
11 | ? Reflect.get(document, 'documentMode')
12 | : ie_11up
13 | ? +ie_11up[1]
14 | : ie_edge
15 | ? +ie_edge[1]
16 | : 0
17 | export const gecko = !ie && /gecko\/(\d+)/i.test(agent)
18 | export const gecko_version =
19 | gecko && +(/Firefox\/(\d+)/.exec(agent) ?? [0, 0])[1]
20 |
21 | export const chrome = Boolean(!ie && /Chrome\/(\d+)/.test(agent))
22 | export const chrome_version: number = chrome
23 | ? Number.parseInt(/Chrome\/(\d+)/.exec(agent)?.[1] ?? '0', 10)
24 | : 0
25 | export const safari = !ie && !!nav && nav.vendor.includes('Apple Computer')
26 | // Is true for both iOS and iPadOS for convenience
27 | export const ios =
28 | safari && (/Mobile\/\w+/.test(agent) || (!!nav && nav.maxTouchPoints > 2))
29 | export const mac = ios || (nav ? nav.platform.includes('Mac') : false)
30 | export const windows = nav ? nav.platform.includes('Win') : false
31 | export const android = /Android \d/.test(agent)
32 | export const webkit =
33 | !!doc && 'webkitFontSmoothing' in doc.documentElement.style
34 | export const webkit_version = webkit
35 | ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) ?? [0, 0])[1]
36 | : 0
37 |
--------------------------------------------------------------------------------
/src/utils/content-transform.ts:
--------------------------------------------------------------------------------
1 | export const contentTransform = (content: string) => {
2 | // 处理空内容或非字符串内容
3 | if (content && typeof content === 'string' && !content.startsWith('<')) {
4 | // 处理纯文本中的换行符
5 | console.log(content.split('\n'))
6 | return content
7 | .split('\n')
8 | .map((line) => `${line}
`)
9 | .join('')
10 | }
11 |
12 | return content
13 | }
14 |
--------------------------------------------------------------------------------
/src/utils/copyright.ts:
--------------------------------------------------------------------------------
1 | import pkg from '../../package.json'
2 |
3 | export default `/**
4 | * ${pkg.name} ${pkg.version}
5 | * @license ${pkg.license}
6 | * @author ${pkg.author.name} ${pkg.author.url}
7 | * @see ${pkg.homepage}
8 | **/
9 | `
10 |
11 | export const consoleCopyright = () => {
12 | console.info(
13 | t('welcome', { version: pkg.version, homepage: pkg.homepage }),
14 | 'background:#3480f9;color:#fff;border-top-left-radius:3px;border-bottom-left-radius:3px;padding:4px 8px 3px;',
15 | 'background:#fff;color:#3480f9;border-top-right-radius:3px;border-bottom-right-radius:3px;border:solid 1px #3480f9;padding:3px 8px 2px;',
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/utils/functional.ts:
--------------------------------------------------------------------------------
1 | import { isPromise } from '@tool-belt/type-predicates'
2 |
3 | /**
4 | * Wraps a function with error suppression and optional logging.
5 | *
6 | * @param fn - The function to execute.
7 | * @param errorMessage - The error message to log if an exception is thrown.
8 | * @returns The wrapped function with error suppression.
9 | */
10 | export function withSuppress any>(
11 | fn: T,
12 | errorMessage?: string,
13 | ): (
14 | ...args: Parameters
15 | ) => ReturnType extends Promise
16 | ? Promise
17 | : ReturnType | undefined {
18 | const log = errorMessage ? (msg: string) => console.error(msg) : null
19 |
20 | return (...args: Parameters) => {
21 | try {
22 | const result = fn(...args)
23 |
24 | if (isPromise(result)) {
25 | return result.catch((error) => {
26 | log?.(`${errorMessage}\n${error?.stack ?? error}`)
27 | return undefined
28 | })
29 | }
30 |
31 | return result
32 | } catch (error) {
33 | log?.(
34 | `${errorMessage}\n${Reflect.get(error as Record, 'stack') ?? error}`,
35 | )
36 | return undefined
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/utils/options.ts:
--------------------------------------------------------------------------------
1 | import { isRecord } from '@tool-belt/type-predicates'
2 |
3 | import { defaultOptions, ojbectSchema } from '@/options'
4 |
5 | export const getOpitons = (propsOptions: unknown, globalOptions?: unknown) => {
6 | const propsOptionsValue =
7 | isRecord(propsOptions) && Object.keys(propsOptions).includes('value')
8 | ? propsOptions.value
9 | : propsOptions
10 |
11 | const componentOptions = Object.keys(propsOptionsValue).reduce<
12 | Record
13 | >((acc: Record, key: string) => {
14 | if (propsOptionsValue[key] !== undefined) {
15 | acc[key] = propsOptionsValue[key]
16 | }
17 | return acc
18 | }, {})
19 |
20 | const options = ojbectSchema.merge(
21 | defaultOptions,
22 | globalOptions || {},
23 | componentOptions,
24 | )
25 |
26 | return options
27 | }
28 |
--------------------------------------------------------------------------------
/src/utils/short-id.ts:
--------------------------------------------------------------------------------
1 | export const shortId = (length = 8) =>
2 | Math.random()
3 | .toString(36)
4 | .substring(2, length + 2)
5 |
--------------------------------------------------------------------------------
/src/utils/shortcut.ts:
--------------------------------------------------------------------------------
1 | export const getShortcut = (shortcut: string) => {
2 | if (!shortcut) {
3 | return ''
4 | }
5 | // 判断是 Mac OS
6 | const isMacOS = /macintosh|mac os x/gi.test(navigator.userAgent)
7 | let keys = shortcut
8 | if (isMacOS) {
9 | keys = keys
10 | .replace(/ctrl/gi, '⌘')
11 | .replace(/shift/gi, '⇧')
12 | .replace(/alt/gi, '⌥')
13 | .replace(/Enter/gi, 'Return')
14 | .replace(/Backspace/gi, 'Delete')
15 | }
16 | return keys
17 | }
18 |
--------------------------------------------------------------------------------
/src/utils/time-ago.ts:
--------------------------------------------------------------------------------
1 | export const timeAgo = (timestamp: string | number | Date) => {
2 | const messages = {
3 | justNow: t('time.justNow'),
4 | past: (n: string | number | Date) =>
5 | n.toString().match(/\d/) ? t('time.past', { n }) : n,
6 | day: (n: Date | number | string) =>
7 | n === 1 ? t('time.yesterday') : t('time.day', { n }),
8 | hour: (n: string | number | Date) => t('time.hour', { n }),
9 | minute: (n: string | number | Date) => t('time.minute', { n }),
10 | second: (n: string | number | Date) => t('time.second', { n }),
11 | } as const
12 | const time = useTimeAgo(new Date(timestamp), {
13 | messages: messages as any,
14 | })
15 | return time.value.replace(/"/gi, '')
16 | }
17 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noImplicitAny": false,
4 | "removeComments": true,
5 | "disableSizeLimit": true,
6 | "target": "ESNext",
7 | "module": "ESNext",
8 | "strict": true,
9 | "allowJs": true,
10 | "noEmit": true,
11 | "jsx": "preserve",
12 | "moduleResolution": "bundler",
13 | "experimentalDecorators": true,
14 | "resolveJsonModule": true,
15 | "skipLibCheck": true,
16 | "esModuleInterop": true,
17 | "allowSyntheticDefaultImports": true,
18 | "forceConsistentCasingInFileNames": true,
19 | "useDefineForClassFields": true,
20 | "verbatimModuleSyntax": true,
21 | "sourceMap": true,
22 | "baseUrl": ".",
23 | "types": [
24 | "vue",
25 | "unplugin-vue-macros/macros-global",
26 | "@vue-macros/reactivity-transform/macros-global",
27 | "vite/client",
28 | "vitest/globals",
29 | "vitest",
30 | "./types/imports.d.ts",
31 | "./types/components.d.ts"
32 | ],
33 | "paths": {
34 | "@/*": ["./src/*"],
35 | "@/types": ["./types"]
36 | },
37 | "lib": ["ESNext", "DOM", "DOM.Iterable", "ScriptHost"]
38 | },
39 | "vueCompilerOptions": {
40 | "plugins": ["unplugin-vue-macros/volar"]
41 | },
42 | "include": [
43 | "*.mjs",
44 | "*.ts",
45 | "*.d.ts",
46 | "types/**/*.d.ts",
47 | "src/**/*.ts",
48 | "src/**/*.vue",
49 | "src/**/*.spec.ts",
50 | "src/**/*.spec.tsx",
51 | "src/**/*.d.ts"
52 | ],
53 | "exclude": ["node_modules", "dist"]
54 | }
55 |
--------------------------------------------------------------------------------
/types/shims.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import type { DefineComponent } from 'vue'
3 | const component: DefineComponent<
4 | Record,
5 | Record,
6 | any
7 | >
8 | export default component
9 | }
10 |
11 | declare module '@vue/runtime-core' {
12 | interface ComponentCustomProperties {
13 | t: (key: string, ...args: any[]) => any
14 | }
15 | }
16 |
17 | declare function t(key: string, ...args: any[]): any
18 |
19 | declare module 'dom-to-image-more' {
20 | export function toBlob(node: HTMLElement, options?: any): Promise
21 | export function toJpeg(node: HTMLElement, options?: any): Promise
22 | export function toPng(node: HTMLElement, options?: any): Promise
23 | }
24 | declare const echarts: any
25 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, mergeConfig } from 'vitest/config'
2 |
3 | import viteConfig from './vite.config'
4 |
5 | const testConfig = defineConfig({
6 | test: {
7 | environment: 'jsdom',
8 | globals: true,
9 | setupFiles: [],
10 | coverage: {
11 | include: ['src'],
12 | exclude: ['**/*.spec.*', '**/*.d.ts', 'src/types.ts', 'testing/*'],
13 | },
14 | onConsoleLog(log: string) {
15 | if (
16 | log.includes(
17 | 'Error: Not implemented: HTMLFormElement.prototype.requestSubmit',
18 | ) ||
19 | log.includes('(node:25503) [DEP0040]')
20 | ) {
21 | return false
22 | }
23 | },
24 | },
25 | })
26 |
27 | export default mergeConfig(viteConfig, testConfig)
28 |
--------------------------------------------------------------------------------