diff --git a/packages/editor/src/extensions/code-block/CodeBlockViewRenderer.vue b/packages/editor/src/extensions/code-block/CodeBlockViewRenderer.vue
index ad36351..eaa47ca 100644
--- a/packages/editor/src/extensions/code-block/CodeBlockViewRenderer.vue
+++ b/packages/editor/src/extensions/code-block/CodeBlockViewRenderer.vue
@@ -1,9 +1,20 @@
+
+
+
+
+
+
+
+
diff --git a/packages/editor/src/extensions/image/index.ts b/packages/editor/src/extensions/image/index.ts
new file mode 100644
index 0000000..145dc70
--- /dev/null
+++ b/packages/editor/src/extensions/image/index.ts
@@ -0,0 +1,59 @@
+import TiptapImage from "@tiptap/extension-image";
+import { VueNodeViewRenderer } from "@tiptap/vue-3";
+import ImageView from "./ImageView.vue";
+
+const Image = TiptapImage.extend({
+ inline() {
+ return true;
+ },
+
+ group() {
+ return "inline";
+ },
+
+ addAttributes() {
+ return {
+ ...this.parent?.(),
+ width: {
+ default: null,
+ parseHTML: (element) => {
+ const width =
+ element.style.width || element.getAttribute("width") || null;
+ return width == null ? null : parseInt(width, 10);
+ },
+ renderHTML: (attributes) => {
+ return {
+ width: attributes.width,
+ };
+ },
+ },
+ height: {
+ default: null,
+ parseHTML: (element) => {
+ const height =
+ element.style.height || element.getAttribute("height") || null;
+ return height == null ? null : parseInt(height, 10);
+ },
+ renderHTML: (attributes) => {
+ return {
+ height: attributes.height,
+ };
+ },
+ },
+ };
+ },
+
+ addNodeView() {
+ return VueNodeViewRenderer(ImageView);
+ },
+
+ parseHTML() {
+ return [
+ {
+ tag: "img[src]",
+ },
+ ];
+ },
+});
+
+export default Image;
diff --git a/packages/editor/src/extensions/index.ts b/packages/editor/src/extensions/index.ts
index 4ce515f..01afe0f 100644
--- a/packages/editor/src/extensions/index.ts
+++ b/packages/editor/src/extensions/index.ts
@@ -16,7 +16,7 @@ import ExtensionOrderedList from "@tiptap/extension-ordered-list";
import ExtensionParagraph from "@tiptap/extension-paragraph";
import ExtensionStrike from "@tiptap/extension-strike";
import ExtensionText from "@tiptap/extension-text";
-import ExtensionImage from "@tiptap/extension-image";
+import ExtensionImage from "./image";
import ExtensionTaskList from "@tiptap/extension-task-list";
import ExtensionTaskItem from "@tiptap/extension-task-item";
import ExtensionLink from "@tiptap/extension-link";
@@ -55,12 +55,7 @@ const allExtensions = [
ExtensionParagraph,
ExtensionStrike,
ExtensionText,
- ExtensionImage.configure({
- inline: true,
- HTMLAttributes: {
- loading: "lazy",
- },
- }),
+ ExtensionImage,
ExtensionTaskList,
ExtensionTaskItem,
ExtensionLink.configure({
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4e57010..7cb1974 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -105,6 +105,7 @@ importers:
'@tiptap/vue-3': 2.0.0-beta.202
'@types/katex': ^0.14.0
'@vue/compiler-sfc': ^3.2.45
+ '@vueuse/core': ^9.6.0
autoprefixer: ^10.4.13
floating-vue: 2.0.0-beta.20
katex: ^0.16.3
@@ -152,6 +153,7 @@ importers:
'@tiptap/extension-underline': 2.0.0-beta.202_fosglmwb3u6jhi6bbjmnlbdsbu
'@tiptap/suggestion': 2.0.0-beta.202_fosglmwb3u6jhi6bbjmnlbdsbu
'@tiptap/vue-3': 2.0.0-beta.202_fosglmwb3u6jhi6bbjmnlbdsbu
+ '@vueuse/core': 9.6.0
floating-vue: 2.0.0-beta.20
katex: 0.16.3
lowlight: 2.7.0
@@ -1309,6 +1311,10 @@ packages:
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
dev: false
+ /@types/web-bluetooth/0.0.16:
+ resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
+ dev: false
+
/@typescript-eslint/eslint-plugin/5.33.0_4ef6l6rno4vditvp6wd3bmzmmy:
resolution: {integrity: sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1686,6 +1692,31 @@ packages:
'@types/node': 18.11.9
dev: true
+ /@vueuse/core/9.6.0:
+ resolution: {integrity: sha512-qGUcjKQXHgN+jqXEgpeZGoxdCbIDCdVPz3QiF1uyecVGbMuM63o96I1GjYx5zskKgRI0FKSNsVWM7rwrRMTf6A==}
+ dependencies:
+ '@types/web-bluetooth': 0.0.16
+ '@vueuse/metadata': 9.6.0
+ '@vueuse/shared': 9.6.0
+ vue-demi: 0.13.6
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: false
+
+ /@vueuse/metadata/9.6.0:
+ resolution: {integrity: sha512-sIC8R+kWkIdpi5X2z2Gk8TRYzmczDwHRhEFfCu2P+XW2JdPoXrziqsGpDDsN7ykBx4ilwieS7JUIweVGhvZ93w==}
+ dev: false
+
+ /@vueuse/shared/9.6.0:
+ resolution: {integrity: sha512-/eDchxYYhkHnFyrb00t90UfjCx94kRHxc7J1GtBCqCG4HyPMX+krV9XJgVtWIsAMaxKVU4fC8NSUviG1JkwhUQ==}
+ dependencies:
+ vue-demi: 0.13.6
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: false
+
/abab/2.0.6:
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
dev: true
@@ -6011,6 +6042,19 @@ packages:
acorn-walk: 8.2.0
dev: true
+ /vue-demi/0.13.6:
+ resolution: {integrity: sha512-02NYpxgyGE2kKGegRPYlNQSL1UWfA/+JqvzhGCOYjhfbLWXU5QQX0+9pAm/R2sCOPKr5NBxVIab7fvFU0B1RxQ==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dev: false
+
/vue-demi/0.13.6_vue@3.2.45:
resolution: {integrity: sha512-02NYpxgyGE2kKGegRPYlNQSL1UWfA/+JqvzhGCOYjhfbLWXU5QQX0+9pAm/R2sCOPKr5NBxVIab7fvFU0B1RxQ==}
engines: {node: '>=12'}