diff --git a/examples/Root.vue b/examples/Root.vue index fc58ded..24cd91a 100644 --- a/examples/Root.vue +++ b/examples/Root.vue @@ -1,21 +1,97 @@ diff --git a/examples/components/ArticleShowcase.vue b/examples/components/ArticleShowcase.vue new file mode 100644 index 0000000..0a648c6 --- /dev/null +++ b/examples/components/ArticleShowcase.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/examples/components/EditorShowcase.vue b/examples/components/EditorShowcase.vue new file mode 100644 index 0000000..9ef7582 --- /dev/null +++ b/examples/components/EditorShowcase.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/examples/components/NotifyShowcase.vue b/examples/components/NotifyShowcase.vue new file mode 100644 index 0000000..3c3e011 --- /dev/null +++ b/examples/components/NotifyShowcase.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/examples/demo-data.ts b/examples/demo-data.ts new file mode 100644 index 0000000..f2defa0 --- /dev/null +++ b/examples/demo-data.ts @@ -0,0 +1,59 @@ +import type { Article, NotifyDetail, UploadResult } from "timi-web/editor"; + +/** 编辑器演示使用的固定内容,避免每个页面各自维护一份 HTML。 */ +export const DEMO_ARTICLE_CONTENT = `

跨平台编辑器

+

这段内容同时验证标题、段落、链接、表格和代码块的渲染。

+

移动端和 PC 端只替换交互层,共享文档模型。

+
const message: string = "timi editor";
`; + +export const DEMO_CODE = `type DemoUser = { +\tid: string; +\tname: string; +}; + +const user: DemoUser = { +\tid: "demo-001", +\tname: "Timi" +}; + +console.log(user.name);`; + +export const DEMO_ARTICLE: Article = { + title: "编辑器组件演示文章", + description: "用于验证文章编辑、预览和附件处理。", + contentType: "TIP_TAP", + content: DEMO_ARTICLE_CONTENT, + attachmentList: [] +}; + +export const DEMO_NOTIFY: NotifyDetail = { + subject: "编辑器通知演示", + msgType: "INTERNAL", + contentType: "TIP_TAP", + content: DEMO_ARTICLE_CONTENT, + status: "WAITING", + attachmentList: [] +}; + +export function cloneArticle(): Article { + return { + ...DEMO_ARTICLE, + attachmentList: [...(DEMO_ARTICLE.attachmentList || [])] + }; +} + +export function cloneNotify(): NotifyDetail { + return { + ...DEMO_NOTIFY, + attachmentList: [...(DEMO_NOTIFY.attachmentList || [])] + }; +} + +/** 返回本地预览地址,让示例无需依赖后端上传接口。 */ +export async function uploadDemoMedia(file: File): Promise { + return { + id: `demo-${Date.now()}-${file.name}`, + name: file.name, + url: URL.createObjectURL(file) + }; +} diff --git a/examples/main.ts b/examples/main.ts index 1ac6180..fb17358 100644 --- a/examples/main.ts +++ b/examples/main.ts @@ -1,14 +1,11 @@ import { createApp } from "vue"; import Root from "./Root.vue"; -import TimiWebUI, { axios, Network, VPopup } from "timi-web"; // 本地开发 +import TimiWebUI, { VPopup } from "timi-web"; import "timi-web/style.css"; import "~/assets/style/tencent-cloud.less"; import "~/assets/style/tencent-cloud-custom.less"; -axios.defaults.baseURL = "http://localhost:8091"; -axios.interceptors.request.use(Network.userTokenInterceptors); - const app = createApp(Root); app.use(TimiWebUI); app.directive("popup", VPopup); diff --git a/package.json b/package.json index 0128c63..448d27b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,8 @@ "node": ">=16.0.0" }, "dependencies": { + "tdesign-vue-next": "^1.18.6", + "timi-web": "0.0.24", "vue": "^3.5.26" }, "devDependencies": { @@ -62,8 +64,6 @@ "vite-plugin-vue-setup-extend": "^0.4.0", "@vue/tsconfig": "^0.8.1", "vite": "7.3.1", - "vue-tsc": "^3.2.2", - "tdesign-vue-next": "^1.18.6", - "timi-web": "0.0.2" + "vue-tsc": "^3.2.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c43befc..c2c6d2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,12 @@ importers: .: dependencies: + tdesign-vue-next: + specifier: ^1.18.6 + version: 1.18.6(vue@3.5.26(typescript@5.9.3)) + timi-web: + specifier: 0.0.24 + version: 0.0.24(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3)) vue: specifier: ^3.5.26 version: 3.5.26(typescript@5.9.3) @@ -63,12 +69,6 @@ importers: prettier: specifier: ^3.8.0 version: 3.8.0 - tdesign-vue-next: - specifier: ^1.18.6 - version: 1.18.6(vue@3.5.26(typescript@5.9.3)) - timi-web: - specifier: 0.0.2 - version: 0.0.2 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -1462,6 +1462,15 @@ packages: '@vue/component-compiler-utils@3.3.0': resolution: {integrity: sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==} + '@vue/devtools-api@7.7.10': + resolution: {integrity: sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==} + + '@vue/devtools-kit@7.7.10': + resolution: {integrity: sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==} + + '@vue/devtools-shared@7.7.10': + resolution: {integrity: sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==} + '@vue/eslint-config-prettier@10.2.0': resolution: {integrity: sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==} peerDependencies: @@ -1602,6 +1611,10 @@ packages: resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} engines: {node: '>= 10.0.0'} + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + ajv-draft-04@1.0.0: resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} peerDependencies: @@ -1719,8 +1732,8 @@ packages: peerDependencies: postcss: ^8.1.0 - axios@1.13.5: - resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} + axios@1.18.0: + resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==} babel-loader@8.4.1: resolution: {integrity: sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==} @@ -1768,6 +1781,9 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -2153,6 +2169,10 @@ packages: copy-anything@2.0.6: resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + copy-anything@4.1.0: + resolution: {integrity: sha512-ufbM3smX/Jbnpk5wcQjzd1MgBpzmqfNETUAyZNrGwU9foRlyHoGzMMBBCRzEhQLBjZfFDE1W2ufPXX2vdWkV8Q==} + engines: {node: '>=18'} + copy-webpack-plugin@9.1.0: resolution: {integrity: sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==} engines: {node: '>= 12.13.0'} @@ -2704,6 +2724,15 @@ packages: debug: optional: true + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -2845,6 +2874,9 @@ packages: highlight.js@10.7.3: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -2908,6 +2940,10 @@ packages: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -3611,6 +3647,9 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + picocolors@0.2.1: resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==} @@ -3629,6 +3668,15 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + pinia@3.0.4: + resolution: {integrity: sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==} + peerDependencies: + typescript: '>=4.5.0' + vue: ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -3895,8 +3943,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} @@ -4025,6 +4074,9 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -4211,6 +4263,10 @@ packages: resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} engines: {node: '>=6.0.0'} + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -4280,6 +4336,10 @@ packages: peerDependencies: postcss: ^8.2.15 + superjson@2.2.6: + resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} + engines: {node: '>=16'} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -4339,11 +4399,6 @@ packages: uglify-js: optional: true - terser@5.39.0: - resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} - engines: {node: '>=10'} - hasBin: true - terser@5.46.1: resolution: {integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==} engines: {node: '>=10'} @@ -4365,8 +4420,8 @@ packages: thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} - timi-web@0.0.2: - resolution: {integrity: sha512-tXznHwCjFy/AtmWBky35V0SkLTeHG4FayzUhBRoUNe6a7xxlSQ0p8XcQAuSFkugQuCz8/pJsZNHgplfpzs041A==} + timi-web@0.0.24: + resolution: {integrity: sha512-qzcm72W9EE3BrYiUzc8a20J8xqxH17moEm/ovdijhRbIJtJUr81sslXFe2+OjNtx14meEIPJm3IfRooFzRswLg==} engines: {node: '>=16.0.0'} tinycolor2@1.6.0: @@ -4521,6 +4576,7 @@ packages: uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true validate-npm-package-license@3.0.4: @@ -4901,7 +4957,7 @@ snapshots: '@babel/core': 7.26.9 '@babel/helper-compilation-targets': 7.26.5 '@babel/helper-plugin-utils': 7.26.5 - debug: 4.4.0 + debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.10 transitivePeerDependencies: @@ -6554,6 +6610,24 @@ snapshots: - walrus - whiskers + '@vue/devtools-api@7.7.10': + dependencies: + '@vue/devtools-kit': 7.7.10 + + '@vue/devtools-kit@7.7.10': + dependencies: + '@vue/devtools-shared': 7.7.10 + birpc: 2.9.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.6 + + '@vue/devtools-shared@7.7.10': + dependencies: + rfdc: 1.4.1 + '@vue/eslint-config-prettier@10.2.0(@types/eslint@9.6.1)(eslint@9.39.2)(prettier@3.8.0)': dependencies: eslint: 9.39.2 @@ -6735,6 +6809,12 @@ snapshots: address@1.2.2: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + ajv-draft-04@1.0.0(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 @@ -6841,13 +6921,15 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 - axios@1.13.5: + axios@1.18.0: dependencies: - follow-redirects: 1.15.11(debug@4.4.3) + follow-redirects: 1.16.0 form-data: 4.0.5 - proxy-from-env: 1.1.0 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 transitivePeerDependencies: - debug + - supports-color babel-loader@8.4.1(@babel/core@7.26.9)(webpack@5.98.0): dependencies: @@ -6904,6 +6986,8 @@ snapshots: binary-extensions@2.3.0: {} + birpc@2.9.0: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -7157,6 +7241,8 @@ snapshots: dependencies: is-what: 3.14.1 + copy-anything@4.1.0: {} + copy-webpack-plugin@9.1.0(webpack@5.98.0): dependencies: fast-glob: 3.3.3 @@ -7769,6 +7855,8 @@ snapshots: optionalDependencies: debug: 4.4.3 + follow-redirects@1.16.0: {} + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -7903,6 +7991,8 @@ snapshots: highlight.js@10.7.3: {} + hookable@5.5.3: {} + hosted-git-info@2.8.9: {} hpack.js@2.1.6: @@ -7984,6 +8074,13 @@ snapshots: transitivePeerDependencies: - debug + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} iconv-lite@0.4.24: @@ -8605,6 +8702,8 @@ snapshots: pathe@2.0.3: {} + perfect-debounce@1.0.0: {} + picocolors@0.2.1: {} picocolors@1.1.1: {} @@ -8616,6 +8715,13 @@ snapshots: pify@4.0.1: optional: true + pinia@3.0.4(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3)): + dependencies: + '@vue/devtools-api': 7.7.10 + vue: 3.5.26(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -8878,7 +8984,7 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - proxy-from-env@1.1.0: {} + proxy-from-env@2.1.0: {} prr@1.0.1: optional: true @@ -9015,6 +9121,8 @@ snapshots: reusify@1.1.0: {} + rfdc@1.4.1: {} + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -9266,6 +9374,8 @@ snapshots: transitivePeerDependencies: - supports-color + speakingurl@14.0.1: {} + sprintf-js@1.0.3: {} ssri@8.0.1: @@ -9325,6 +9435,10 @@ snapshots: postcss: 8.5.6 postcss-selector-parser: 6.1.2 + superjson@2.2.6: + dependencies: + copy-anything: 4.1.0 + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -9385,16 +9499,9 @@ snapshots: jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 - terser: 5.39.0 + terser: 5.46.1 webpack: 5.98.0 - terser@5.39.0: - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.14.1 - commander: 2.20.3 - source-map-support: 0.5.21 - terser@5.46.1: dependencies: '@jridgewell/source-map': 0.3.6 @@ -9421,18 +9528,22 @@ snapshots: thunky@1.1.0: {} - timi-web@0.0.2: + timi-web@0.0.24(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3)): dependencies: - axios: 1.13.5 + axios: 1.18.0 less: 4.5.1 marked: 17.0.6 marked-gfm-heading-id: 4.1.4(marked@17.0.6) marked-highlight: 2.2.4(marked@17.0.6) marked-mangle: 1.1.13(marked@17.0.6) + pinia: 3.0.4(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3)) prismjs: 1.30.0 terser: 5.46.1 transitivePeerDependencies: - debug + - supports-color + - typescript + - vue tinycolor2@1.6.0: {} diff --git a/src/components/article-editor/index.ts b/src/components/article-editor/index.ts new file mode 100644 index 0000000..4fa4ced --- /dev/null +++ b/src/components/article-editor/index.ts @@ -0,0 +1,11 @@ +import view from "./index.vue"; +import { Toolkit } from "timi-web"; +import type { Article } from "timi-web/editor"; + +export type ArticleEditorExpose = { + submit: () => Promise
; + getPendingMediaCount: () => number; +}; + +export const ArticleEditor = Toolkit.withInstall(view); +export default ArticleEditor; diff --git a/src/components/article-editor/index.vue b/src/components/article-editor/index.vue new file mode 100644 index 0000000..c6b1978 --- /dev/null +++ b/src/components/article-editor/index.vue @@ -0,0 +1,289 @@ + + + diff --git a/src/components/article-view/index.ts b/src/components/article-view/index.ts new file mode 100644 index 0000000..190b030 --- /dev/null +++ b/src/components/article-view/index.ts @@ -0,0 +1,5 @@ +import view from "./index.vue"; +import { Toolkit } from "timi-web"; + +export const ArticleView = Toolkit.withInstall(view); +export default ArticleView; diff --git a/src/components/article-view/index.vue b/src/components/article-view/index.vue new file mode 100644 index 0000000..47e643d --- /dev/null +++ b/src/components/article-view/index.vue @@ -0,0 +1,118 @@ + + + + + diff --git a/src/components/authorize-form/login.vue b/src/components/authorize-form/login.vue index fd8a3c1..5e91c09 100644 --- a/src/components/authorize-form/login.vue +++ b/src/components/authorize-form/login.vue @@ -9,7 +9,7 @@
- +
@@ -24,7 +24,7 @@ diff --git a/src/components/code-editor/style.less b/src/components/code-editor/style.less new file mode 100644 index 0000000..b9453f4 --- /dev/null +++ b/src/components/code-editor/style.less @@ -0,0 +1,202 @@ +.tui-code-editor { + width: calc(100% - 2px); + min-width: 0; + border: 1px solid var(--td-component-stroke, #B8BBC9); + display: flex; + overflow: hidden; + background: transparent; + border-radius: var(--td-radius-medium, 0); + + .gutter { + flex: none; + color: var(--td-text-color-placeholder, #999); + overflow: hidden; + text-align: right; + background: #F2F2F2E6; + border-right: 1px solid var(--td-component-stroke, #B8BBC9); + + > span { + width: 3.25rem; + height: 1.5rem; + display: block; + font-size: 1rem; + font-family: "JetBrains Mono", "Fira Code", Consolas, "Courier New", monospace; + line-height: 1.5rem; + padding-right: .25rem; + } + } + + .body { + flex: 1; + min-width: 0; + min-height: 0; + position: relative; + overflow: hidden; + } + + .search-bar { + top: .5rem; + right: .5rem; + gap: .5rem; + z-index: 3; + display: flex; + padding: .5rem; + position: absolute; + align-items: center; + border-radius: var(--td-radius-default, .375rem); + background: var(--td-bg-color-container, #fff); + border: 1px solid var(--td-component-stroke, #B8BBC9); + box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .12); + } + + .search-input { + width: 10rem; + height: 2rem; + padding: 0 .5rem; + color: var(--td-text-color-primary, #111); + border: 1px solid var(--td-component-stroke, #B8BBC9); + background: var(--td-bg-color-container, #fff); + border-radius: var(--td-radius-default, .375rem); + font: inherit; + } + + .search-actions { + gap: .25rem; + display: flex; + align-items: center; + } + + .search-button { + height: 2rem; + padding: 0 .625rem; + color: var(--td-text-color-primary, #111); + border: 1px solid var(--td-component-stroke, #B8BBC9); + background: var(--td-bg-color-container, #fff); + border-radius: var(--td-radius-default, .375rem); + cursor: pointer; + + &:hover { + background: var(--td-bg-color-container-hover, #f6f6f6); + } + } + + .search-status { + color: var(--td-text-color-secondary, #666); + white-space: nowrap; + font-size: .875rem; + } + + .preview, + .input { + inset: 0; + width: 100%; + height: 100%; + margin: 0; + tab-size: 4; + overflow: auto; + max-width: 100%; + min-width: 0; + line-height: 1.5rem; + font-size: 1rem; + box-sizing: border-box; + font-family: "JetBrains Mono", "Fira Code", Consolas, "Courier New", monospace; + } + + .preview { + top: 0; + left: 0; + border: none; + position: absolute; + word-break: normal; + background: transparent; + transition: none; + white-space: pre; + border-radius: 0; + pointer-events: none; + + code { + padding: 0; + display: block; + width: max-content; + min-width: 100%; + min-height: 100%; + color: inherit; + background: transparent; + text-shadow: none; + font-size: inherit; + line-height: inherit; + font-family: inherit; + } + } + + .input { + top: 0; + left: 0; + color: transparent; + resize: none; + border: none; + outline: none; + position: absolute; + background: transparent; + white-space: pre; + word-break: normal; + overflow-wrap: normal; + caret-color: var(--td-text-color-primary, #111); + -webkit-text-fill-color: transparent; + } + + .input::placeholder { + color: var(--td-text-color-placeholder, #999); + -webkit-text-fill-color: var(--td-text-color-placeholder, #999); + } + + .input::selection { + background: rgb(0 122 255 / 18%); + } + + &.disabled { + opacity: .65; + } + + &.readonly { + .preview { + pointer-events: auto; + } + } +} + +@media (prefers-color-scheme: dark) { + .tui-code-editor { + border-color: var(--td-component-stroke, #434343); + + .gutter { + border-right-color: var(--td-component-stroke, #434343); + } + + .search-bar { + background: var(--td-bg-color-container, #1f1f1f); + border-color: var(--td-component-stroke, #434343); + box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .28); + } + + .search-input, + .search-button { + color: var(--td-text-color-primary, #F5F5F5); + border-color: var(--td-component-stroke, #434343); + background: var(--td-bg-color-container, #1f1f1f); + } + + .search-button:hover { + background: var(--td-bg-color-container-hover, #2b2b2b); + } + + .input { + caret-color: var(--td-text-color-primary, #F5F5F5); + } + + .input::selection { + background: rgb(64 153 255 / 28%); + } + } +} + diff --git a/src/components/comment/form/emits.ts b/src/components/comment/form/emits.ts deleted file mode 100644 index 8da9836..0000000 --- a/src/components/comment/form/emits.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Comment } from "timi-web"; - -/** - * emits - */ -export interface Emits { - (event: "submit"): Promise; -} - -export const useHandler = (emit: Emits) => { - - const onSubmit = async (comment: Comment) => await emit("submit"); - - return { - onSubmit, - }; -}; diff --git a/src/components/comment/form/index.ts b/src/components/comment/form/index.ts deleted file mode 100644 index ccc25e6..0000000 --- a/src/components/comment/form/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import view from "./index.vue"; -import { Toolkit } from "timi-web"; - -export const CommentForm = Toolkit.withInstall(view); -export default CommentForm; diff --git a/src/components/comment/form/index.vue b/src/components/comment/form/index.vue deleted file mode 100644 index 8691ee0..0000000 --- a/src/components/comment/form/index.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - - - diff --git a/src/components/comment/form/reply/emits.ts b/src/components/comment/form/reply/emits.ts deleted file mode 100644 index 5f7e70b..0000000 --- a/src/components/comment/form/reply/emits.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CommentReply } from "timi-web"; - -/** - * emits - */ -export interface Emits { - (event: "cancel"): Promise; - (event: "submit", reply: CommentReply): Promise; -} - -export const useHandler = (emit: Emits) => { - - const onCancel = async () => await emit("cancel"); - const onSubmit = async (reply: CommentReply) => await emit("submit", reply); - - return { - onCancel, - onSubmit - }; -}; diff --git a/src/components/comment/form/reply/index.ts b/src/components/comment/form/reply/index.ts deleted file mode 100644 index d7ff5c4..0000000 --- a/src/components/comment/form/reply/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import view from "./index.vue"; -import { Toolkit } from "timi-web"; - -export const CommentReplyForm = Toolkit.withInstall(view); -export default CommentReplyForm; diff --git a/src/components/comment/form/reply/index.vue b/src/components/comment/form/reply/index.vue deleted file mode 100644 index 6e99017..0000000 --- a/src/components/comment/form/reply/index.vue +++ /dev/null @@ -1,168 +0,0 @@ - - - - - diff --git a/src/components/comment/index.ts b/src/components/comment/index.ts deleted file mode 100644 index 3c12858..0000000 --- a/src/components/comment/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import view from "./index.vue"; -import { Toolkit } from "timi-web"; - -export const Comment = Toolkit.withInstall(view); -export default Comment; diff --git a/src/components/comment/index.vue b/src/components/comment/index.vue deleted file mode 100644 index 0e8659d..0000000 --- a/src/components/comment/index.vue +++ /dev/null @@ -1,148 +0,0 @@ - - - - - diff --git a/src/components/comment/list/emits.ts b/src/components/comment/list/emits.ts deleted file mode 100644 index 8ed4165..0000000 --- a/src/components/comment/list/emits.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * emits - */ -export interface Emits { -} - -export const useHandler = (emit: Emits) => { - - return { - }; -}; diff --git a/src/components/comment/list/index.ts b/src/components/comment/list/index.ts deleted file mode 100644 index f10d2c2..0000000 --- a/src/components/comment/list/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import view from "./index.vue"; -import { Toolkit } from "timi-web"; - -export const CommentList = Toolkit.withInstall(view); -export default CommentList; diff --git a/src/components/comment/list/index.vue b/src/components/comment/list/index.vue deleted file mode 100644 index 4512ec5..0000000 --- a/src/components/comment/list/index.vue +++ /dev/null @@ -1,240 +0,0 @@ - - - - - diff --git a/src/components/comment/list/reply/emits.ts b/src/components/comment/list/reply/emits.ts deleted file mode 100644 index 3b31e4d..0000000 --- a/src/components/comment/list/reply/emits.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Comment, CommentReply } from "timi-web"; - -/** - * emits - */ -export interface Emits { - (event: "reply", comment: Comment, replyTo?: CommentReply): Promise; -} - -export const useHandler = (emit: Emits) => { - - const onReply = async (comment: Comment, replyTo?: CommentReply) => await emit("reply", comment, replyTo); - - return { - onReply, - }; -}; diff --git a/src/components/comment/list/reply/index.ts b/src/components/comment/list/reply/index.ts deleted file mode 100644 index 54db3a2..0000000 --- a/src/components/comment/list/reply/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import view from "./index.vue"; -import { Toolkit } from "timi-web"; - -export const CommentReplyList = Toolkit.withInstall(view); -export default CommentReplyList; diff --git a/src/components/comment/list/reply/index.vue b/src/components/comment/list/reply/index.vue deleted file mode 100644 index 46fb0e7..0000000 --- a/src/components/comment/list/reply/index.vue +++ /dev/null @@ -1,179 +0,0 @@ - - - - - diff --git a/src/components/editor-search/index.vue b/src/components/editor-search/index.vue new file mode 100644 index 0000000..fb71e40 --- /dev/null +++ b/src/components/editor-search/index.vue @@ -0,0 +1,271 @@ + + + + + diff --git a/src/components/index.ts b/src/components/index.ts index f4a11c8..14d3a79 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,34 +1,56 @@ /** 导出所有组件 */ import AuthorizeForm from "~/components/authorize-form"; import RootLayout from "~/components/root-layout"; -import Comment from "~/components/comment"; -import CommentForm from "~/components/comment/form"; -import CommentList from "~/components/comment/list"; -import CommentReplyList from "~/components/comment/list/reply"; -import CommentReplyForm from "~/components/comment/form/reply"; import UserProfile from "~/components/user-profile"; import UserProfilePopup from "~/components/user-profile/popup"; +import CodeEditor from "~/components/code-editor"; +import TiptapEditor from "~/components/tiptap-editor"; +import TiptapView from "~/components/tiptap-view"; +import ArticleEditor from "~/components/article-editor"; +import ArticleView from "~/components/article-view"; +import NotifyEditor from "~/components/notify-editor"; +import NotifyView from "~/components/notify-view"; export default [ RootLayout, AuthorizeForm, - Comment, - CommentForm, - CommentReplyForm, - CommentList, - CommentReplyList, UserProfile, - UserProfilePopup + UserProfilePopup, + CodeEditor, + TiptapEditor, + TiptapView, + ArticleEditor, + ArticleView, + NotifyEditor, + NotifyView ]; export { RootLayout, AuthorizeForm, - Comment, - CommentForm, - CommentReplyForm, - CommentList, - CommentReplyList, UserProfile, - UserProfilePopup + UserProfilePopup, + CodeEditor, + TiptapEditor, + TiptapView, + ArticleEditor, + ArticleView, + NotifyEditor, + NotifyView }; + +export type { + CodeEditorExpose +} from "./code-editor"; + +export type { + TiptapEditorExpose +} from "./tiptap-editor"; + +export type { + ArticleEditorExpose +} from "./article-editor"; + +export type { + NotifyEditorExpose +} from "./notify-editor"; diff --git a/src/components/message.ts b/src/components/message.ts new file mode 100644 index 0000000..77a14bb --- /dev/null +++ b/src/components/message.ts @@ -0,0 +1,7 @@ +import { MessagePlugin } from "tdesign-vue-next"; + +type MessageType = "info" | "success" | "warning" | "error"; + +export async function showPlatformMessage(type: MessageType, content: string) { + await MessagePlugin[type](content); +} diff --git a/src/components/notify-editor/index.ts b/src/components/notify-editor/index.ts new file mode 100644 index 0000000..2a28533 --- /dev/null +++ b/src/components/notify-editor/index.ts @@ -0,0 +1,11 @@ +import view from "./index.vue"; +import { Toolkit } from "timi-web"; +import type { NotifyDetail } from "timi-web/editor"; + +export type NotifyEditorExpose = { + submit: () => Promise; + getPendingMediaCount: () => number; +}; + +export const NotifyEditor = Toolkit.withInstall(view); +export default NotifyEditor; diff --git a/src/components/notify-editor/index.vue b/src/components/notify-editor/index.vue new file mode 100644 index 0000000..da7d622 --- /dev/null +++ b/src/components/notify-editor/index.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/components/notify-view/index.ts b/src/components/notify-view/index.ts new file mode 100644 index 0000000..0bd6ef4 --- /dev/null +++ b/src/components/notify-view/index.ts @@ -0,0 +1,5 @@ +import view from "./index.vue"; +import { Toolkit } from "timi-web"; + +export const NotifyView = Toolkit.withInstall(view); +export default NotifyView; diff --git a/src/components/notify-view/index.vue b/src/components/notify-view/index.vue new file mode 100644 index 0000000..674ec41 --- /dev/null +++ b/src/components/notify-view/index.vue @@ -0,0 +1,32 @@ + + + diff --git a/src/components/tiptap-content.less b/src/components/tiptap-content.less new file mode 100644 index 0000000..73ffa63 --- /dev/null +++ b/src/components/tiptap-content.less @@ -0,0 +1,46 @@ +.tp-content-theme() { + color: var(--td-text-color-primary); + line-height: 1.6; + + p { + margin: 0 0 .75rem; + } + + p:empty:before { + content: "\00a0"; + } + + ul, + ol { + margin: 0 0 .75rem; + padding-left: 1.25rem; + } + + table { + width: 100%; + margin: .75rem 0; + table-layout: fixed; + border-collapse: collapse; + } + + th, + td { + border: 1px solid var(--td-component-border); + } + + th { + background: var(--td-bg-color-secondarycontainer); + } + + img, + video, + iframe { + margin: 0 auto; + max-width: 100%; + } +} + +.tp-content-body { + .tp-content-theme(); +} + diff --git a/src/components/tiptap-editor/TiptapCodeBlockButton.vue b/src/components/tiptap-editor/TiptapCodeBlockButton.vue new file mode 100644 index 0000000..10c4bae --- /dev/null +++ b/src/components/tiptap-editor/TiptapCodeBlockButton.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/components/tiptap-editor/TiptapIframeButton.vue b/src/components/tiptap-editor/TiptapIframeButton.vue new file mode 100644 index 0000000..bcf40ff --- /dev/null +++ b/src/components/tiptap-editor/TiptapIframeButton.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/src/components/tiptap-editor/TiptapLinkButton.vue b/src/components/tiptap-editor/TiptapLinkButton.vue new file mode 100644 index 0000000..8af2570 --- /dev/null +++ b/src/components/tiptap-editor/TiptapLinkButton.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/components/tiptap-editor/TiptapMediaButton.vue b/src/components/tiptap-editor/TiptapMediaButton.vue new file mode 100644 index 0000000..4a3217d --- /dev/null +++ b/src/components/tiptap-editor/TiptapMediaButton.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/src/components/tiptap-editor/TiptapPaddingButton.vue b/src/components/tiptap-editor/TiptapPaddingButton.vue new file mode 100644 index 0000000..0cc151c --- /dev/null +++ b/src/components/tiptap-editor/TiptapPaddingButton.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/src/components/tiptap-editor/TiptapTableButton.vue b/src/components/tiptap-editor/TiptapTableButton.vue new file mode 100644 index 0000000..47b1b5a --- /dev/null +++ b/src/components/tiptap-editor/TiptapTableButton.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/src/components/tiptap-editor/TiptapToolbar.vue b/src/components/tiptap-editor/TiptapToolbar.vue new file mode 100644 index 0000000..961176a --- /dev/null +++ b/src/components/tiptap-editor/TiptapToolbar.vue @@ -0,0 +1,429 @@ + + + + + diff --git a/src/components/tiptap-editor/index.ts b/src/components/tiptap-editor/index.ts new file mode 100644 index 0000000..5f44f8e --- /dev/null +++ b/src/components/tiptap-editor/index.ts @@ -0,0 +1,19 @@ +import view from "./index.vue"; +import { Toolkit } from "timi-web"; +import type { TiptapEditorInstance } from "timi-web/editor"; + +export * from "timi-web/editor"; +export type TiptapEditorExpose = { + submit: () => Promise; + getPendingMediaCount: () => number; + openSearch: (showReplace: boolean) => void; + closeSearch: () => void; + findNext: () => boolean; + findPrevious: () => boolean; + replaceCurrent: () => boolean; + replaceAll: () => number; + editor?: TiptapEditorInstance; +}; + +export const TiptapEditor = Toolkit.withInstall(view); +export default TiptapEditor; diff --git a/src/components/tiptap-editor/index.vue b/src/components/tiptap-editor/index.vue new file mode 100644 index 0000000..b9f2e5c --- /dev/null +++ b/src/components/tiptap-editor/index.vue @@ -0,0 +1,624 @@ + + + + + diff --git a/src/components/tiptap-view/index.ts b/src/components/tiptap-view/index.ts new file mode 100644 index 0000000..1c4cd1d --- /dev/null +++ b/src/components/tiptap-view/index.ts @@ -0,0 +1,5 @@ +import view from "./index.vue"; +import { Toolkit } from "timi-web"; + +export const TiptapView = Toolkit.withInstall(view); +export default TiptapView; diff --git a/src/components/tiptap-view/index.vue b/src/components/tiptap-view/index.vue new file mode 100644 index 0000000..5196979 --- /dev/null +++ b/src/components/tiptap-view/index.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/src/index.ts b/src/index.ts index 9fc4165..c0055ec 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,9 @@ import "./assets/style/tencent-cloud.less"; import "./assets/style/tencent-cloud-custom.less"; import { popupUserStore } from "./store/popupUser"; +import "./components/tiptap-content.less"; +import "timi-web/style.css"; +import "../../timi-web/src/components/prism-code-block.less"; export * from "./components"; diff --git a/tsconfig.json b/tsconfig.json index 4ff52e1..2a4c4ca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,9 @@ "@/*": [ "./examples/*" ], + "timi-web/editor": [ + "../timi-web/src/editor/index.ts" + ], "timi-tdesign-pc": [ "./src/index.ts" ] diff --git a/vite.config.ts b/vite.config.ts index fff1ece..653d21c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -20,6 +20,10 @@ const alias: Alias[] = [ find: "*", replacement: resolve("") }, + { + find: /^timi-web\/editor$/, + replacement: resolve(__dirname, "../timi-web/src/editor/index.ts") + }, { find: /^timi-tdesign-pc(\/(es|lib))?$/, replacement: resolve(__dirname, "./src/index.ts")