@ctzhian/tiptap 2.4.3 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,7 +13,7 @@ import { Box } from '@mui/material';
13
13
  import React, { useCallback, useEffect, useState } from 'react';
14
14
  import "../index.css";
15
15
  var Reader = function Reader() {
16
- var _useState = useState("本文用以记录 Gitlab 相关问题及解答\n\n## 我在使用 `git@git.in.chaitin.net:ns/repo` 时可以访问仓库,但是 `https://git.in.chaitin.net/ns/repo` 无法访问\n\n问题通常出现 git clone 与其他依赖 git 进行的操作,如 `go get` 等,具体报错可能为 `Permission Denied`.\n\n在使用 curl 借助 `CI_JOB_TOKEN` 获取其他仓库 cicd job 产物或者 generic package 时,其具体报错为 `404 Not Found` 的问题.\n\n原因是在使用 `git@git.in.chaitin.net` 时,使用的是 ssh 协议,此时默认使用的是 `~/.ssh` 下的私钥进行认证你在 gitlab 中添加的 `SSH Keys`。而使用 `https://git.in.chaitin.net/ns/repo` 时,使用的是 http 协议,此时默认使用的是 `~/.netrc` 认证你在 gitlab 中申请的 `Access tokens`。部分软件如 `go get` 默认使用的便是 http 来拉取代码,因此需要额外配置。\n\n这里推荐两种解决方案:\n\n1. 配置 `~/.netrc` 文件(推荐)\n\n 在 ~/.netrc 文件中添加以下配置:\n\n ```text\n machine git.in.chaitin.net login git password <your access token>\n ```\n\n 在 gitlab cicd job 中遇到拉取其他仓库时遇到权限问题可以使用本配置,比如可以在 job 的 `before_script` 阶段添加以下命令:\n\n ```shell\n echo \"machine git.in.chaitin.net login git password $CI_JOB_TOKEN\" >> ~/.netrc\n ```\n\n 注意: 其中 `$CI_JOB_TOKEN` 是 job 运行期间生成的 token,其权限与 trigger 用户相同,详见 [CI Job Token](https://docs.gitlab.com/ci/jobs/ci_job_token/)。其 Token 权限由 `pipeline 触发者`权限以及`目标仓库权限`共同决定。因此被拉取的目标仓库也需要保证其 `Setting -> CI/CD -> Job token permissions` 配置正确,允许源仓库的 CI/CD 能够访问到该仓库,否则依然会出现如 `404 Not Found`, `403 Forbidden` 的权限问题。(如果你是 pipeline 触发者,可以手动在浏览器通过 gitlab api 访问目标仓库的 generic package 或者 job artifact 如果可以正常下载,说明是 `Job token permissions` 问题)\n\n2. 配置 `git url replace`\n\n 在 ~/.gitconfig 文件中添加以下配置:\n\n ```ini\n [url \"git@git.in.chaitin.net:\"]\n insteadOf = https://git.in.chaitin.net/\n ```\n\n 这个配置可以将所有 `https://git.in.chaitin.net/` 请求替换为 `git@git.in.chaitin.net:` 使用 ssh 来拉取代码仓库\n\n## 我在 clone gitlab 仓库时没问题,但是 lfs 遇到了 EOF 问题\n\nEOF 在大多数情况下由代理导致,如果代理不允许客户端访问某个网站,行为可能是提早结束连接,导致 `EOF` 错误。如\n\n> 在 ubunu 虚拟机里无法拉取 safeline-aliyun 项目里的 lfs 文件怎么处理?\n\n```bash\nroot@OPS-5108:~/proj/safeline-aliyun# git lfs fetch --all\nfetch: 34 object(s) found, done.\nfetch: Fetching all references...\nbatch response: Post https://git.in.chaitin.net/patronus/safeline-aliyun.git/info/lfs/objects/batch: EOF\nerror: failed to fetch some objects from 'https://git.in.chaitin.net/patronus/safeline-aliyun.git/info/lfs'\n```\n\n可以看到返回了 EOF 问题,经查代理未配置在 git config 中。从 `env` 中可以看到用户配置了 *_proxy 但其中发现 `no_proxy` 配置不正确:\n\n```shell\nroot@OPS-5108:~/proj/safeline-aliyun# env | grep pro\nno_proxy=localhost, 127.0.0.1, ::1\nPWD=/root/proj/safeline-aliyun\nftp_proxy=http://proxy.in.chaitin.net:8123\nhttps_proxy=http://proxy.in.chaitin.net:8123\nproxy=http://proxy.in.chaitin.net:8123\nhttp_proxy=http://proxy.in.chaitin.net:8123\nOLDPWD=/root/proj\n```\n\n需要按照 [代理配置](https://info.chaitin.net/colab-editor/page/%E7%A0%94%E5%8F%91%E4%BD%93%E7%B3%BB%2F%E7%A0%94%E5%8F%91%E6%94%AF%E6%8C%81%2F%E4%BB%A3%E7%90%86%E6%89%AB%E7%9B%B2) 进行正确配置后,重新执行操作,发现 EOF 问题被解决。\n\n## 我在访问公司内部服务时报错 `x509: certificate signed by unknown authority`\n\n公司部分内部服务采用自签名证书,导致客户端在访问这些服务时会遇到 `x509: certificate signed by unknown authority` 错误。为了确保客户端能够信任这些自签名证书,你需要配置信任自签名证书即 CA。\n\n以 debian 系系统举例:\n\n```shell\ncurl -o /usr/local/share/ca-certificates/chaitin_ca.crt -L https://chaitin-ops-public.cn-beijing.oss.aliyuncs.com/Chaitin_Ltd_Root_CA.pem\nupdate-ca-certificates\n```\n\n如果无法访问外网,可以尝试 `http://s3-ephemeral.in.chaitin.net/dev/Chaitin_Ltd_Root_CA.pem`\n\n其他系统 CA 证书安装请参考 [安装CA证书](https://info.chaitin.net/colab-editor/page/IT%E5%8A%9E%E5%85%AC/%E5%8A%9E%E5%85%AC%E7%BD%91%E7%BB%9C/windows%E7%94%A8%E6%88%B7/%E5%A4%87%E9%80%89%E6%96%B9%E6%A1%88%EF%BC%88Windows%EF%BC%89/%E8%AF%81%E4%B9%A6%E5%AE%89%E8%A3%85%28windows%29/%E9%95%BF%E4%BA%AD%E6%A0%B9%E8%AF%81%E4%B9%A6%E5%AE%89%E8%A3%85%28windows%29)\n"),
16
+ var _useState = useState(":wolf:\n\n本文用以记录 Gitlab 相关问题及解答\n\n## 我在使用 `git@git.in.chaitin.net:ns/repo` 时可以访问仓库,但是 `https://git.in.chaitin.net/ns/repo` 无法访问\n\n问题通常出现 git clone 与其他依赖 git 进行的操作,如 `go get` 等,具体报错可能为 `Permission Denied`.\n\n在使用 curl 借助 `CI_JOB_TOKEN` 获取其他仓库 cicd job 产物或者 generic package 时,其具体报错为 `404 Not Found` 的问题.\n\n原因是在使用 `git@git.in.chaitin.net` 时,使用的是 ssh 协议,此时默认使用的是 `~/.ssh` 下的私钥进行认证你在 gitlab 中添加的 `SSH Keys`。而使用 `https://git.in.chaitin.net/ns/repo` 时,使用的是 http 协议,此时默认使用的是 `~/.netrc` 认证你在 gitlab 中申请的 `Access tokens`。部分软件如 `go get` 默认使用的便是 http 来拉取代码,因此需要额外配置。\n\n这里推荐两种解决方案:\n\n1. 配置 `~/.netrc` 文件(推荐)\n\n 在 ~/.netrc 文件中添加以下配置:\n\n ```text\n machine git.in.chaitin.net login git password <your access token>\n ```\n\n 在 gitlab cicd job 中遇到拉取其他仓库时遇到权限问题可以使用本配置,比如可以在 job 的 `before_script` 阶段添加以下命令:\n\n ```shell\n echo \"machine git.in.chaitin.net login git password $CI_JOB_TOKEN\" >> ~/.netrc\n ```\n\n 注意: 其中 `$CI_JOB_TOKEN` 是 job 运行期间生成的 token,其权限与 trigger 用户相同,详见 [CI Job Token](https://docs.gitlab.com/ci/jobs/ci_job_token/)。其 Token 权限由 `pipeline 触发者`权限以及`目标仓库权限`共同决定。因此被拉取的目标仓库也需要保证其 `Setting -> CI/CD -> Job token permissions` 配置正确,允许源仓库的 CI/CD 能够访问到该仓库,否则依然会出现如 `404 Not Found`, `403 Forbidden` 的权限问题。(如果你是 pipeline 触发者,可以手动在浏览器通过 gitlab api 访问目标仓库的 generic package 或者 job artifact 如果可以正常下载,说明是 `Job token permissions` 问题)\n\n2. 配置 `git url replace`\n\n 在 ~/.gitconfig 文件中添加以下配置:\n\n ```ini\n [url \"git@git.in.chaitin.net:\"]\n insteadOf = https://git.in.chaitin.net/\n ```\n\n 这个配置可以将所有 `https://git.in.chaitin.net/` 请求替换为 `git@git.in.chaitin.net:` 使用 ssh 来拉取代码仓库\n\n## 我在 clone gitlab 仓库时没问题,但是 lfs 遇到了 EOF 问题\n\nEOF 在大多数情况下由代理导致,如果代理不允许客户端访问某个网站,行为可能是提早结束连接,导致 `EOF` 错误。如\n\n> 在 ubunu 虚拟机里无法拉取 safeline-aliyun 项目里的 lfs 文件怎么处理?\n\n```bash\nroot@OPS-5108:~/proj/safeline-aliyun# git lfs fetch --all\nfetch: 34 object(s) found, done.\nfetch: Fetching all references...\nbatch response: Post https://git.in.chaitin.net/patronus/safeline-aliyun.git/info/lfs/objects/batch: EOF\nerror: failed to fetch some objects from 'https://git.in.chaitin.net/patronus/safeline-aliyun.git/info/lfs'\n```\n\n可以看到返回了 EOF 问题,经查代理未配置在 git config 中。从 `env` 中可以看到用户配置了 *_proxy 但其中发现 `no_proxy` 配置不正确:\n\n```shell\nroot@OPS-5108:~/proj/safeline-aliyun# env | grep pro\nno_proxy=localhost, 127.0.0.1, ::1\nPWD=/root/proj/safeline-aliyun\nftp_proxy=http://proxy.in.chaitin.net:8123\nhttps_proxy=http://proxy.in.chaitin.net:8123\nproxy=http://proxy.in.chaitin.net:8123\nhttp_proxy=http://proxy.in.chaitin.net:8123\nOLDPWD=/root/proj\n```\n\n需要按照 [代理配置](https://info.chaitin.net/colab-editor/page/%E7%A0%94%E5%8F%91%E4%BD%93%E7%B3%BB%2F%E7%A0%94%E5%8F%91%E6%94%AF%E6%8C%81%2F%E4%BB%A3%E7%90%86%E6%89%AB%E7%9B%B2) 进行正确配置后,重新执行操作,发现 EOF 问题被解决。\n\n## 我在访问公司内部服务时报错 `x509: certificate signed by unknown authority`\n\n公司部分内部服务采用自签名证书,导致客户端在访问这些服务时会遇到 `x509: certificate signed by unknown authority` 错误。为了确保客户端能够信任这些自签名证书,你需要配置信任自签名证书即 CA。\n\n以 debian 系系统举例:\n\n```shell\ncurl -o /usr/local/share/ca-certificates/chaitin_ca.crt -L https://chaitin-ops-public.cn-beijing.oss.aliyuncs.com/Chaitin_Ltd_Root_CA.pem\nupdate-ca-certificates\n```\n\n如果无法访问外网,可以尝试 `http://s3-ephemeral.in.chaitin.net/dev/Chaitin_Ltd_Root_CA.pem`\n\n其他系统 CA 证书安装请参考 [安装CA证书](https://info.chaitin.net/colab-editor/page/IT%E5%8A%9E%E5%85%AC/%E5%8A%9E%E5%85%AC%E7%BD%91%E7%BB%9C/windows%E7%94%A8%E6%88%B7/%E5%A4%87%E9%80%89%E6%96%B9%E6%A1%88%EF%BC%88Windows%EF%BC%89/%E8%AF%81%E4%B9%A6%E5%AE%89%E8%A3%85%28windows%29/%E9%95%BF%E4%BA%AD%E6%A0%B9%E8%AF%81%E4%B9%A6%E5%AE%89%E8%A3%85%28windows%29)\n"),
17
17
  _useState2 = _slicedToArray(_useState, 2),
18
18
  mdContent = _useState2[0],
19
19
  setMdContent = _useState2[1];
@@ -157,9 +157,7 @@ var Reader = function Reader() {
157
157
  editor: editor,
158
158
  height: '500px',
159
159
  value: mdContent,
160
- splitMode: true
161
- // showToolbar={false}
162
- ,
160
+ splitMode: true,
163
161
  defaultDisplayMode: "split",
164
162
  placeholder: "\u8BF7\u8F93\u5165\u5185\u5BB9",
165
163
  onUpload: onUpload,
@@ -7,6 +7,6 @@ export interface UploadProgressAttributes {
7
7
  tempId: string;
8
8
  }
9
9
  export declare const getFileIcon: (fileType: string) => React.JSX.Element;
10
- export declare const getFileTypeText: (fileType: string) => "视频" | "音频" | "图片" | "文件";
10
+ export declare const getFileTypeText: (fileType: string) => "图片" | "视频" | "音频" | "文件";
11
11
  declare const UploadProgressView: React.FC<NodeViewProps>;
12
12
  export default UploadProgressView;
@@ -1,2 +1,2 @@
1
1
  import { GetExtensionsProps } from '../type';
2
- export declare const getExtensions: ({ contentType, limit, exclude, extensions: extensionsProps, youtube, editable, mentionItems, onMentionFilter, onUpload, onError, onTocUpdate, onAiWritingGetSuggestion, onValidateUrl, placeholder, tableOfContentsOptions, }: GetExtensionsProps) => any;
2
+ export declare const getExtensions: ({ limit, exclude, extensions: extensionsProps, editable, mentionItems, baseUrl, onMentionFilter, onUpload, onError, onTocUpdate, onAiWritingGetSuggestion, onValidateUrl, placeholder, youtubeOptions, tableOfContentsOptions, }: GetExtensionsProps) => any;
@@ -16,13 +16,13 @@ import { AiWritingExtension, ImeComposition, SlashCommands, StructuredDiffExtens
16
16
  import { CodeExtension } from "./mark/Code";
17
17
  import { AlertExtension, AudioExtension, BlockAttachmentExtension, BlockLinkExtension, CodeBlockLowlightExtension, CustomBlockMathExtension, CustomHorizontalRule, CustomInlineMathExtension, CustomSubscript, CustomSuperscript, DetailsContentExtension, DetailsExtension, DetailsSummaryExtension, EmojiExtension, FileHandlerExtension, FlowExtension, IframeExtension, ImageExtension, Indent, InlineAttachmentExtension, InlineLinkExtension, InlineUploadProgressExtension, ListExtension, MentionExtension, TableExtension, TableOfContents, UploadProgressExtension, VerticalAlign, VideoExtension, YamlFormat, YoutubeExtension } from "./node";
18
18
  export var getExtensions = function getExtensions(_ref) {
19
- var contentType = _ref.contentType,
20
- limit = _ref.limit,
19
+ var limit = _ref.limit,
21
20
  exclude = _ref.exclude,
22
21
  extensionsProps = _ref.extensions,
23
- youtube = _ref.youtube,
24
22
  editable = _ref.editable,
25
23
  mentionItems = _ref.mentionItems,
24
+ _ref$baseUrl = _ref.baseUrl,
25
+ baseUrl = _ref$baseUrl === void 0 ? '' : _ref$baseUrl,
26
26
  onMentionFilter = _ref.onMentionFilter,
27
27
  onUpload = _ref.onUpload,
28
28
  onError = _ref.onError,
@@ -30,6 +30,7 @@ export var getExtensions = function getExtensions(_ref) {
30
30
  onAiWritingGetSuggestion = _ref.onAiWritingGetSuggestion,
31
31
  onValidateUrl = _ref.onValidateUrl,
32
32
  _placeholder = _ref.placeholder,
33
+ youtubeOptions = _ref.youtubeOptions,
33
34
  tableOfContentsOptions = _ref.tableOfContentsOptions;
34
35
  var defaultExtensions = [ImeComposition, StarterKit.configure({
35
36
  link: false,
@@ -45,34 +46,39 @@ export var getExtensions = function getExtensions(_ref) {
45
46
  color: 'var(--mui-palette-primary-main)',
46
47
  width: 2
47
48
  }
48
- }), TextStyleKit, CodeExtension, ListExtension, EmojiExtension, AlertExtension, CustomSubscript, DetailsExtension, CustomSuperscript, DetailsContentExtension, DetailsSummaryExtension, CodeBlockLowlightExtension, InlineUploadProgressExtension, YamlFormat, InlineLinkExtension, BlockLinkExtension, CustomHorizontalRule, IframeExtension({
49
+ }), YamlFormat, TextStyleKit, CodeExtension, ListExtension, EmojiExtension, AlertExtension, CustomSubscript, DetailsExtension, CustomSuperscript, DetailsContentExtension, DetailsSummaryExtension, CodeBlockLowlightExtension, InlineUploadProgressExtension, CustomHorizontalRule].concat(_toConsumableArray(TableExtension({
50
+ editable: editable
51
+ })), [CustomBlockMathExtension({
52
+ onError: onError
53
+ }), CustomInlineMathExtension({
54
+ onError: onError
55
+ }), TableOfContents({
56
+ onTocUpdate: onTocUpdate,
57
+ tableOfContentsOptions: tableOfContentsOptions
58
+ }), InlineLinkExtension, BlockLinkExtension, IframeExtension({
49
59
  onError: onError,
50
60
  onValidateUrl: onValidateUrl
51
61
  }), VideoExtension({
62
+ baseUrl: baseUrl,
52
63
  onUpload: onUpload,
53
64
  onError: onError,
54
65
  onValidateUrl: onValidateUrl
55
66
  }), AudioExtension({
67
+ baseUrl: baseUrl,
56
68
  onUpload: onUpload,
57
69
  onError: onError,
58
70
  onValidateUrl: onValidateUrl
59
- })].concat(_toConsumableArray(TableExtension({
60
- editable: editable
61
- })), [TableOfContents({
62
- onTocUpdate: onTocUpdate,
63
- tableOfContentsOptions: tableOfContentsOptions
64
71
  }), ImageExtension({
72
+ baseUrl: baseUrl,
65
73
  onUpload: onUpload,
66
74
  onError: onError,
67
75
  onValidateUrl: onValidateUrl
68
- }), CustomBlockMathExtension({
69
- onError: onError
70
- }), CustomInlineMathExtension({
71
- onError: onError
72
76
  }), InlineAttachmentExtension({
77
+ baseUrl: baseUrl,
73
78
  onUpload: onUpload,
74
79
  onError: onError
75
80
  }), BlockAttachmentExtension({
81
+ baseUrl: baseUrl,
76
82
  onUpload: onUpload,
77
83
  onError: onError
78
84
  }), Highlight.configure({
@@ -163,7 +169,7 @@ export var getExtensions = function getExtensions(_ref) {
163
169
  defaultExtensions.push(Mention);
164
170
  }
165
171
  if (!(exclude !== null && exclude !== void 0 && exclude.includes('youtube'))) {
166
- var Youtube = YoutubeExtension(youtube);
172
+ var Youtube = YoutubeExtension(youtubeOptions);
167
173
  defaultExtensions.push(Youtube);
168
174
  }
169
175
  if (!(exclude !== null && exclude !== void 0 && exclude.includes('flow'))) {
@@ -24,5 +24,8 @@ declare module '@tiptap/core' {
24
24
  };
25
25
  }
26
26
  }
27
- export declare const InlineAttachmentExtension: (props: EditorFnProps) => Node<any, any>;
28
- export declare const BlockAttachmentExtension: (props: EditorFnProps) => Node<any, any>;
27
+ export type AttachmentExtensionProps = EditorFnProps & {
28
+ baseUrl: string;
29
+ };
30
+ export declare const InlineAttachmentExtension: (props: AttachmentExtensionProps) => Node<any, any>;
31
+ export declare const BlockAttachmentExtension: (props: AttachmentExtensionProps) => Node<any, any>;
@@ -4,6 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ import { removeBaseUrl, withBaseUrl } from "../../util";
7
8
  import { mergeAttributes, Node } from "@tiptap/core";
8
9
  import { ReactNodeViewRenderer } from "@tiptap/react";
9
10
  import AttachmentViewWrapper from "../component/Attachment";
@@ -16,30 +17,21 @@ export var InlineAttachmentExtension = function InlineAttachmentExtension(props)
16
17
  atom: true,
17
18
  draggable: true,
18
19
  selectable: true,
19
- addOptions: function addOptions() {
20
- return {
21
- HTMLAttributes: {
22
- url: '',
23
- title: '',
24
- size: '0'
25
- }
26
- };
27
- },
28
20
  addAttributes: function addAttributes() {
29
21
  return {
30
22
  url: {
31
- default: this.options.HTMLAttributes.url,
23
+ default: '',
32
24
  parseHTML: function parseHTML(element) {
33
- return element.getAttribute('data-url');
25
+ return withBaseUrl(element.getAttribute('data-url') || '', props.baseUrl);
34
26
  },
35
27
  renderHTML: function renderHTML(attributes) {
36
28
  return {
37
- 'data-url': attributes.url
29
+ 'data-url': removeBaseUrl(attributes.url, props.baseUrl)
38
30
  };
39
31
  }
40
32
  },
41
33
  title: {
42
- default: this.options.HTMLAttributes.title,
34
+ default: '',
43
35
  parseHTML: function parseHTML(element) {
44
36
  return element.getAttribute('data-title');
45
37
  },
@@ -50,7 +42,7 @@ export var InlineAttachmentExtension = function InlineAttachmentExtension(props)
50
42
  }
51
43
  },
52
44
  size: {
53
- default: this.options.HTMLAttributes.size,
45
+ default: '0',
54
46
  parseHTML: function parseHTML(element) {
55
47
  return element.getAttribute('data-size') || '0';
56
48
  },
@@ -157,30 +149,22 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
157
149
  atom: true,
158
150
  draggable: true,
159
151
  selectable: true,
160
- addOptions: function addOptions() {
161
- return {
162
- HTMLAttributes: {
163
- url: '',
164
- title: '',
165
- size: '0'
166
- }
167
- };
168
- },
169
152
  addAttributes: function addAttributes() {
170
153
  return {
171
154
  url: {
172
- default: this.options.HTMLAttributes.url,
155
+ default: '',
173
156
  parseHTML: function parseHTML(element) {
174
- return element.getAttribute('data-url');
157
+ return withBaseUrl(element.getAttribute('data-url') || '', props.baseUrl);
175
158
  },
176
159
  renderHTML: function renderHTML(attributes) {
160
+ if (!attributes.url) return {};
177
161
  return {
178
- 'data-url': attributes.url
162
+ 'data-url': removeBaseUrl(attributes.url, props.baseUrl)
179
163
  };
180
164
  }
181
165
  },
182
166
  title: {
183
- default: this.options.HTMLAttributes.title,
167
+ default: '',
184
168
  parseHTML: function parseHTML(element) {
185
169
  return element.getAttribute('data-title');
186
170
  },
@@ -191,7 +175,7 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
191
175
  }
192
176
  },
193
177
  size: {
194
- default: this.options.HTMLAttributes.size,
178
+ default: '0',
195
179
  parseHTML: function parseHTML(element) {
196
180
  return element.getAttribute('data-size') || '0';
197
181
  },
@@ -18,6 +18,8 @@ declare module '@tiptap/core' {
18
18
  };
19
19
  }
20
20
  }
21
- export type AudioExtensionProps = EditorFnProps;
21
+ export type AudioExtensionProps = EditorFnProps & {
22
+ baseUrl: string;
23
+ };
22
24
  export declare const AudioExtension: (props: AudioExtensionProps) => Node<any, any>;
23
25
  export default AudioExtension;
@@ -4,6 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ import { removeBaseUrl, withBaseUrl } from "../../util";
7
8
  import { InputRule, mergeAttributes, Node } from '@tiptap/core';
8
9
  import { ReactNodeViewRenderer } from '@tiptap/react';
9
10
  import AudioViewWrapper from "../component/Audio";
@@ -31,12 +32,12 @@ export var AudioExtension = function AudioExtension(props) {
31
32
  src: {
32
33
  default: null,
33
34
  parseHTML: function parseHTML(element) {
34
- return element.getAttribute('src');
35
+ return withBaseUrl(element.getAttribute('src') || '', props.baseUrl);
35
36
  },
36
37
  renderHTML: function renderHTML(attributes) {
37
38
  if (!attributes.src) return {};
38
39
  return {
39
- src: attributes.src
40
+ src: removeBaseUrl(attributes.src, props.baseUrl)
40
41
  };
41
42
  }
42
43
  },
@@ -1,6 +1,68 @@
1
- import Emoji, { gitHubEmojis } from "@tiptap/extension-emoji";
1
+ import Emoji, { emojiToShortcode, gitHubEmojis, shortcodeToEmoji } from "@tiptap/extension-emoji";
2
2
  import { emojiSuggestion } from "../suggestion/emoji";
3
- export var EmojiExtension = Emoji.configure({
3
+ var EMOJI_SHORTCODE_REGEX = /^:([a-zA-Z0-9_+-]+):/;
4
+ function extractEmojiName(token) {
5
+ if (token.name) {
6
+ return token.name;
7
+ }
8
+ if (token.shortcode) {
9
+ var emojiItem = shortcodeToEmoji(token.shortcode, gitHubEmojis);
10
+ if (emojiItem) {
11
+ return emojiItem.name;
12
+ }
13
+ }
14
+ if (typeof token.markup === 'string' && token.markup.startsWith(':') && token.markup.endsWith(':')) {
15
+ var shortcode = token.markup.slice(1, -1);
16
+ var _emojiItem = shortcodeToEmoji(shortcode, gitHubEmojis);
17
+ if (_emojiItem) {
18
+ return _emojiItem.name;
19
+ }
20
+ }
21
+ if (typeof token.emoji === 'string' && token.emoji) {
22
+ var _shortcode = emojiToShortcode(token.emoji, gitHubEmojis);
23
+ if (_shortcode) {
24
+ return _shortcode;
25
+ }
26
+ }
27
+ return null;
28
+ }
29
+ export var EmojiExtension = Emoji.extend({
30
+ markdownTokenName: 'emoji',
31
+ markdownTokenizer: {
32
+ name: 'emoji',
33
+ level: 'inline',
34
+ start: function start(src) {
35
+ return src.indexOf(':');
36
+ },
37
+ tokenize: function tokenize(src, _tokens, helpers) {
38
+ var match = EMOJI_SHORTCODE_REGEX.exec(src);
39
+ if (!match) {
40
+ return;
41
+ }
42
+ var shortcode = match[1];
43
+ var emojiItem = shortcodeToEmoji(shortcode, gitHubEmojis);
44
+ if (!emojiItem) {
45
+ return;
46
+ }
47
+ return {
48
+ type: 'emoji',
49
+ raw: match[0],
50
+ name: emojiItem.name,
51
+ shortcode: shortcode,
52
+ emoji: emojiItem.emoji || ''
53
+ };
54
+ }
55
+ },
56
+ parseMarkdown: function parseMarkdown(token, helpers) {
57
+ var name = extractEmojiName(token);
58
+ if (!name) {
59
+ return [];
60
+ }
61
+ return helpers.createNode('emoji', {
62
+ name: name
63
+ });
64
+ }
65
+ }).configure({
4
66
  emojis: gitHubEmojis,
5
67
  enableEmoticons: true,
6
68
  suggestion: emojiSuggestion
@@ -1,4 +1,4 @@
1
1
  import { UploadFunction } from "../../type";
2
2
  export declare const FileHandlerExtension: (props: {
3
3
  onUpload?: UploadFunction;
4
- }) => import("@tiptap/core").Extension<Omit<import("@tiptap/extension-file-handler").FileHandlePluginOptions, "key" | "editor">, any>;
4
+ }) => import("@tiptap/core").Extension<Omit<import("@tiptap/extension-file-handler").FileHandlePluginOptions, "editor" | "key">, any>;
@@ -1,3 +1,5 @@
1
1
  import { EditorFnProps } from "../../type";
2
- export type ImageExtensionProps = EditorFnProps;
2
+ export type ImageExtensionProps = EditorFnProps & {
3
+ baseUrl: string;
4
+ };
3
5
  export declare const ImageExtension: (props: ImageExtensionProps) => import("@tiptap/core").Node<import("@tiptap/extension-image").ImageOptions, any>;
@@ -7,13 +7,30 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
7
7
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
8
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
9
9
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
10
- import { getFileType } from "../../util";
10
+ import { getFileType, removeBaseUrl, withBaseUrl } from "../../util";
11
11
  import Image from "@tiptap/extension-image";
12
12
  import { Plugin, PluginKey } from "@tiptap/pm/state";
13
13
  import { ReactNodeViewRenderer } from "@tiptap/react";
14
14
  import ImageViewWrapper, { getImageDimensionsFromFile } from "../component/Image";
15
15
  var customImage = function customImage(props) {
16
16
  return Image.extend({
17
+ addAttributes: function addAttributes() {
18
+ var _this$parent;
19
+ return _objectSpread(_objectSpread({}, (_this$parent = this.parent) === null || _this$parent === void 0 ? void 0 : _this$parent.call(this)), {}, {
20
+ src: {
21
+ default: null,
22
+ parseHTML: function parseHTML(element) {
23
+ return withBaseUrl(element.getAttribute('src') || '', props.baseUrl);
24
+ },
25
+ renderHTML: function renderHTML(attributes) {
26
+ if (!attributes.src) return {};
27
+ return {
28
+ src: removeBaseUrl(attributes.src, props.baseUrl)
29
+ };
30
+ }
31
+ }
32
+ });
33
+ },
17
34
  addKeyboardShortcuts: function addKeyboardShortcuts() {
18
35
  var _this = this;
19
36
  return {
@@ -1,5 +1,5 @@
1
1
  import { Extension } from '@tiptap/core';
2
2
  export declare const TableExtension: ({ editable }: {
3
3
  editable: boolean;
4
- }) => (import("@tiptap/core").Node<import("@tiptap/extension-table").TableOptions, any> | import("@tiptap/core").Node<import("@tiptap/extension-table").TableHeaderOptions, any> | Extension<any, any>)[];
4
+ }) => (Extension<any, any> | import("@tiptap/core").Node<import("@tiptap/extension-table").TableOptions, any> | import("@tiptap/core").Node<import("@tiptap/extension-table").TableHeaderOptions, any>)[];
5
5
  export default TableExtension;
@@ -19,6 +19,8 @@ declare module '@tiptap/core' {
19
19
  };
20
20
  }
21
21
  }
22
- export type VideoExtensionProps = EditorFnProps;
22
+ export type VideoExtensionProps = EditorFnProps & {
23
+ baseUrl: string;
24
+ };
23
25
  export declare const VideoExtension: (props: VideoExtensionProps) => Node<any, any>;
24
26
  export default VideoExtension;
@@ -7,7 +7,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
7
7
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
8
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
9
9
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
10
- import { getFileType } from "../../util";
10
+ import { getFileType, removeBaseUrl, withBaseUrl } from "../../util";
11
11
  import { InputRule, mergeAttributes, Node } from '@tiptap/core';
12
12
  import { Plugin, PluginKey } from '@tiptap/pm/state';
13
13
  import { ReactNodeViewRenderer } from '@tiptap/react';
@@ -37,12 +37,12 @@ export var VideoExtension = function VideoExtension(props) {
37
37
  src: {
38
38
  default: null,
39
39
  parseHTML: function parseHTML(element) {
40
- return element.getAttribute('src');
40
+ return withBaseUrl(element.getAttribute('src') || '', props.baseUrl);
41
41
  },
42
42
  renderHTML: function renderHTML(attributes) {
43
43
  if (!attributes.src) return {};
44
44
  return {
45
- src: attributes.src
45
+ src: removeBaseUrl(attributes.src, props.baseUrl)
46
46
  };
47
47
  }
48
48
  },
@@ -1,3 +1,3 @@
1
1
  import { YoutubeOptions } from "@tiptap/extension-youtube";
2
- export declare const YoutubeExtension: (youtube?: Partial<YoutubeOptions>) => import("@tiptap/core").Node<YoutubeOptions, any>;
2
+ export declare const YoutubeExtension: (youtubeOptions?: Partial<YoutubeOptions>) => import("@tiptap/core").Node<YoutubeOptions, any>;
3
3
  export default YoutubeExtension;
@@ -5,10 +5,10 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
7
  import Youtube from "@tiptap/extension-youtube";
8
- export var YoutubeExtension = function YoutubeExtension(youtube) {
8
+ export var YoutubeExtension = function YoutubeExtension(youtubeOptions) {
9
9
  return Youtube.configure(_objectSpread({
10
10
  ccLanguage: 'zh-CN',
11
11
  nocookie: true
12
- }, youtube));
12
+ }, youtubeOptions));
13
13
  };
14
14
  export default YoutubeExtension;
@@ -1,4 +1,4 @@
1
1
  import { UseTiptapProps, UseTiptapReturn } from "../type";
2
2
  import { UseEditorOptions } from '@tiptap/react';
3
- declare const useTiptap: ({ exclude, extensions: extensionsProps, mentionItems, onMentionFilter, onSave, onError, onUpload, onTocUpdate, onAiWritingGetSuggestion, onValidateUrl, editable, contentType, placeholder, tableOfContentsOptions, ...options }: UseTiptapProps & UseEditorOptions) => UseTiptapReturn;
3
+ declare const useTiptap: ({ editable, contentType, onSave, onError, onUpload, baseUrl, ...options }: UseTiptapProps & UseEditorOptions) => UseTiptapReturn;
4
4
  export default useTiptap;
@@ -1,5 +1,5 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["exclude", "extensions", "mentionItems", "onMentionFilter", "onSave", "onError", "onUpload", "onTocUpdate", "onAiWritingGetSuggestion", "onValidateUrl", "editable", "contentType", "placeholder", "tableOfContentsOptions"];
2
+ var _excluded = ["editable", "contentType", "onSave", "onError", "onUpload", "baseUrl"];
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
5
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -8,40 +8,31 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
8
8
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
9
9
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
10
10
  import { getExtensions } from "../extension";
11
+ import { withBaseUrl } from "../util";
11
12
  import { migrateMathStrings } from '@tiptap/extension-mathematics';
12
13
  import { useEditor } from '@tiptap/react';
13
14
  var useTiptap = function useTiptap(_ref) {
14
- var exclude = _ref.exclude,
15
- extensionsProps = _ref.extensions,
16
- mentionItems = _ref.mentionItems,
17
- onMentionFilter = _ref.onMentionFilter,
15
+ var _ref$editable = _ref.editable,
16
+ editable = _ref$editable === void 0 ? true : _ref$editable,
17
+ _ref$contentType = _ref.contentType,
18
+ contentType = _ref$contentType === void 0 ? 'html' : _ref$contentType,
18
19
  onSave = _ref.onSave,
19
20
  onError = _ref.onError,
20
21
  onUpload = _ref.onUpload,
21
- onTocUpdate = _ref.onTocUpdate,
22
- onAiWritingGetSuggestion = _ref.onAiWritingGetSuggestion,
23
- onValidateUrl = _ref.onValidateUrl,
24
- _ref$editable = _ref.editable,
25
- editable = _ref$editable === void 0 ? true : _ref$editable,
26
- contentType = _ref.contentType,
27
- placeholder = _ref.placeholder,
28
- tableOfContentsOptions = _ref.tableOfContentsOptions,
22
+ _ref$baseUrl = _ref.baseUrl,
23
+ baseUrl = _ref$baseUrl === void 0 ? '' : _ref$baseUrl,
29
24
  options = _objectWithoutProperties(_ref, _excluded);
30
- var extensions = getExtensions({
31
- contentType: contentType,
32
- exclude: exclude,
33
- extensions: extensionsProps,
25
+ var handleUpload = onUpload ? function (file, onProgress, abortSignal) {
26
+ return onUpload(file, onProgress, abortSignal).then(function (url) {
27
+ return withBaseUrl(url, baseUrl);
28
+ });
29
+ } : undefined;
30
+ var extensions = getExtensions(_objectSpread({
34
31
  editable: editable,
35
- mentionItems: mentionItems,
36
- onMentionFilter: onMentionFilter,
37
- onUpload: onUpload,
38
32
  onError: onError,
39
- onTocUpdate: onTocUpdate,
40
- onAiWritingGetSuggestion: onAiWritingGetSuggestion,
41
- onValidateUrl: onValidateUrl,
42
- placeholder: placeholder,
43
- tableOfContentsOptions: tableOfContentsOptions
44
- });
33
+ baseUrl: baseUrl,
34
+ onUpload: handleUpload
35
+ }, options));
45
36
  var editor = useEditor(_objectSpread(_objectSpread(_objectSpread({
46
37
  editable: editable,
47
38
  extensions: extensions
@@ -50,16 +41,13 @@ var useTiptap = function useTiptap(_ref) {
50
41
  } : {}), options), {}, {
51
42
  editorProps: {
52
43
  handleKeyDown: function handleKeyDown(view, event) {
53
- // 编辑模式下保存
54
- if (event.key === 's' && (event.metaKey || event.ctrlKey) && editable && onSave) {
44
+ if (editable && event.key === 's' && (event.metaKey || event.ctrlKey) && onSave) {
55
45
  event.preventDefault();
56
46
  onSave === null || onSave === void 0 || onSave(editor);
57
47
  return true;
58
48
  }
59
- // tab
60
49
  if (event.key === 'Tab') {
61
50
  var _storage;
62
- // 若开启了 aiWriting,则放行给扩展处理(Tab 接受建议),不再插入制表符
63
51
  var aiWritingEnabled = !!(editor !== null && editor !== void 0 && (_storage = editor.storage) !== null && _storage !== void 0 && (_storage = _storage.aiWriting) !== null && _storage !== void 0 && _storage.enabled);
64
52
  if (aiWritingEnabled) {
65
53
  return false;
@@ -81,7 +69,6 @@ var useTiptap = function useTiptap(_ref) {
81
69
  (_options$onCreate = options.onCreate) === null || _options$onCreate === void 0 || _options$onCreate.call(options, {
82
70
  editor: currentEditor
83
71
  });
84
- // 处理数学公式 - 延迟执行确保文档完全准备好
85
72
  setTimeout(function () {
86
73
  try {
87
74
  migrateMathStrings(currentEditor);
@@ -90,26 +77,16 @@ var useTiptap = function useTiptap(_ref) {
90
77
  onError === null || onError === void 0 || onError(error);
91
78
  }
92
79
  }, 100);
93
- },
94
- onSelectionUpdate: function onSelectionUpdate(props) {
95
- if (options.onSelectionUpdate) {
96
- options.onSelectionUpdate(props);
97
- }
98
- },
99
- onContentError: function onContentError(props) {
100
- if (options.onContentError) {
101
- options.onContentError(props);
102
- }
103
- onError === null || onError === void 0 || onError(props.error);
104
80
  }
105
81
  }));
106
82
  return {
107
83
  editor: editor,
108
84
  setContent: function setContent(value, type) {
109
- var _editor$chain;
110
- editor === null || editor === void 0 || (_editor$chain = editor.chain()) === null || _editor$chain === void 0 || (_editor$chain = _editor$chain.focus()) === null || _editor$chain === void 0 || (_editor$chain = _editor$chain.setContent(value, {
85
+ var _editor$chain$focus$s;
86
+ if (!editor) return;
87
+ (_editor$chain$focus$s = editor.chain().focus().setContent(value, {
111
88
  contentType: type || (contentType === 'markdown' ? 'markdown' : 'html')
112
- })) === null || _editor$chain === void 0 || _editor$chain.run();
89
+ })) === null || _editor$chain$focus$s === void 0 || _editor$chain$focus$s.run();
113
90
  },
114
91
  getContent: function getContent() {
115
92
  if (!editor) return '';
@@ -123,13 +100,16 @@ var useTiptap = function useTiptap(_ref) {
123
100
  return editor.getMarkdown();
124
101
  },
125
102
  getText: function getText() {
126
- return (editor === null || editor === void 0 ? void 0 : editor.getText()) || '';
103
+ if (!editor) return '';
104
+ return editor.getText() || '';
127
105
  },
128
106
  getHTML: function getHTML() {
129
- return (editor === null || editor === void 0 ? void 0 : editor.getHTML()) || '';
107
+ if (!editor) return '';
108
+ return editor.getHTML() || '';
130
109
  },
131
110
  getJSON: function getJSON() {
132
- return (editor === null || editor === void 0 ? void 0 : editor.getJSON()) || null;
111
+ if (!editor) return null;
112
+ return editor.getJSON() || null;
133
113
  }
134
114
  };
135
115
  };
@@ -76,13 +76,28 @@ export type TocItem = {
76
76
  export type TocList = TocItem[];
77
77
  export type ValidateUrlFunction = (url: string, type: 'image' | 'video' | 'audio' | 'iframe') => Promise<string> | string;
78
78
  export type EditorFnProps = {
79
+ /**
80
+ * 错误处理
81
+ */
79
82
  onError?: (error: Error) => void;
83
+ /**
84
+ * 上传处理
85
+ */
80
86
  onUpload?: UploadFunction;
87
+ /**
88
+ * 目录更新
89
+ */
81
90
  onTocUpdate?: (toc: TocList) => void;
91
+ /**
92
+ * AI 写作建议
93
+ */
82
94
  onAiWritingGetSuggestion?: ({ prefix, suffix }: {
83
95
  prefix: string;
84
96
  suffix: string;
85
97
  }) => Promise<string>;
98
+ /**
99
+ * 验证 URL
100
+ */
86
101
  onValidateUrl?: ValidateUrlFunction;
87
102
  };
88
103
  export type MentionItems = string[];
@@ -92,16 +107,45 @@ export type MentionExtensionProps = {
92
107
  query: string;
93
108
  }) => Promise<MentionItems>;
94
109
  };
95
- export type ExtensionRelativeProps = MentionExtensionProps & EditorFnProps & {
110
+ export type NodeOrMetaOrSuggestionOrExtensionOptions = {
111
+ youtubeOptions?: Partial<YoutubeOptions>;
112
+ tableOfContentsOptions?: Partial<TableOfContentsOptions>;
113
+ };
114
+ export type BaseExtensionOptions = {
115
+ /**
116
+ * 字数限制
117
+ */
96
118
  limit?: number | null;
119
+ /**
120
+ * 排除的扩展
121
+ */
97
122
  exclude?: string[];
123
+ /**
124
+ * 扩展
125
+ * @default []
126
+ */
98
127
  extensions?: Extension[];
128
+ /**
129
+ * 是否可编辑
130
+ * @default true
131
+ */
99
132
  editable: boolean;
100
- youtube?: Partial<YoutubeOptions>;
133
+ /**
134
+ * 内容类型
135
+ * @default 'html'
136
+ * @description 支持 'html' 和 'markdown' 和 'json'
137
+ */
101
138
  contentType?: UseEditorOptions['contentType'];
139
+ /**
140
+ * 占位符
141
+ */
102
142
  placeholder?: string;
103
- tableOfContentsOptions?: TableOfContentsOptions;
143
+ /**
144
+ * 静态资源基础路径
145
+ */
146
+ baseUrl?: string;
104
147
  };
148
+ export type ExtensionRelativeProps = MentionExtensionProps & NodeOrMetaOrSuggestionOrExtensionOptions & EditorFnProps & BaseExtensionOptions;
105
149
  export type UseTiptapProps = {
106
150
  onSave?: (editor: Editor) => void;
107
151
  } & ExtensionRelativeProps;
@@ -7,6 +7,8 @@ export * from './shortcutKey';
7
7
  import { Node } from '@tiptap/pm/model';
8
8
  import { EditorState } from '@tiptap/pm/state';
9
9
  import { Editor } from '@tiptap/react';
10
+ export declare const withBaseUrl: (url: string, baseUrl: string) => string;
11
+ export declare const removeBaseUrl: (url: string, baseUrl: string) => string;
10
12
  export declare const formatFileSize: (bytes: number) => string;
11
13
  export declare const insertNodeAfterPosition: (editor: Editor, pos: number, nodeContent: any) => void;
12
14
  export declare const hasMarksInBlock: (node: Node | null | undefined) => boolean;
@@ -4,6 +4,44 @@ export * from "./floating";
4
4
  export * from "./linewiseConvert";
5
5
  export * from "./resourceExtractor";
6
6
  export * from "./shortcutKey";
7
+ export var withBaseUrl = function withBaseUrl(url, baseUrl) {
8
+ var _url$trim, _baseUrl$trim;
9
+ var trimmedUrl = (_url$trim = url === null || url === void 0 ? void 0 : url.trim()) !== null && _url$trim !== void 0 ? _url$trim : '';
10
+ if (!trimmedUrl) return trimmedUrl;
11
+ var isAbsolute = /^([a-z][a-z\d+\-.]*:)?\/\//i.test(trimmedUrl) || trimmedUrl.startsWith('data:');
12
+ if (isAbsolute) {
13
+ return trimmedUrl;
14
+ }
15
+ var trimmedBase = (_baseUrl$trim = baseUrl === null || baseUrl === void 0 ? void 0 : baseUrl.trim()) !== null && _baseUrl$trim !== void 0 ? _baseUrl$trim : '';
16
+ if (!trimmedBase) {
17
+ return trimmedUrl;
18
+ }
19
+ if (trimmedUrl.startsWith(trimmedBase)) {
20
+ return trimmedUrl;
21
+ }
22
+ var baseEndsWithSlash = trimmedBase.endsWith('/');
23
+ var urlStartsWithSlash = trimmedUrl.startsWith('/');
24
+ if (baseEndsWithSlash && urlStartsWithSlash) {
25
+ return "".concat(trimmedBase.slice(0, -1)).concat(trimmedUrl);
26
+ } else if (!baseEndsWithSlash && !urlStartsWithSlash) {
27
+ return "".concat(trimmedBase, "/").concat(trimmedUrl);
28
+ } else {
29
+ return "".concat(trimmedBase).concat(trimmedUrl);
30
+ }
31
+ };
32
+ export var removeBaseUrl = function removeBaseUrl(url, baseUrl) {
33
+ var _url$trim2, _baseUrl$trim2;
34
+ var trimmedUrl = (_url$trim2 = url === null || url === void 0 ? void 0 : url.trim()) !== null && _url$trim2 !== void 0 ? _url$trim2 : '';
35
+ if (!trimmedUrl) return trimmedUrl;
36
+ var trimmedBase = (_baseUrl$trim2 = baseUrl === null || baseUrl === void 0 ? void 0 : baseUrl.trim()) !== null && _baseUrl$trim2 !== void 0 ? _baseUrl$trim2 : '';
37
+ if (!trimmedBase) {
38
+ return trimmedUrl;
39
+ }
40
+ if (trimmedUrl.startsWith(trimmedBase)) {
41
+ return trimmedUrl.slice(trimmedBase.length);
42
+ }
43
+ return trimmedUrl;
44
+ };
7
45
  export var formatFileSize = function formatFileSize(bytes) {
8
46
  if (bytes === 0) return '0 B';
9
47
  var k = 1024;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctzhian/tiptap",
3
- "version": "2.4.3",
3
+ "version": "2.5.0",
4
4
  "description": "基于 Tiptap 二次开发的编辑器组件",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",